A math struct representing a 3x3 basis plus translation (a 4x3 matrix) used for transforms in the Bullet physics port. It provides factory methods for common transforms (translation, scale, rotations, perspective, look-at), operators for multiplication with vectors and matrices, inversion and utilities to get/set rotation and directional vectors.
/* * C# / XNA port of Bullet (c) 2011 Mark Neale <[email protected]> * * Bullet Continuous Collision Detection and Physics Library * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ // Adapted from BulletXNA 73b2e1b9: namespace isolation, no XNA rendering, one type per file. #nullable disable #pragma warning disable CS1591, CS0168, CS0219, CS0414, CS0660, CS0661, CS0659, CS0693, CS8981, CS0108, CS0114 using System; namespace HumanoidRetargeter.Core.Formats.Mmd.Bullet.LinearMath; internal struct IndexedMatrix : IEquatable<IndexedMatrix> { private static IndexedMatrix _identity = new IndexedMatrix(1f, 0.0f, 0.0f, 0.0f, 1f, 0.0f, 0.0f, 0.0f, 1f, 0.0f, 0.0f, 0.0f); public static IndexedMatrix Identity { get { return IndexedMatrix._identity; } } static IndexedMatrix() { } public IndexedMatrix(float m11, float m12, float m13, float m21, float m22, float m23, float m31, float m32, float m33, float m41, float m42, float m43) { _basis = new IndexedBasisMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33); _origin = new IndexedVector3(m41, m42, m43); } public IndexedMatrix(IndexedBasisMatrix basis, IndexedVector3 origin) { _basis = basis; _origin = origin; } public static IndexedMatrix CreateLookAt(IndexedVector3 cameraPosition, IndexedVector3 cameraTarget, IndexedVector3 cameraUpVector) { IndexedVector3 vector3_1 = IndexedVector3.Normalize(cameraPosition - cameraTarget); IndexedVector3 vector3_2 = IndexedVector3.Normalize(IndexedVector3.Cross(cameraUpVector, vector3_1)); IndexedVector3 vector1 = IndexedVector3.Cross(vector3_1, vector3_2); IndexedMatrix matrix = IndexedMatrix.Identity; //matrix._basis = new IndexedBasisMatrix(vector3_2.X, vector1.X, vector3_1.X, vector3_2.Y, vector1.Y, vector3_1.Y, vector3_2.Z, vector1.Z, vector3_1.Z).Transpose(); matrix._basis = new IndexedBasisMatrix(ref vector3_2, ref vector1, ref vector3_1); matrix._origin = new IndexedVector3(-IndexedVector3.Dot(vector3_2, cameraPosition), -IndexedVector3.Dot(vector1, cameraPosition), -IndexedVector3.Dot(vector3_1, cameraPosition)); return matrix; } public static IndexedMatrix CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) { // if ((double)fieldOfView <= 0.0 || (double)fieldOfView >= 3.14159274101257) // throw new ArgumentOutOfRangeException("fieldOfView", string.Format((IFormatProvider)CultureInfo.CurrentCulture, FrameworkResources.OutRangeFieldOfView, new object[1] //{ // (object) "fieldOfView" //})); // else if ((double)nearPlaneDistance <= 0.0) // throw new ArgumentOutOfRangeException("nearPlaneDistance", string.Format((IFormatProvider)CultureInfo.CurrentCulture, FrameworkResources.NegativePlaneDistance, new object[1] //{ // (object) "nearPlaneDistance" //})); // else if ((double)farPlaneDistance <= 0.0) // { // throw new ArgumentOutOfRangeException("farPlaneDistance", string.Format((IFormatProvider)CultureInfo.CurrentCulture, FrameworkResources.NegativePlaneDistance, new object[1] //{ // (object) "farPlaneDistance" //})); // } // else { //if ((double)nearPlaneDistance >= (double)farPlaneDistance) // throw new ArgumentOutOfRangeException("nearPlaneDistance", FrameworkResources.OppositePlanes); float num1 = 1f / (float)Math.Tan((double)fieldOfView * 0.5); float num2 = num1 / aspectRatio; IndexedMatrix matrix = IndexedMatrix.Identity; matrix._basis = new IndexedBasisMatrix(num2, 0, 0, 0, num1, 0, 0, 0, farPlaneDistance / (nearPlaneDistance - farPlaneDistance)); matrix._origin = new IndexedVector3(0, 0, (float)((double)nearPlaneDistance * (double)farPlaneDistance / ((double)nearPlaneDistance - (double)farPlaneDistance))); return matrix; } } public static bool operator ==(IndexedMatrix matrix1, IndexedMatrix matrix2) { return matrix1._basis == matrix2._basis && matrix1._origin == matrix2._origin; } public static bool operator !=(IndexedMatrix matrix1, IndexedMatrix matrix2) { return matrix1._basis != matrix2._basis || matrix1._origin != matrix2._origin; } public static IndexedVector3 operator *(IndexedMatrix matrix1, IndexedVector3 v) { //return new IndexedVector3(matrix1._basis[0].Dot(ref v) + matrix1._origin.X, // matrix1._basis[1].Dot(ref v) + matrix1._origin.Y, // matrix1._basis[2].Dot(ref v) + matrix1._origin.Z); return new IndexedVector3(matrix1._basis._el0.Dot(ref v) + matrix1._origin.X, matrix1._basis._el1.Dot(ref v) + matrix1._origin.Y, matrix1._basis._el2.Dot(ref v) + matrix1._origin.Z); } public static void Multiply(out IndexedVector3 vout, ref IndexedMatrix matrix1, ref IndexedVector3 vin) { vout = new IndexedVector3(matrix1._basis._el0.Dot(ref vin) + matrix1._origin.X, matrix1._basis._el1.Dot(ref vin) + matrix1._origin.Y, matrix1._basis._el2.Dot(ref vin) + matrix1._origin.Z); } //public static IndexedVector3 operator *(IndexedVector3 v,IndexedMatrix matrix1) //{ // return new IndexedVector3(matrix1._basis[0].Dot(ref v) + matrix1._origin.X, // matrix1._basis[1].Dot(ref v) + matrix1._origin.Y, // matrix1._basis[2].Dot(ref v) + matrix1._origin.Z); //} public static IndexedMatrix operator *(IndexedMatrix matrix1, IndexedMatrix matrix2) { IndexedMatrix IndexedMatrix; IndexedMatrix._basis = matrix1._basis * matrix2._basis; IndexedMatrix._origin = matrix1 * matrix2._origin; return IndexedMatrix; } //public static IndexedMatrix operator *(IndexedMatrix matrix1, float scaleFactor) //{ // float num = scaleFactor; // IndexedMatrix IndexedMatrix; // IndexedMatrix._basis._Row0 = matrix1._Row0 * scaleFactor; // IndexedMatrix._basis._Row1 = matrix1._Row1 * scaleFactor; // IndexedMatrix._basis._Row3 = matrix1._Row3 * scaleFactor; // IndexedMatrix._basis.Row3 = matrix1.Row3 * scaleFactor; // return IndexedMatrix; //} //public static IndexedMatrix operator *(float scaleFactor, IndexedMatrix matrix1) //{ // IndexedMatrix IndexedMatrix; // IndexedMatrix._basis._Row0 = matrix1._basis._Row0 * scaleFactor; // IndexedMatrix._basis._Row1 = matrix1._basis._Row1 * scaleFactor; // IndexedMatrix._basis._Row2 = matrix1._basis._Row2 * scaleFactor; // IndexedMatrix._origin = matrix1._origin * scaleFactor; // return IndexedMatrix; //} //public static IndexedMatrix operator /(IndexedMatrix matrix1, IndexedMatrix matrix2) //{ // IndexedMatrix IndexedMatrix = IndexedMatrix.Identity; // IndexedMatrix._basis = matrix1._basis / matrix2._basis; // IndexedMatrix._origin = matrix1._origin / matrix2._origin; // return IndexedMatrix; //} public static IndexedMatrix operator /(IndexedMatrix matrix1, float divider) { float num = 1f / divider; IndexedMatrix IndexedMatrix; IndexedMatrix._basis = matrix1._basis * num; IndexedMatrix._origin = matrix1._origin * num; return IndexedMatrix; } public static IndexedMatrix CreateTranslation(IndexedVector3 position) { IndexedMatrix IndexedMatrix = IndexedMatrix.Identity; IndexedMatrix._origin = position; return IndexedMatrix; } public static void CreateTranslation(ref IndexedVector3 position, out IndexedMatrix result) { result = IndexedMatrix.Identity; result._origin = position; } public static IndexedMatrix CreateTranslation(float xPosition, float yPosition, float zPosition) { IndexedMatrix IndexedMatrix = IndexedMatrix.Identity; IndexedMatrix._origin = new IndexedVector3(xPosition, yPosition, zPosition); return IndexedMatrix; } public static void CreateTranslation(float xPosition, float yPosition, float zPosition, out IndexedMatrix result) { result = IndexedMatrix.Identity; result._origin = new IndexedVector3(xPosition, yPosition, zPosition); } public static IndexedMatrix CreateScale(float x, float y, float z) { IndexedMatrix IndexedMatrix = IndexedMatrix.Identity; IndexedMatrix._basis = IndexedBasisMatrix.CreateScale(new IndexedVector3(x, y, z)); return IndexedMatrix; } public static void CreateScale(float xScale, float yScale, float zScale, out IndexedMatrix result) { result = IndexedMatrix.Identity; result._basis = IndexedBasisMatrix.CreateScale(new IndexedVector3(xScale, yScale, zScale)); } public static IndexedMatrix CreateScale(IndexedVector3 scales) { IndexedMatrix result = IndexedMatrix.Identity; result._basis = IndexedBasisMatrix.CreateScale(scales); return result; } public static void CreateScale(ref IndexedVector3 scales, out IndexedMatrix result) { result = IndexedMatrix.Identity; result._basis = IndexedBasisMatrix.CreateScale(scales); } public static IndexedMatrix CreateScale(float scale) { IndexedMatrix result = IndexedMatrix.Identity; result._basis = IndexedBasisMatrix.CreateScale(new IndexedVector3(scale)); return result; } public static void CreateScale(float scale, out IndexedMatrix result) { result = IndexedMatrix.Identity; result._basis = IndexedBasisMatrix.CreateScale(new IndexedVector3(scale)); } public static IndexedMatrix CreateRotationX(float radians) { IndexedMatrix IndexedMatrix; IndexedMatrix._basis = IndexedBasisMatrix.CreateRotationX(radians); IndexedMatrix._origin = new IndexedVector3(0, 0, 0); return IndexedMatrix; } public static void CreateRotationX(float radians, out IndexedMatrix result) { result._basis = IndexedBasisMatrix.CreateRotationX(radians); result._origin = new IndexedVector3(0, 0, 0); } public static IndexedMatrix CreateRotationY(float radians) { IndexedMatrix IndexedMatrix; IndexedMatrix._basis = IndexedBasisMatrix.CreateRotationY(radians); IndexedMatrix._origin = new IndexedVector3(0, 0, 0); return IndexedMatrix; } public static void CreateRotationY(float radians, out IndexedMatrix result) { result._basis = IndexedBasisMatrix.CreateRotationY(radians); result._origin = new IndexedVector3(0, 0, 0); } public static IndexedMatrix CreateRotationZ(float radians) { IndexedMatrix IndexedMatrix; IndexedMatrix._basis = IndexedBasisMatrix.CreateRotationZ(radians); IndexedMatrix._origin = new IndexedVector3(0, 0, 0); return IndexedMatrix; } public static void CreateRotationZ(float radians, out IndexedMatrix result) { result._basis = IndexedBasisMatrix.CreateRotationZ(radians); result._origin = new IndexedVector3(0, 0, 0); } public bool Equals(IndexedMatrix other) { return _basis.Equals(other._basis) && _origin.Equals(other._origin); } public override bool Equals(object obj) { bool flag = false; if (obj is IndexedMatrix) flag = this.Equals((IndexedMatrix)obj); return flag; } public override int GetHashCode() { return this._basis.GetHashCode() + this._origin.GetHashCode(); } public IndexedMatrix Inverse() { IndexedBasisMatrix inv = _basis.Transpose(); return new IndexedMatrix(inv, inv * -_origin); } public IndexedVector3 InvXform(IndexedVector3 inVec) { IndexedVector3 v = inVec - _origin; return (_basis.Transpose() * v); } public IndexedVector3 InvXform(ref IndexedVector3 inVec) { IndexedVector3 v = inVec - _origin; return (_basis.Transpose() * v); } public IndexedMatrix InverseTimes(ref IndexedMatrix t) { IndexedVector3 v = new IndexedVector3(t._origin.X - _origin.X, t._origin.Y - _origin.Y, t._origin.Z - _origin.Z); IndexedVector3 v2 = new IndexedVector3(); IndexedBasisMatrix.Multiply(ref v2, ref _basis, ref v); return new IndexedMatrix(_basis.TransposeTimes(ref t._basis), v * _basis); } public void SetRotation(IndexedQuaternion q) { _basis.SetRotation(ref q); } public void SetRotation(ref IndexedQuaternion q) { _basis.SetRotation(ref q); } public IndexedQuaternion GetRotation() { return _basis.GetRotation(); } public static IndexedMatrix CreateFromQuaternion(IndexedQuaternion q) { IndexedMatrix i = new IndexedMatrix(); i._basis.SetRotation(ref q); return i; } public static IndexedMatrix CreateFromQuaternion(ref IndexedQuaternion q) { IndexedMatrix i = new IndexedMatrix(); i._basis.SetRotation(ref q); return i; } public IndexedVector3 Left { get { return _basis.Left; } } public IndexedVector3 Right { get { return _basis.Right; } } public IndexedVector3 Up { get { return _basis.Up; } } public IndexedVector3 Down { get { return _basis.Down; } } public IndexedVector3 Forward { get { return _basis.Forward; } } public IndexedVector3 Backward { get { return _basis.Backward; } } public IndexedBasisMatrix _basis; public IndexedVector3 _origin; }