// Helper method to prepend the inverse of Camera.Transform to the // the given viewMatrix. This is used by the various GetViewMatrix() // and RayFromViewportPoint implementations. // // Transforming the camera is equivalent to applying the inverse // transform to the scene. We invert the transform and prepend it to // the result of viewMatrix: // // -1 // viewMatrix = Camera.Transform x viewMatrix // // If the matrix is non-invertable we set the viewMatrix to NaNs which // will result in nothing being rendered. This is the correct behavior // since the near and far planes will have collapsed onto each other. internal static void PrependInverseTransform(Matrix3D matrix, ref Matrix3D viewMatrix) { if (!matrix.InvertCore()) { // If the matrix is non-invertable we return a NaN matrix. viewMatrix = new Matrix3D( double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN); } else { viewMatrix.Prepend(matrix); } }
public static void Transform(Matrix3D modelMatrix, ref Point3D origin, ref Vector3D direction, out bool isRay) { if (modelMatrix.InvertCore()) { Point4D o = new Point4D(origin.X,origin.Y,origin.Z,1); Point4D d = new Point4D(direction.X,direction.Y,direction.Z,0); modelMatrix.MultiplyPoint(ref o); modelMatrix.MultiplyPoint(ref d); if (o.W == 1 && d.W == 0) { // Affine transformation origin = new Point3D(o.X, o.Y, o.Z); direction = new Vector3D(d.X, d.Y, d.Z); isRay = true; } else { // Non-affine transformation (likely projection) // Form 4x2 matrix with two points on line in two columns. double[,] linepoints = new double[,]{{o.X,d.X},{o.Y,d.Y},{o.Z,d.Z},{o.W,d.W}}; ColumnsToAffinePointVector(linepoints,0,1,out origin, out direction); isRay = false; } } else { TransformSingular(ref modelMatrix, ref origin, ref direction); isRay = false; } }