/// <summary> /// Construct a matrix which is a copy of another matrix. /// </summary> /// <param name="m"> /// A <see cref="Matrix3x3"/> to be copied. /// </param> /// <exception cref="ArgumentNullException"> /// Exception throw if <paramref name="m"/> is null. /// </exception> public Matrix3x3(Matrix3x3 m) : base(m) { }
/// <summary> /// Compute the transpose of this Matrix3x3. /// </summary> /// <returns> /// A <see cref="Matrix3x3"/> which hold the transpose of this Matrix3x3. /// </returns> public new Matrix3x3 Transpose() { Matrix3x3 t = new Matrix3x3(); // 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> /// 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 Matrix3x3 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) float determinant = GetDeterminant(); if (Math.Abs(determinant) < Single.Epsilon) throw new InvalidOperationException("non-invertible"); Matrix3x3 inverse = new Matrix3x3(); float inv = 1.0f / determinant; unsafe { fixed (float* m = MatrixBuffer) { fixed (float* mi = inverse.MatrixBuffer) { float a = m[0], b = m[3], c = m[6]; float d = m[1], e = m[4], f = m[7]; float 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 product of two Matrix3x3. /// </summary> /// <param name="result"> /// A <see cref="Matrix3x3"/> that stores the matrix multiplication result. /// </param> /// <param name="m"> /// A <see cref="Matrix3x3"/> that specify the left multiplication operand. /// </param> /// <param name="n"> /// A <see cref="Matrix3x3"/> 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(Matrix3x3 result, Matrix3x3 m, Matrix3x3 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 (float* 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="Matrix3x3"/> that specify the left multiplication operand. /// </param> /// <param name="m2"> /// A <see cref="Matrix3x3"/> that specify the right multiplication operand. /// </param> /// <returns> /// A <see cref="Matrix3x3"/> 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 Matrix3x3 operator *(Matrix3x3 m1, Matrix3x3 m2) { // Allocate product matrix Matrix3x3 prod = new Matrix3x3(); // 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. /// </exception> public new Matrix4x4 GetInverseMatrix() { #if XXX float px = Math.Abs(this[0, 3]), py = Math.Abs(this[1, 3]), pz = Math.Abs(this[2, 3]), ps = Math.Abs(this[3, 3] - 1.0f); if ((px > Single.Epsilon) || (py > Single.Epsilon) || (pz > Single.Epsilon) || (ps > Single.Epsilon)) #endif return ((Matrix4x4)base.GetInverseMatrix()); // Most general case, but rare #if XXX else { Matrix3x3 rotMatrix = new Matrix3x3(this, 3, 3); Matrix4x4 inverseMatrix = (Matrix4x4) Clone(); // Invert rotation matrix rotMatrix = rotMatrix.GetInverseMatrix(); unsafe { fixed (float* src = rotMatrix.MatrixBuffer) fixed (float* dst = inverseMatrix.MatrixBuffer) { // Copy rotation matrix into the inverse dst[0] = src[0]; dst[4] = src[3]; dst[8] = src[6]; dst[1] = src[1]; dst[5] = src[4]; dst[9] = src[7]; dst[2] = src[2]; dst[6] = src[5]; dst[10] = src[8]; dst[3] = 0.0f; dst[7] = 0.0f; dst[11] = 0.0f; dst[15] = 1.0f; } fixed (float* src = MatrixBuffer) fixed (float* dst = inverseMatrix.MatrixBuffer) { // Negate translation dst[12] = -src[12]; dst[13] = -src[13]; dst[14] = -src[14]; } } return (inverseMatrix); } #endif }
/// <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, Matrix3x3 m) { if (ctx == null) throw new ArgumentNullException("ctx"); UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat3x3: SetUniform(ctx, uniformName, m); break; case ShaderUniformType.DoubleMat3x3: SetUniform(ctx, uniformName, (MatrixDouble3x3)m); break; default: throw new ShaderException("unable to set single-precision floating-point matrix 3x3 data to uniform of type {0}", uniform.UniformType); } }
/// <summary> /// Set uniform state variable (mat3 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="Matrix3x3"/> holding the uniform variabile data. /// </param> public void SetUniform(GraphicsContext ctx, string uniformName, Matrix3x3 m) { if (ctx == null) throw new ArgumentNullException("ctx"); if (m == null) throw new ArgumentNullException("m"); UniformBinding uniform = GetUniform(uniformName); CheckProgramBinding(); CheckUniformType(uniform, Gl.FLOAT_MAT3); // Set uniform value Gl.UniformMatrix3(uniform.Location, 1, false, m.MatrixBuffer); }