/* * Copyright 2019-2025 Andrey Pokidov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; /* * Author: Andrey Pokidov * Date: 10 Feb 2019 */ namespace BGC { public struct F32Matrix3x3 { public float r1c1, r1c2, r1c3; public float r2c1, r2c2, r2c3; public float r3c1, r3c2, r3c3; public F32Matrix3x3() { this.r1c1 = 0.0f; this.r1c2 = 0.0f; this.r1c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 0.0f; this.r2c3 = 0.0f; this.r3c1 = 0.0f; this.r3c2 = 0.0f; this.r3c3 = 0.0f; } public F32Matrix3x3(float d1, float d2, float d3) { this.r1c1 = d1; this.r1c2 = 0.0f; this.r1c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = d2; this.r2c3 = 0.0f; this.r3c1 = 0.0f; this.r3c2 = 0.0f; this.r3c3 = d3; } public F32Matrix3x3(in F32Matrix3x3 matrix) { this.r1c1 = matrix.r1c1; this.r1c2 = matrix.r1c2; this.r1c3 = matrix.r1c3; this.r2c1 = matrix.r2c1; this.r2c2 = matrix.r2c2; this.r2c3 = matrix.r2c3; this.r3c1 = matrix.r3c1; this.r3c2 = matrix.r3c2; this.r3c3 = matrix.r3c3; } public F32Matrix3x3(in F64Matrix3x3 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r1c2; this.r1c3 = (float)matrix.r1c3; this.r2c1 = (float)matrix.r2c1; this.r2c2 = (float)matrix.r2c2; this.r2c3 = (float)matrix.r2c3; this.r3c1 = (float)matrix.r3c1; this.r3c2 = (float)matrix.r3c2; this.r3c3 = (float)matrix.r3c3; } public readonly float GetDeterminant() { return this.r1c1 * (this.r2c2 * this.r3c3 - this.r2c3 * this.r3c2) + this.r1c2 * (this.r2c3 * this.r3c1 - this.r2c1 * this.r3c3) + this.r1c3 * (this.r2c1 * this.r3c2 - this.r2c2 * this.r3c1); } public readonly bool IsSingular() { float determinant = this.GetDeterminant(); return -F32Utility.EPSYLON <= determinant && determinant <= F32Utility.EPSYLON; } public void Transpose() { (this.r1c2, this.r2c1) = (this.r2c1, this.r1c2); (this.r1c3, this.r3c1) = (this.r3c1, this.r1c3); (this.r2c3, this.r3c2) = (this.r3c2, this.r2c3); } public bool Invert() { float determinant = this.GetDeterminant(); if (-F32Utility.EPSYLON <= determinant && determinant <= F32Utility.EPSYLON) { return false; } float r1c1 = this.r2c2 * this.r3c3 - this.r2c3 * this.r3c2; float r1c2 = this.r1c3 * this.r3c2 - this.r1c2 * this.r3c3; float r1c3 = this.r1c2 * this.r2c3 - this.r1c3 * this.r2c2; float r2c1 = this.r2c3 * this.r3c1 - this.r2c1 * this.r3c3; float r2c2 = this.r1c1 * this.r3c3 - this.r1c3 * this.r3c1; float r2c3 = this.r1c3 * this.r2c1 - this.r1c1 * this.r2c3; float r3c1 = this.r2c1 * this.r3c2 - this.r2c2 * this.r3c1; float r3c2 = this.r1c2 * this.r3c1 - this.r1c1 * this.r3c2; float r3c3 = this.r1c1 * this.r2c2 - this.r1c2 * this.r2c1; this.r1c1 = r1c1 / determinant; this.r1c2 = r1c2 / determinant; this.r1c3 = r1c3 / determinant; this.r2c1 = r2c1 / determinant; this.r2c2 = r2c2 / determinant; this.r2c3 = r2c3 / determinant; this.r3c1 = r3c1 / determinant; this.r3c2 = r3c2 / determinant; this.r3c3 = r3c3 / determinant; return true; } public void Reset() { this.r1c1 = 0.0f; this.r1c2 = 0.0f; this.r1c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 0.0f; this.r2c3 = 0.0f; this.r3c1 = 0.0f; this.r3c2 = 0.0f; this.r3c3 = 0.0f; } public void SetToIdentity() { this.r1c1 = 1.0f; this.r1c2 = 0.0f; this.r1c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 1.0f; this.r2c3 = 0.0f; this.r3c1 = 0.0f; this.r3c2 = 0.0f; this.r3c3 = 1.0f; } public void SetToDiagonal(float d1, float d2, float d3) { this.r1c1 = d1; this.r1c2 = 0.0f; this.r1c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = d2; this.r2c3 = 0.0f; this.r2c1 = 0.0f; this.r2c2 = 0.0f; this.r2c3 = d3; } public void SetValues(in F32Matrix3x3 matrix) { this.r1c1 = matrix.r1c1; this.r1c2 = matrix.r1c2; this.r1c3 = matrix.r1c3; this.r2c1 = matrix.r2c1; this.r2c2 = matrix.r2c2; this.r2c3 = matrix.r2c3; this.r3c1 = matrix.r3c1; this.r3c2 = matrix.r3c2; this.r3c3 = matrix.r3c3; } public void SetValues(in F64Matrix3x3 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r1c2; this.r1c3 = (float)matrix.r1c3; this.r2c1 = (float)matrix.r2c1; this.r2c2 = (float)matrix.r2c2; this.r2c3 = (float)matrix.r2c3; this.r3c1 = (float)matrix.r3c1; this.r3c2 = (float)matrix.r3c2; this.r3c3 = (float)matrix.r3c3; } public void SetTransposedOf(in F32Matrix3x3 matrix) { this.r1c1 = matrix.r1c1; this.r2c2 = matrix.r2c2; this.r3c3 = matrix.r3c3; (this.r1c2, this.r2c1) = (matrix.r2c1, matrix.r1c2); (this.r1c3, this.r3c1) = (matrix.r3c1, matrix.r1c3); (this.r2c3, this.r3c2) = (matrix.r3c2, matrix.r2c3); } public void SetTransposedOf(in F64Matrix3x3 matrix) { this.r1c1 = (float)matrix.r1c1; this.r1c2 = (float)matrix.r2c1; this.r1c3 = (float)matrix.r3c1; this.r2c1 = (float)matrix.r1c2; this.r2c2 = (float)matrix.r2c2; this.r2c3 = (float)matrix.r3c2; this.r3c1 = (float)matrix.r1c3; this.r3c2 = (float)matrix.r2c3; this.r3c3 = (float)matrix.r3c3; } public bool SetInvertedOf(in F32Matrix3x3 matrix) { float determinant = matrix.GetDeterminant(); if (-F32Utility.EPSYLON <= determinant && determinant <= F32Utility.EPSYLON) { return false; } float r1c1 = matrix.r2c2 * matrix.r3c3 - matrix.r2c3 * matrix.r3c2; float r1c2 = matrix.r1c3 * matrix.r3c2 - matrix.r1c2 * matrix.r3c3; float r1c3 = matrix.r1c2 * matrix.r2c3 - matrix.r1c3 * matrix.r2c2; float r2c1 = matrix.r2c3 * matrix.r3c1 - matrix.r2c1 * matrix.r3c3; float r2c2 = matrix.r1c1 * matrix.r3c3 - matrix.r1c3 * matrix.r3c1; float r2c3 = matrix.r1c3 * matrix.r2c1 - matrix.r1c1 * matrix.r2c3; float r3c1 = matrix.r2c1 * matrix.r3c2 - matrix.r2c2 * matrix.r3c1; float r3c2 = matrix.r1c2 * matrix.r3c1 - matrix.r1c1 * matrix.r3c2; float r3c3 = matrix.r1c1 * matrix.r2c2 - matrix.r1c2 * matrix.r2c1; this.r1c1 = r1c1 / determinant; this.r1c2 = r1c2 / determinant; this.r1c3 = r1c3 / determinant; this.r2c1 = r2c1 / determinant; this.r2c2 = r2c2 / determinant; this.r2c3 = r2c3 / determinant; this.r3c1 = r3c1 / determinant; this.r3c2 = r3c2 / determinant; this.r3c3 = r3c3 / determinant; return true; } public void SetRow1(float c1, float c2, float c3) { this.r1c1 = c1; this.r1c2 = c2; this.r1c3 = c3; } public void SetRow2(float c1, float c2, float c3) { this.r2c1 = c1; this.r2c2 = c2; this.r2c3 = c3; } public void SetRow3(float c1, float c2, float c3) { this.r3c1 = c1; this.r3c2 = c2; this.r3c3 = c3; } public void SetColumn1(float r1, float r2, float r3) { this.r1c1 = r1; this.r2c1 = r2; this.r3c1 = r3; } public void SetColumn2(float r1, float r2, float r3) { this.r1c2 = r1; this.r2c2 = r2; this.r3c2 = r3; } public void SetColumn3(float r1, float r2, float r3) { this.r1c3 = r1; this.r2c3 = r2; this.r3c3 = r3; } public static void Add(in F32Matrix3x3 matrix1, in F32Matrix3x3 matrix2, out F32Matrix3x3 sum) { sum.r1c1 = matrix1.r1c1 + matrix2.r1c1; sum.r1c2 = matrix1.r1c2 + matrix2.r1c2; sum.r1c3 = matrix1.r1c3 + matrix2.r1c3; sum.r2c1 = matrix1.r2c1 + matrix2.r2c1; sum.r2c2 = matrix1.r2c2 + matrix2.r2c2; sum.r2c3 = matrix1.r2c3 + matrix2.r2c3; sum.r3c1 = matrix1.r3c1 + matrix2.r3c1; sum.r3c2 = matrix1.r3c2 + matrix2.r3c2; sum.r3c3 = matrix1.r3c3 + matrix2.r3c3; } public static void Subtract(in F32Matrix3x3 minuend, in F32Matrix3x3 subtrahend, out F32Matrix3x3 difference) { difference.r1c1 = minuend.r1c1 - subtrahend.r1c1; difference.r1c2 = minuend.r1c2 - subtrahend.r1c2; difference.r1c3 = minuend.r1c3 - subtrahend.r1c3; difference.r2c1 = minuend.r2c1 - subtrahend.r2c1; difference.r2c2 = minuend.r2c2 - subtrahend.r2c2; difference.r2c3 = minuend.r2c3 - subtrahend.r2c3; difference.r3c1 = minuend.r3c1 - subtrahend.r3c1; difference.r3c2 = minuend.r3c2 - subtrahend.r3c2; difference.r3c3 = minuend.r3c3 - subtrahend.r3c3; } public static void Multiply(in F32Matrix3x3 multiplicand, float multiplier, out F32Matrix3x3 product) { product.r1c1 = multiplicand.r1c1 * multiplier; product.r1c2 = multiplicand.r1c2 * multiplier; product.r1c3 = multiplicand.r1c3 * multiplier; product.r2c1 = multiplicand.r2c1 * multiplier; product.r2c2 = multiplicand.r2c2 * multiplier; product.r2c3 = multiplicand.r2c3 * multiplier; product.r3c1 = multiplicand.r3c1 * multiplier; product.r3c2 = multiplicand.r3c2 * multiplier; product.r3c3 = multiplicand.r3c3 * multiplier; } public static void Divide(in F32Matrix3x3 dividend, float divisor, out F32Matrix3x3 quotient) { quotient.r1c1 = dividend.r1c1 / divisor; quotient.r1c2 = dividend.r1c2 / divisor; quotient.r1c3 = dividend.r1c3 / divisor; quotient.r2c1 = dividend.r2c1 / divisor; quotient.r2c2 = dividend.r2c2 / divisor; quotient.r2c3 = dividend.r2c3 / divisor; quotient.r3c1 = dividend.r3c1 / divisor; quotient.r3c2 = dividend.r3c2 / divisor; quotient.r3c3 = dividend.r3c3 / divisor; } public static void GetWeightedSum2( float weight1, in F32Matrix3x3 matrix1, float weight2, in F32Matrix3x3 matrix2, out F32Matrix3x3 sum) { sum.r1c1 = matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2; sum.r1c2 = matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2; sum.r1c3 = matrix1.r1c3 * weight1 + matrix2.r1c3 * weight2; sum.r2c1 = matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2; sum.r2c2 = matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2; sum.r2c3 = matrix1.r2c3 * weight1 + matrix2.r2c3 * weight2; sum.r3c1 = matrix1.r3c1 * weight1 + matrix2.r3c1 * weight2; sum.r3c2 = matrix1.r3c2 * weight1 + matrix2.r3c2 * weight2; sum.r3c3 = matrix1.r3c3 * weight1 + matrix2.r3c3 * weight2; } public static void GetWeightedSum3( float weight1, in F32Matrix3x3 matrix1, float weight2, in F32Matrix3x3 matrix2, float weight3, in F32Matrix3x3 matrix3, out F32Matrix3x3 sum) { sum.r1c1 = matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2 + matrix3.r1c1 * weight3; sum.r1c2 = matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2 + matrix3.r1c2 * weight3; sum.r1c3 = matrix1.r1c3 * weight1 + matrix2.r1c3 * weight2 + matrix3.r1c3 * weight3; sum.r2c1 = matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2 + matrix3.r2c1 * weight3; sum.r2c2 = matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2 + matrix3.r2c2 * weight3; sum.r2c3 = matrix1.r2c3 * weight1 + matrix2.r2c3 * weight2 + matrix3.r2c3 * weight3; sum.r3c1 = matrix1.r3c1 * weight1 + matrix2.r3c1 * weight2 + matrix3.r3c1 * weight3; sum.r3c2 = matrix1.r3c2 * weight1 + matrix2.r3c2 * weight2 + matrix3.r3c2 * weight3; sum.r3c3 = matrix1.r3c3 * weight1 + matrix2.r3c3 * weight2 + matrix3.r3c3 * weight3; } public static void GetWeightedSum4( float weight1, in F32Matrix3x3 matrix1, float weight2, in F32Matrix3x3 matrix2, float weight3, in F32Matrix3x3 matrix3, float weight4, in F32Matrix3x3 matrix4, out F32Matrix3x3 sum) { sum.r1c1 = (matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2) + (matrix3.r1c1 * weight3 + matrix4.r1c1 * weight4); sum.r1c2 = (matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2) + (matrix3.r1c2 * weight3 + matrix4.r1c2 * weight4); sum.r1c3 = (matrix1.r1c3 * weight1 + matrix2.r1c3 * weight2) + (matrix3.r1c3 * weight3 + matrix4.r1c3 * weight4); sum.r2c1 = (matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2) + (matrix3.r2c1 * weight3 + matrix4.r2c1 * weight4); sum.r2c2 = (matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2) + (matrix3.r2c2 * weight3 + matrix4.r2c2 * weight4); sum.r2c3 = (matrix1.r2c3 * weight1 + matrix2.r2c3 * weight2) + (matrix3.r2c3 * weight3 + matrix4.r2c3 * weight4); sum.r3c1 = (matrix1.r3c1 * weight1 + matrix2.r3c1 * weight2) + (matrix3.r3c1 * weight3 + matrix4.r3c1 * weight4); sum.r3c2 = (matrix1.r3c2 * weight1 + matrix2.r3c2 * weight2) + (matrix3.r3c2 * weight3 + matrix4.r3c2 * weight4); sum.r3c3 = (matrix1.r3c3 * weight1 + matrix2.r3c3 * weight2) + (matrix3.r3c3 * weight3 + matrix4.r3c3 * weight4); } public static void GetWeightedSum5( float weight1, in F32Matrix3x3 matrix1, float weight2, in F32Matrix3x3 matrix2, float weight3, in F32Matrix3x3 matrix3, float weight4, in F32Matrix3x3 matrix4, float weight5, in F32Matrix3x3 matrix5, out F32Matrix3x3 sum) { sum.r1c1 = (matrix1.r1c1 * weight1 + matrix2.r1c1 * weight2) + (matrix3.r1c1 * weight3 + matrix4.r1c1 * weight4) + matrix5.r1c1 * weight5; sum.r1c2 = (matrix1.r1c2 * weight1 + matrix2.r1c2 * weight2) + (matrix3.r1c2 * weight3 + matrix4.r1c2 * weight4) + matrix5.r1c2 * weight5; sum.r1c3 = (matrix1.r1c3 * weight1 + matrix2.r1c3 * weight2) + (matrix3.r1c3 * weight3 + matrix4.r1c3 * weight4) + matrix5.r1c3 * weight5; sum.r2c1 = (matrix1.r2c1 * weight1 + matrix2.r2c1 * weight2) + (matrix3.r2c1 * weight3 + matrix4.r2c1 * weight4) + matrix5.r2c1 * weight5; sum.r2c2 = (matrix1.r2c2 * weight1 + matrix2.r2c2 * weight2) + (matrix3.r2c2 * weight3 + matrix4.r2c2 * weight4) + matrix5.r2c2 * weight5; sum.r2c3 = (matrix1.r2c3 * weight1 + matrix2.r2c3 * weight2) + (matrix3.r2c3 * weight3 + matrix4.r2c3 * weight4) + matrix5.r2c3 * weight5; sum.r3c1 = (matrix1.r3c1 * weight1 + matrix2.r3c1 * weight2) + (matrix3.r3c1 * weight3 + matrix4.r3c1 * weight4) + matrix5.r3c1 * weight5; sum.r3c2 = (matrix1.r3c2 * weight1 + matrix2.r3c2 * weight2) + (matrix3.r3c2 * weight3 + matrix4.r3c2 * weight4) + matrix5.r3c2 * weight5; sum.r3c3 = (matrix1.r3c3 * weight1 + matrix2.r3c3 * weight2) + (matrix3.r3c3 * weight3 + matrix4.r3c3 * weight4) + matrix5.r3c3 * weight5; } public static void GetRightProduct(in F32Matrix3x3 matrix, in F32Vector3 vector, out F32Vector3 result) { float x1 = matrix.r1c1 * vector.x1 + matrix.r1c2 * vector.x2 + matrix.r1c3 * vector.x3; float x2 = matrix.r2c1 * vector.x1 + matrix.r2c2 * vector.x2 + matrix.r2c3 * vector.x3; float x3 = matrix.r3c1 * vector.x1 + matrix.r3c2 * vector.x2 + matrix.r3c3 * vector.x3; result.x1 = x1; result.x2 = x2; result.x3 = x3; } public static void GetLeftProduct(in F32Vector3 vector, in F32Matrix3x3 matrix, out F32Vector3 result) { float x1 = vector.x1 * matrix.r1c1 + vector.x2 * matrix.r2c1 + vector.x3 * matrix.r3c1; float x2 = vector.x1 * matrix.r1c2 + vector.x2 * matrix.r2c2 + vector.x3 * matrix.r3c2; float x3 = vector.x1 * matrix.r1c3 + vector.x2 * matrix.r2c3 + vector.x3 * matrix.r3c3; result.x1 = x1; result.x2 = x2; result.x3 = x3; } public static void LoadZero(out F32Matrix3x3 matrix) { matrix.r1c1 = 0.0f; matrix.r1c2 = 0.0f; matrix.r1c3 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = 0.0f; matrix.r2c3 = 0.0f; matrix.r3c1 = 0.0f; matrix.r3c2 = 0.0f; matrix.r3c3 = 0.0f; } public static void LoadIdentity(out F32Matrix3x3 matrix) { matrix.r1c1 = 1.0f; matrix.r1c2 = 0.0f; matrix.r1c3 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = 1.0f; matrix.r2c3 = 0.0f; matrix.r3c1 = 0.0f; matrix.r3c2 = 0.0f; matrix.r3c3 = 1.0f; } public static void LoadDiagonal(float d1, float d2, float d3, out F32Matrix3x3 matrix) { matrix.r1c1 = d1; matrix.r1c2 = 0.0f; matrix.r1c3 = 0.0f; matrix.r2c1 = 0.0f; matrix.r2c2 = d2; matrix.r2c3 = 0.0f; matrix.r3c1 = 0.0f; matrix.r3c2 = 0.0f; matrix.r3c3 = d3; } } }