public static GLTK.Matrix Short3CoordToRotationMatrix(Chunks.Short3Coord xiCoord) { GLTK.Matrix lRotation = GLTK.Matrix.Rotation(-xiCoord.Z / 1024.0 * Math.PI / 2.0, GLTK.Vector.ZAxis); lRotation *= GLTK.Matrix.Rotation(-xiCoord.Y / 1024.0 * Math.PI / 2.0, GLTK.Vector.YAxis); lRotation *= GLTK.Matrix.Rotation(-xiCoord.X / 1024.0 * Math.PI / 2.0, GLTK.Vector.XAxis); return(lRotation); }
/// <summary> /// Converts a GLTK rotation matrix into the MMs representation of a rotation. /// /// The input matrix must be rotation-only, otherwise the output of this method /// is not defined. /// </summary> public static Chunks.Short3Coord RotationMatrixToShort3Coord(GLTK.Matrix xiRotation) { // Algorithm is as follows: // // There are only two degrees of freedom, so one of the coordinates in the // vector is redundant. Therefore we fix one of the coordinates at 0 and // solve for the other 2. // // * First identify the axis that moves the furthest under the rotation; // this will be the fixed coordinate i.e. we'll rotate about the other // two. // * Next see what effect the rotation has on the axis that moves furthest; // since rotations are defined uniquely by their action on a single point // on the unit ball (apart from the poles) we just need to solve the // simultaneous equations generated by applying rotations of theta and phi // around the two non-fixed axis to this vector. Note: it is sufficient // to solve only two of the three equations as the third coordinate of the // vector is determined by the other two. // see what effect the rotation has on the x and y axes GLTK.Vector lNewXAxis = xiRotation * GLTK.Vector.XAxis; GLTK.Vector lNewYAxis = xiRotation * GLTK.Vector.YAxis; GLTK.Vector lNewZAxis = xiRotation * GLTK.Vector.ZAxis; double lXdist = Math.Abs(lNewXAxis * GLTK.Vector.XAxis); double lYdist = Math.Abs(lNewYAxis * GLTK.Vector.YAxis); double lZdist = Math.Abs(lNewZAxis * GLTK.Vector.ZAxis); if (lXdist < lYdist && lXdist < lZdist) { // x axis has moved the furthest - use (0, y, z) format // rotate about z by theta first, then y by phi // need to solve cos(theta)*cos(phi) = newx.x; sin(theta) = newx.y double lTheta = Math.Asin(-lNewXAxis.y); // check which of the possible values for theta is correct if (lNewXAxis.x < 0) { lTheta = Math.PI - lTheta; } double lPhi = Math.Acos(lNewXAxis.x / Math.Cos(lTheta)); // check which of the possible values for phi is correct if (lNewXAxis.z < 0) { lPhi = -lPhi; } return(new Chunks.Short3Coord( 0, (short)((lPhi / Math.PI) * 2 * 1024), (short)((lTheta / Math.PI) * 2 * 1024))); } else if (lYdist < lZdist) { // y axis has moved the furthest - use (x, 0, z) format // rotate about z by theta first, then x by phi // need to solve -sin(theta) = newy.x; cos(theta)cos(phi) = newy.y double lTheta = Math.Asin(lNewYAxis.x); // check which of the possible values for theta is correct if (lNewYAxis.y < 0) { lTheta = Math.PI - lTheta; } double lPhi = Math.Acos(lNewYAxis.y / Math.Cos(lTheta)); // check which of the possible values for phi is correct if (lNewYAxis.z > 0) { lPhi = -lPhi; } return(new Chunks.Short3Coord( (short)((lPhi / Math.PI) * 2 * 1024), 0, (short)((lTheta / Math.PI) * 2 * 1024))); } else { // z axis has moved the furthest - use (x, y, 0) format // rotate about y by theta first, then x by phi // need to solve sin(theta) = newz.x; cos(phi)cos(theta) = newz.z double lTheta = Math.Asin(lNewZAxis.x); // check which of the possible values for theta is correct if (lNewZAxis.z < 0) { lTheta = Math.PI - lTheta; } double lPhi = Math.Acos(lNewZAxis.z / Math.Cos(lTheta)); // check which of the possible values for phi is correct if (lNewZAxis.y < 0) { lPhi = -lPhi; } return(new Chunks.Short3Coord( (short)((lPhi / Math.PI) * 2 * 1024), (short)((lTheta / Math.PI) * 2 * 1024), 0)); } }