/// <summary> /// Construct a complement matrix of a <see cref="Matrix4x4"/>. /// </summary> /// <param name="m"> /// A <see cref="Matrix4x4"/> on which is computed the complement matrix. /// </param> /// <param name="c"> /// A <see cref="UInt32"/> that specify the index of the column that is excluded for /// computing the complement matrix. /// </param> /// <param name="r"> /// A <see cref="UInt32"/> that specify the index of the row that is excluded for /// computing the complement matrix. /// </param> /// <exception cref="ArgumentNullException"> /// Exception throw if <paramref name="m"/> is null. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// Exception throw if <paramref name="c"/> is greater or equal to <paramref name="m"/> column count, /// or if <paramref name="r"/> is greater or equal to <paramref name="m"/> row count. /// </exception> public Matrix3x3(Matrix4x4 m, uint c, uint r) : base(m, c, r) { }
/// <summary> /// Construct ModelMatrix from a <see cref="Matrix4x4"/>. /// </summary> /// <param name="m"> /// A <see cref="Matrix4x4"/> to be copied. /// </param> public ModelMatrix(Matrix4x4 m) : base(m) { }
/// <summary> /// Sets the uniform value. /// </summary> /// <param name="name">The uniform name.</param> /// <param name="value">The uniform value.</param> /// <returns>Reference to self for method call chaining.</returns> IShaderUniform IShaderUniform.SetUniform(string name, Matrix4x4 value) { int location; if (this.uniformLocations.TryGetValue(name, out location)) { gl.UniformMatrix4x4(location, 1, false, ref value.M11); } return this; }
/// <summary> /// Sets the model matrix. /// </summary> /// <param name="transformation">The transformation matrix.</param> public static void Transform(Matrix4x4 transformation) { modelMatrix = transformation; modelViewMatrix = transformation * viewMatrix; gl.LoadMatrix(ref modelViewMatrix.M11); }
/// <summary> /// Saves the current model matrix and applies a transformation to it. /// </summary> /// <param name="transformation">The transformation matrix.</param> public static void PushTransform(Matrix4x4 transformation) { PushTransform(); Transform(transformation * modelMatrix); }
/// <summary> /// Matrix copy constructor. /// </summary> /// <param name="m"> /// A <see cref="Matrix"/> /// </param> public Matrix4x4(Matrix4x4 m) : base(m) { }
/// <summary> /// Configures the view projection and transformation. /// </summary> /// <param name="projection">The view projection.</param> /// <param name="transformation">The view transformation.</param> public static void Camera(Projection projection, Matrix4x4 transformation) { if (Width > 0 && Height > 0 && projection != null) { Aspect = (float)Width / (float)Height; MinimumDepth = projection.MinimumDepth; MaximumDepth = projection.MaximumDepth; projectionMatrix = projection.ToMatrix(Width, Height); } else { Aspect = 1; MinimumDepth = -1; MaximumDepth = +1; projectionMatrix = Matrix4x4.Identity; } modelMatrix = Matrix4x4.Identity; viewMatrix = transformation; modelViewMatrix = transformation; modelMatrixStack.Clear(); var m = viewMatrix * projectionMatrix; ViewClipPlanes[0] = Plane.Normalize(new Plane(m.M14 - m.M11, m.M24 - m.M21, m.M34 - m.M31, m.M44 - m.M41)); // right ViewClipPlanes[1] = Plane.Normalize(new Plane(m.M14 + m.M11, m.M24 + m.M21, m.M34 + m.M31, m.M44 + m.M41)); // left ViewClipPlanes[2] = Plane.Normalize(new Plane(m.M14 - m.M12, m.M24 - m.M22, m.M34 - m.M32, m.M44 - m.M42)); // top ViewClipPlanes[3] = Plane.Normalize(new Plane(m.M14 + m.M12, m.M24 + m.M22, m.M34 + m.M32, m.M44 + m.M42)); // bottom ViewClipPlanes[4] = Plane.Normalize(new Plane(m.M14 - m.M13, m.M24 - m.M23, m.M34 - m.M33, m.M44 - m.M43)); // far ViewClipPlanes[5] = Plane.Normalize(new Plane(m.M14 + m.M13, m.M24 + m.M23, m.M34 + m.M33, m.M44 + m.M43)); // near gl.ActiveTexture(GL.TEXTURE0); gl.MatrixMode(GL.TEXTURE); gl.LoadMatrix(ref viewMatrix.M11); gl.MatrixMode(GL.PROJECTION); gl.LoadMatrix(ref projectionMatrix.M11); gl.MatrixMode(GL.MODELVIEW); gl.LoadMatrix(ref modelViewMatrix.M11); }
/// <summary> /// Compute the transpose of this Matrix4x4. /// </summary> /// <returns> /// A <see cref="Matrix4x4"/> which hold the transpose of this Matrix4x4. /// </returns> public new Matrix4x4 Transpose() { Matrix4x4 transpose = new Matrix4x4(); // Transpose matrix for (uint c = 0; c < 4; c++) for (uint r = 0; r < 4; r++) transpose[r, c] = this[c, r]; return (transpose); }
/// <summary> /// /// </summary> /// <param name="matrices"></param> /// <returns></returns> public static Matrix4x4 Concatenate(params Matrix4x4[] matrices) { if (matrices.Length == 0) throw new ArgumentNullException("matrices", "no matric chain"); Matrix4x4 m = new Matrix4x4(); m.SetIdentity(); unsafe { if (SimdLibrary.Matrix4x4_Concatenate != null) { List<GCHandle> gcHandles = new List<GCHandle>(); try { float*[] matrixChain = new float*[matrices.Length + 1]; GCHandle matrixData = GCHandle.Alloc(m.MatrixBuffer, GCHandleType.Pinned); gcHandles.Add(matrixData); matrixChain[0] = (float*)matrixData.AddrOfPinnedObject().ToPointer(); for (int i = 0; i < matrices.Length; i++) { matrixData = GCHandle.Alloc(matrices[i].MatrixBuffer, GCHandleType.Pinned); gcHandles.Add(matrixData); matrixChain[i + 1] = (float*)matrixData.AddrOfPinnedObject().ToPointer(); } SimdLibrary.Matrix4x4_Concatenate(matrixChain, (uint)matrixChain.Length); } finally { foreach (GCHandle gcHandle in gcHandles) gcHandle.Free(); } } else { foreach (Matrix4x4 matrix in matrices) m = m * matrix; } } return (m); }
/// <summary> /// Rotate a Matrix4x4 in three-dimensional space using Quaternion. /// </summary> /// <param name="m"></param> /// <param name="q"></param> /// <returns></returns> public static Matrix4x4 operator *(Matrix4x4 m, Quaternion q) { Matrix4x4 prod = new Matrix4x4(); // COmpute product ComputeMatrixProduct(prod, m, (Matrix4x4) q); return (prod); }
/// <summary> /// Compute the product of Matrix4x4 by MatrixDouble4x4. /// </summary> /// <param name="result"> /// A <see cref="Matrix4x4"/> that stores the matrix multiplication result. /// </param> /// <param name="m"> /// A <see cref="Matrix4x4"/> that specifies the left multiplication operand. /// </param> /// <param name="n"> /// A <see cref="MatrixDouble4x4"/> that specifies the right multiplication operand. /// </param> /// <remarks> /// If you to store the result in a <see cref="MatrixDouble4x4"/>, use the <see cref="MatrixDouble4x4.ComputeMatrixProduct(MatrixDouble4x4,MatrixDouble4x4,Matrix4x4)"/>. /// </remarks> protected static void ComputeMatrixProduct(Matrix4x4 result, Matrix4x4 m, MatrixDouble4x4 n) { if (result == null) throw new ArgumentNullException("result"); if (m == null) throw new ArgumentNullException("m"); if (n == null) throw new ArgumentNullException("n"); unsafe { fixed (float* prodFix = result.MatrixBuffer) fixed (float* pm = m.MatrixBuffer) fixed (double* pn = n.MatrixBuffer) { prodFix[0x0] = (float)(pm[0x0]*pn[0x0] + pm[0x4]*pn[0x1] + pm[0x8]*pn[0x2] + pm[0xC]*pn[0x3]); prodFix[0x4] = (float)(pm[0x0]*pn[0x4] + pm[0x4]*pn[0x5] + pm[0x8]*pn[0x6] + pm[0xC]*pn[0x7]); prodFix[0x8] = (float)(pm[0x0]*pn[0x8] + pm[0x4]*pn[0x9] + pm[0x8]*pn[0xA] + pm[0xC]*pn[0xB]); prodFix[0xC] = (float)(pm[0x0]*pn[0xC] + pm[0x4]*pn[0xD] + pm[0x8]*pn[0xE] + pm[0xC]*pn[0xF]); prodFix[0x1] = (float)(pm[0x1]*pn[0x0] + pm[0x5]*pn[0x1] + pm[0x9]*pn[0x2] + pm[0xD]*pn[0x3]); prodFix[0x5] = (float)(pm[0x1]*pn[0x4] + pm[0x5]*pn[0x5] + pm[0x9]*pn[0x6] + pm[0xD]*pn[0x7]); prodFix[0x9] = (float)(pm[0x1]*pn[0x8] + pm[0x5]*pn[0x9] + pm[0x9]*pn[0xA] + pm[0xD]*pn[0xB]); prodFix[0xD] = (float)(pm[0x1]*pn[0xC] + pm[0x5]*pn[0xD] + pm[0x9]*pn[0xE] + pm[0xD]*pn[0xF]); prodFix[0x2] = (float)(pm[0x2]*pn[0x0] + pm[0x6]*pn[0x1] + pm[0xA]*pn[0x2] + pm[0xE]*pn[0x3]); prodFix[0x6] = (float)(pm[0x2]*pn[0x4] + pm[0x6]*pn[0x5] + pm[0xA]*pn[0x6] + pm[0xE]*pn[0x7]); prodFix[0xA] = (float)(pm[0x2]*pn[0x8] + pm[0x6]*pn[0x9] + pm[0xA]*pn[0xA] + pm[0xE]*pn[0xB]); prodFix[0xE] = (float)(pm[0x2]*pn[0xC] + pm[0x6]*pn[0xD] + pm[0xA]*pn[0xE] + pm[0xE]*pn[0xF]); prodFix[0x3] = (float)(pm[0x3]*pn[0x0] + pm[0x7]*pn[0x1] + pm[0xB]*pn[0x2] + pm[0xF]*pn[0x3]); prodFix[0x7] = (float)(pm[0x3]*pn[0x4] + pm[0x7]*pn[0x5] + pm[0xB]*pn[0x6] + pm[0xF]*pn[0x7]); prodFix[0xB] = (float)(pm[0x3]*pn[0x8] + pm[0x7]*pn[0x9] + pm[0xB]*pn[0xA] + pm[0xF]*pn[0xB]); prodFix[0xF] = (float)(pm[0x3]*pn[0xC] + pm[0x7]*pn[0xD] + pm[0xB]*pn[0xE] + pm[0xF]*pn[0xF]); } } }
/// <summary> /// Compute the product of two Matrix4x4. /// </summary> /// <param name="m1"> /// A <see cref="Matrix4x4"/> that specifies the left multiplication operand. /// </param> /// <param name="m2"> /// A <see cref="Matrix4x4"/> that specifies the right multiplication operand. /// </param> /// <returns> /// A <see cref="Matrix4x4"/> resulting from the product of the matrix <paramref name="m1"/> and /// the matrix <paramref name="m2"/>. This operator is used to concatenate successive transformations. /// </returns> public static Matrix4x4 operator *(Matrix4x4 m1, Matrix4x4 m2) { Matrix4x4 prod = new Matrix4x4(); // Compute product ComputeMatrixProduct(prod, m1, m2); return (prod); }
/// <summary> /// Convert this structure to a <see cref="Matrix"/> instance. /// </summary> /// <returns> /// It returns a <see cref="Matrix"/> instance equivalent to this ISingleMatrix. /// </returns> public Matrix ToMatrix() { Matrix matrix = new Matrix4x4(); for (uint r = 0; r < 4; r++) matrix[0, r] = Column0[r]; for (uint r = 0; r < 4; r++) matrix[1, r] = Column1[r]; for (uint r = 0; r < 4; r++) matrix[2, r] = Column2[r]; for (uint r = 0; r < 4; r++) matrix[3, r] = Column3[r]; return (matrix); }
/// <summary> /// Get the infinity projection. /// </summary> /// <param name="epsilon"> /// A <see cref="Single"/> that specify a positive /// </param> public Matrix4x4 GetInfinityProjection(float epsilon) { if (epsilon < 0.0f) throw new ArgumentException("less than zero", "epsilon"); Matrix4x4 infinityMatrix = new Matrix4x4(this); infinityMatrix[2, 2] = -1.0f; infinityMatrix[2, 3] = epsilon - 1.0f; infinityMatrix[3, 2] = (epsilon - 2.0f) * Near; return (infinityMatrix); }
/// <summary> /// Set uniform state variable (variant type). /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for operations. /// </param> /// <param name="uniformName"> /// A <see cref="String"/> that specify the variable name in the shader source. /// </param> /// <param name="m"> /// A <see cref="Matrix4x4"/> holding the uniform variabile data. /// </param> public void SetVariantUniform(GraphicsContext ctx, string uniformName, Matrix4x4 m) { if (ctx == null) throw new ArgumentNullException("ctx"); UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat4x4: SetUniform(ctx, uniformName, m); break; case ShaderUniformType.DoubleMat4x4: SetUniform(ctx, uniformName, (MatrixDouble4x4)m); break; default: throw new ShaderException("unable to set single-precision floating-point matrix 4x4 data to uniform of type {0}", uniform.UniformType); } }
/// <summary> /// Set uniform state variable (mat4 variable). /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for operations. /// </param> /// <param name="uniformName"> /// A <see cref="String"/> that specify the variable name in the shader source. /// </param> /// <param name="m"> /// A <see cref="Matrix4x4"/> holding the uniform variabile data. /// </param> public void SetUniform(GraphicsContext ctx, string uniformName, Matrix4x4 m) { if (ctx == null) throw new ArgumentNullException("ctx"); if (m == null) throw new ArgumentNullException("m"); UniformBinding uniform = GetUniform(uniformName); CheckProgramBinding(); CheckUniformType(uniform, Gl.FLOAT_MAT4); // Set uniform value Gl.UniformMatrix4(uniform.Location, 1, false, m.MatrixBuffer); }