/// <summary> /// Compute the product of two Matrix3x3. /// </summary> /// <param name="result"> /// A <see cref="MatrixDouble3x3"/> that stores the matrix multiplication result. /// </param> /// <param name="m"> /// A <see cref="MatrixDouble3x3"/> that specify the left multiplication operand. /// </param> /// <param name="n"> /// A <see cref="MatrixDouble3x3"/> that specify the right multiplication operand. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="result"/>, <paramref name="m"/> or <paramref name="n"/> is null. /// </exception> private static void ComputeMatrixProduct(MatrixDouble3x3 result, MatrixDouble3x3 m, MatrixDouble3x3 n) { if (result == null) { throw new ArgumentNullException("result"); } if (m == null) { throw new ArgumentNullException("m"); } if (n == null) { throw new ArgumentNullException("n"); } unsafe { fixed(double *prodFix = result.MatrixBuffer) fixed(double *pm = m.MatrixBuffer) fixed(double *pn = n.MatrixBuffer) { prodFix[0] = pm[0] * pn[0] + pm[3] * pn[1] + pm[6] * pn[2]; prodFix[3] = pm[0] * pn[3] + pm[3] * pn[4] + pm[6] * pn[5]; prodFix[6] = pm[0] * pn[6] + pm[3] * pn[7] + pm[6] * pn[8]; prodFix[1] = pm[1] * pn[0] + pm[4] * pn[1] + pm[7] * pn[2]; prodFix[4] = pm[1] * pn[3] + pm[4] * pn[4] + pm[7] * pn[5]; prodFix[7] = pm[1] * pn[6] + pm[4] * pn[7] + pm[7] * pn[8]; prodFix[2] = pm[2] * pn[0] + pm[5] * pn[1] + pm[8] * pn[2]; prodFix[5] = pm[2] * pn[3] + pm[5] * pn[4] + pm[8] * pn[5]; prodFix[8] = pm[2] * pn[6] + pm[5] * pn[7] + pm[8] * pn[8]; } } }
/// <summary> /// Compute the product of two Matrix4x4. /// </summary> /// <param name="m1"> /// A <see cref="MatrixDouble3x3"/> that specify the left multiplication operand. /// </param> /// <param name="m2"> /// A <see cref="MatrixDouble3x3"/> that specify the right multiplication operand. /// </param> /// <returns> /// A <see cref="MatrixDouble3x3"/> 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> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="m1"/> or <paramref name="m2"/> is null. /// </exception> public static MatrixDouble3x3 operator *(MatrixDouble3x3 m1, MatrixDouble3x3 m2) { // Allocate product matrix MatrixDouble3x3 prod = new MatrixDouble3x3(); // COmpute product ComputeMatrixProduct(prod, m1, m2); return(prod); }
/// <summary> /// Inverse Matrix of this Matrix. /// </summary> /// <returns> /// A <see cref="Matrix"/> representing the inverse matrix of this Matrix. /// </returns> /// <exception cref="InvalidOperationException"> /// The exception is thrown if this Matrix is not square, or it's determinant is 0.0 (i.e. non-invertible). /// </exception> public new MatrixDouble3x3 GetInverseMatrix() { // | a b c | // m = | d e f | // | g h k | // // | A B C |(T) // m^-1 = | D E F | * (1 / det(m)) // | G H K | // // A = +(e * k - f * h) = (e * k - f * h) // B = -(d * k - f * g) = (f * g - d * k) // C = +(d * h - e * g) = (d * h - e * g) // D = -(b * k - c * h) = (c * h - b * k) // E = +(a * k - c * g) = (a * k - c * g) // F = -(a * h - b * g) = (b * g - a * h) // G = +(b * f - c * e) = (b * f - c * e) // H = -(a * f - c * d) = (c * d - a * f) // K = +(a * e - b * d) = (a * e - b * d) double determinant = GetDeterminant(); if (Math.Abs(determinant) < Double.Epsilon) { throw new InvalidOperationException("non-invertible"); } MatrixDouble3x3 inverse = new MatrixDouble3x3(); double inv = 1.0 / determinant; unsafe { fixed(double *m = MatrixBuffer) { fixed(double *mi = inverse.MatrixBuffer) { double a = m[0], b = m[3], c = m[6]; double d = m[1], e = m[4], f = m[7]; double g = m[2], h = m[5], k = m[8]; mi[0] = (e * k - f * h) * inv; mi[1] = (f * g - d * k) * inv; mi[2] = (d * h - e * g) * inv; mi[3] = (c * h - b * k) * inv; mi[4] = (a * k - c * g) * inv; mi[5] = (b * g - a * h) * inv; mi[6] = (b * f - c * e) * inv; mi[7] = (c * d - a * f) * inv; mi[8] = (a * e - b * d) * inv; } } } return(inverse); }
/// <summary> /// Compute the transpose of this Matrix3x3. /// </summary> /// <returns> /// A <see cref="MatrixDouble3x3"/> which hold the transpose of this Matrix3x3. /// </returns> public new MatrixDouble3x3 Transpose() { MatrixDouble3x3 t = new MatrixDouble3x3(); // Transpose matrix for (uint c = 0; c < 3; c++) { for (uint r = 0; r < 3; r++) { t[r, c] = this[c, r]; } } return(t); }
/// <summary> /// Compute the product of two Matrix3x3. /// </summary> /// <param name="result"> /// A <see cref="MatrixDouble3x3"/> that stores the matrix multiplication result. /// </param> /// <param name="m"> /// A <see cref="MatrixDouble3x3"/> that specify the left multiplication operand. /// </param> /// <param name="n"> /// A <see cref="MatrixDouble3x3"/> that specify the right multiplication operand. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="result"/>, <paramref name="m"/> or <paramref name="n"/> is null. /// </exception> private static void ComputeMatrixProduct(MatrixDouble3x3 result, MatrixDouble3x3 m, MatrixDouble3x3 n) { unsafe { fixed(double *prodFix = result.MatrixBuffer) fixed(double *pm = m.MatrixBuffer) fixed(double *pn = n.MatrixBuffer) { prodFix[0] = pm[0] * pn[0] + pm[3] * pn[1] + pm[6] * pn[2]; prodFix[3] = pm[0] * pn[3] + pm[3] * pn[4] + pm[6] * pn[5]; prodFix[6] = pm[0] * pn[6] + pm[3] * pn[7] + pm[6] * pn[8]; prodFix[1] = pm[1] * pn[0] + pm[4] * pn[1] + pm[7] * pn[2]; prodFix[4] = pm[1] * pn[3] + pm[4] * pn[4] + pm[7] * pn[5]; prodFix[7] = pm[1] * pn[6] + pm[4] * pn[7] + pm[7] * pn[8]; prodFix[2] = pm[2] * pn[0] + pm[5] * pn[1] + pm[8] * pn[2]; prodFix[5] = pm[2] * pn[3] + pm[5] * pn[4] + pm[8] * pn[5]; prodFix[8] = pm[2] * pn[6] + pm[5] * pn[7] + pm[8] * pn[8]; } } }
/// <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="Matrix3x3"/> holding the uniform variabile data. /// </param> public void SetVariantUniform(GraphicsContext ctx, string uniformName, MatrixDouble3x3 m) { if (ctx == null) { throw new ArgumentNullException("ctx"); } UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat3x3: SetUniform(ctx, uniformName, (Matrix3x3)m); break; case ShaderUniformType.DoubleMat3x3: SetUniform(ctx, uniformName, m); break; default: throw new ShaderException("unable to set double-precision floating-point matrix 3x3 data to uniform of type {0}", uniform.UniformType); } }
/// <summary> /// Construct a matrix which is a copy of another matrix. /// </summary> /// <param name="m"> /// A <see cref="MatrixDouble3x3"/> to be copied. /// </param> /// <exception cref="ArgumentNullException"> /// Exception throw if <paramref name="m"/> is null. /// </exception> public MatrixDouble3x3(MatrixDouble3x3 m) : base(m) { }
/// <summary> /// Inverse Matrix of this Matrix. /// </summary> /// <returns> /// A <see cref="Matrix"/> representing the inverse matrix of this Matrix. /// </returns> /// <exception cref="InvalidOperationException"> /// The exception is thrown if this Matrix is not square, or it's determinant is 0.0 (i.e. non-invertible). /// </exception> public new MatrixDouble3x3 GetInverseMatrix() { // | a b c | // m = | d e f | // | g h k | // // | A B C |(T) // m^-1 = | D E F | * (1 / det(m)) // | G H K | // // A = +(e * k - f * h) = (e * k - f * h) // B = -(d * k - f * g) = (f * g - d * k) // C = +(d * h - e * g) = (d * h - e * g) // D = -(b * k - c * h) = (c * h - b * k) // E = +(a * k - c * g) = (a * k - c * g) // F = -(a * h - b * g) = (b * g - a * h) // G = +(b * f - c * e) = (b * f - c * e) // H = -(a * f - c * d) = (c * d - a * f) // K = +(a * e - b * d) = (a * e - b * d) double determinant = GetDeterminant(); if (Math.Abs(determinant) < Double.Epsilon) throw new InvalidOperationException("non-invertible"); MatrixDouble3x3 inverse = new MatrixDouble3x3(); double inv = 1.0 / determinant; unsafe { fixed (double* m = MatrixBuffer) { fixed (double* mi = inverse.MatrixBuffer) { double a = m[0], b = m[3], c = m[6]; double d = m[1], e = m[4], f = m[7]; double g = m[2], h = m[5], k = m[8]; mi[0] = (e * k - f * h) * inv; mi[1] = (f * g - d * k) * inv; mi[2] = (d * h - e * g) * inv; mi[3] = (c * h - b * k) * inv; mi[4] = (a * k - c * g) * inv; mi[5] = (b * g - a * h) * inv; mi[6] = (b * f - c * e) * inv; mi[7] = (c * d - a * f) * inv; mi[8] = (a * e - b * d) * inv; } } } return (inverse); }
/// <summary> /// Compute the transpose of this Matrix3x3. /// </summary> /// <returns> /// A <see cref="MatrixDouble3x3"/> which hold the transpose of this Matrix3x3. /// </returns> public new MatrixDouble3x3 Transpose() { MatrixDouble3x3 t = new MatrixDouble3x3(); // Transpose matrix for (uint c = 0; c < 3; c++) for (uint r = 0; r < 3; r++) t[r, c] = this[c, r]; return (t); }
/// <summary> /// Compute the product of two Matrix3x3. /// </summary> /// <param name="result"> /// A <see cref="MatrixDouble3x3"/> that stores the matrix multiplication result. /// </param> /// <param name="m"> /// A <see cref="MatrixDouble3x3"/> that specify the left multiplication operand. /// </param> /// <param name="n"> /// A <see cref="MatrixDouble3x3"/> that specify the right multiplication operand. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="result"/>, <paramref name="m"/> or <paramref name="n"/> is null. /// </exception> private static void ComputeMatrixProduct(MatrixDouble3x3 result, MatrixDouble3x3 m, MatrixDouble3x3 n) { if (result == null) throw new ArgumentNullException("result"); if (m == null) throw new ArgumentNullException("m"); if (n == null) throw new ArgumentNullException("n"); unsafe { fixed (double* prodFix = result.MatrixBuffer) fixed (double* pm = m.MatrixBuffer) fixed (double* pn = n.MatrixBuffer) { prodFix[0] = pm[0] * pn[0] + pm[3] * pn[1] + pm[6] * pn[2]; prodFix[3] = pm[0] * pn[3] + pm[3] * pn[4] + pm[6] * pn[5]; prodFix[6] = pm[0] * pn[6] + pm[3] * pn[7] + pm[6] * pn[8]; prodFix[1] = pm[1] * pn[0] + pm[4] * pn[1] + pm[7] * pn[2]; prodFix[4] = pm[1] * pn[3] + pm[4] * pn[4] + pm[7] * pn[5]; prodFix[7] = pm[1] * pn[6] + pm[4] * pn[7] + pm[7] * pn[8]; prodFix[2] = pm[2] * pn[0] + pm[5] * pn[1] + pm[8] * pn[2]; prodFix[5] = pm[2] * pn[3] + pm[5] * pn[4] + pm[8] * pn[5]; prodFix[8] = pm[2] * pn[6] + pm[5] * pn[7] + pm[8] * pn[8]; } } }
/// <summary> /// Compute the product of two Matrix4x4. /// </summary> /// <param name="m1"> /// A <see cref="MatrixDouble3x3"/> that specify the left multiplication operand. /// </param> /// <param name="m2"> /// A <see cref="MatrixDouble3x3"/> that specify the right multiplication operand. /// </param> /// <returns> /// A <see cref="MatrixDouble3x3"/> 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> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="m1"/> or <paramref name="m2"/> is null. /// </exception> public static MatrixDouble3x3 operator *(MatrixDouble3x3 m1, MatrixDouble3x3 m2) { // Allocate product matrix MatrixDouble3x3 prod = new MatrixDouble3x3(); // COmpute product ComputeMatrixProduct(prod, m1, m2); return (prod); }
/// <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="Matrix3x3"/> holding the uniform variabile data. /// </param> public void SetVariantUniform(GraphicsContext ctx, string uniformName, MatrixDouble3x3 m) { if (ctx == null) throw new ArgumentNullException("ctx"); UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat3x3: SetUniform(ctx, uniformName, (Matrix3x3)m); break; case ShaderUniformType.DoubleMat3x3: SetUniform(ctx, uniformName, m); break; default: throw new ShaderException("unable to set double-precision floating-point matrix 3x3 data to uniform of type {0}", uniform.UniformType); } }
/// <summary> /// Set uniform state variable (dmat3 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="MatrixDouble3x3"/> holding the uniform variabile data. /// </param> public void SetUniform(GraphicsContext ctx, string uniformName, MatrixDouble3x3 m) { if (ctx == null) throw new ArgumentNullException("ctx"); UniformBinding uniform = GetUniform(uniformName); CheckProgramBinding(); CheckUniformType(uniform, Gl.DOUBLE_MAT3); // Set uniform value Gl.UniformMatrix3(uniform.Location, 1, false, m.MatrixBuffer); }