/// <summary> /// Given a FaceDetails on given face of the cube, /// rotates the cube, and returns the new face and correctly oriented FaceDetails /// </summary> internal static (FaceDir, FaceDetails) ApplyRotator(FaceDir faceDir, FaceDetails faceDetails, MatrixInt3x3 rotator) { var rotatedFaceDirForward = rotator.Multiply(faceDir.Forward()); var rotatedFaceDirUp = rotator.Multiply(faceDir.Up()); var rotatedFaceDirRight = rotator.Multiply(Vector3.Cross(faceDir.Forward(), faceDir.Up())); var rotatedFaceDir = FromNormal(rotatedFaceDirForward); var trueUp = rotatedFaceDir.Up(); var trueForward = rotatedFaceDirForward; // = rotatedFaceDir.Forward(); var trueRight = Vector3.Cross(trueForward, trueUp); // Find the rotation that will map rotatedFaceDirUp to trueUp // and rotatedFaceDirRight to trueRight var dot = Vector3.Dot(rotatedFaceDirUp, trueUp); var cross = Vector3.Dot(rotatedFaceDirUp, trueRight); Rotation faceRot; if (dot == 1) { faceRot = new Rotation(); } else if (dot == -1) { faceRot = new Rotation(180); } else if (cross == 1) { faceRot = new Rotation(270); } else if (cross == -1) { faceRot = new Rotation(90); } else { throw new Exception(); } if (Vector3.Dot(Vector3.Cross(rotatedFaceDirForward, rotatedFaceDirUp), rotatedFaceDirRight) < 0) { faceRot = new Rotation(360 - faceRot.RotateCw, true); } var rotatedFaceDetails = faceDetails.RotateBy(faceRot); return(rotatedFaceDir, rotatedFaceDetails); }