Skip to content

Commit 576e70c

Browse files
Merge pull request #390 from SakuragiHnmch/master
2 parents cf42eb2 + 1b1aaa4 commit 576e70c

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

Engine/Source/Common/Include/Common/Math/Matrix.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ namespace Common {
2424
max
2525
};
2626

27+
template<typename T>
28+
struct Quaternion;
29+
2730
// matrix stored in row-major
2831
template <typename T, uint8_t R, uint8_t C>
2932
requires ValidMatDims<R, C>
@@ -115,6 +118,10 @@ namespace Common {
115118
bool CanInverse() const;
116119
Mat Inverse() const;
117120
T Determinant() const;
121+
122+
Vec<T, 3> ExtractTranslation() const;
123+
Vec<T, 3> ExtractScale() const;
124+
Quaternion<T> ExtractRotation() const;
118125
};
119126

120127
template <typename T, uint8_t R, uint8_t C>
@@ -812,6 +819,82 @@ namespace Common {
812819
return result;
813820
}
814821

822+
template<typename T, uint8_t R, uint8_t C>
823+
Vec<T, 3> Mat<T, R, C>::ExtractTranslation() const
824+
{
825+
static_assert( R == 4 && C == 4);
826+
Vec<T, 3> ret = Vec<T, 3>(this->data[3], this->data[7], this->data[11]);
827+
return ret;
828+
}
829+
830+
template<typename T, uint8_t R, uint8_t C>
831+
Quaternion<T> Mat<T, R, C>::ExtractRotation() const
832+
{
833+
static_assert( R == 4 && C == 4);
834+
Quaternion<T> ret = Quaternion<T>(1, 0, 0, 0);
835+
836+
T sx = Vec<T, 3>(this->data[0], this->data[4], this->data[8]).Model();
837+
T sy = Vec<T, 3>(this->data[1], this->data[5], this->data[9]).Model();
838+
T sz = Vec<T, 3>(this->data[2], this->data[6], this->data[10]).Model();
839+
T det = this->Determinant();
840+
if (det < 0) {
841+
sx = -sx;
842+
}
843+
844+
T m11 = this->data[0] / sx, m21 = this->data[4] / sx, m31 = this->data[8] / sx;
845+
T m12 = this->data[1] / sy, m22 = this->data[5] / sy, m32 = this->data[9] / sy;
846+
T m13 = this->data[2] / sz, m23 = this->data[6] / sz, m33 = this->data[10] / sz;
847+
848+
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
849+
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
850+
T trace = m11 + m22 + m33;
851+
if (trace > 0) {
852+
T s = 0.5 / std::sqrt(trace + 1.0);
853+
ret.w = 0.25 / s;
854+
ret.x = (m32 - m23) * s;
855+
ret.y = (m13 - m31) * s;
856+
ret.z = (m21 - m12) * s;
857+
} else if (m11 > m22 && m11 > m33) {
858+
T s = 2.0 * std::sqrt(1.0 + m11 - m22 - m33);
859+
ret.w = ( m32 - m23 ) / s;
860+
ret.x = 0.25 * s;
861+
ret.y = ( m12 + m21 ) / s;
862+
ret.z = ( m13 + m31 ) / s;
863+
} else if (m22 > m33) {
864+
T s = 2.0 * std::sqrt( 1.0 + m22 - m11 - m33 );
865+
ret.w = ( m13 - m31 ) / s;
866+
ret.x = ( m12 + m21 ) / s;
867+
ret.y = 0.25 * s;
868+
ret.z = ( m23 + m32 ) / s;
869+
} else {
870+
T s = 2.0 * std::sqrt( 1.0 + m33 - m11 - m22 );
871+
ret.w = ( m21 - m12 ) / s;
872+
ret.x = ( m13 + m31 ) / s;
873+
ret.y = ( m23 + m32 ) / s;
874+
ret.z = 0.25 * s;
875+
}
876+
877+
return ret;
878+
}
879+
880+
template<typename T, uint8_t R, uint8_t C>
881+
Vec<T, 3> Mat<T, R, C>::ExtractScale() const
882+
{
883+
static_assert( R == 4 && C == 4);
884+
885+
T sx = Vec<T, 3>(this->data[0], this->data[4], this->data[8]).Model();
886+
T sy = Vec<T, 3>(this->data[1], this->data[5], this->data[9]).Model();
887+
T sz = Vec<T, 3>(this->data[2], this->data[6], this->data[10]).Model();
888+
889+
T det = this->Determinant();
890+
if (det < 0) {
891+
sx = -sx;
892+
}
893+
Vec<T, 3> ret = Vec<T, 3>(sx, sy, sz);
894+
895+
return ret;
896+
}
897+
815898
template <typename T, uint8_t R, uint8_t C>
816899
template <uint8_t DR, uint8_t DC>
817900
requires ValidSubMatDims<DR, DC, R, C>

Engine/Source/Common/Include/Common/Math/Transform.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace Common {
2323
static Transform LookAt(const Vec<T, 3>& inPosition, const Vec<T, 3>& inTargetPosition, const Vec<T, 3>& inUpDirection = VecConsts<T, 3>::unitZ);
2424

2525
Transform();
26+
Transform(const Mat<T, 4, 4>& inMatrix);
2627
Transform(Quaternion<T> inRotation, Vec<T, 3> inTranslation);
2728
Transform(Vec<T, 3> inScale, Quaternion<T> inRotation, Vec<T, 3> inTranslation);
2829
Transform(const Transform& other);
@@ -160,6 +161,14 @@ namespace Common {
160161
this->translation = VecConsts<T, 3>::zero;
161162
}
162163

164+
template <typename T>
165+
Transform<T>::Transform(const Mat<T, 4, 4>& inMatrix)
166+
{
167+
this->translation = inMatrix.ExtractTranslation();
168+
this->rotation = inMatrix.ExtractRotation();
169+
this->scale = inMatrix.ExtractScale();
170+
}
171+
163172
template <typename T>
164173
Transform<T>::Transform(Quaternion<T> inRotation, Vec<T, 3> inTranslation)
165174
{

Engine/Source/Common/Test/MathTest.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,22 @@ TEST(MathTest, SubMatrixTest)
351351
ASSERT_TRUE(m1.Row(2) == FVec3(7, 8, 9));
352352
}
353353

354+
TEST(MathTest, MatExtractionTest)
355+
{
356+
const FMat4x4 m = {
357+
0, -2, 0, 7,
358+
4, 0, 0, 5,
359+
0, 0, 3, 3,
360+
7, 5, 3, 1
361+
};
362+
363+
const FTransform trans = FTransform(m);
364+
365+
ASSERT_TRUE(trans.translation == FVec3(7.0f, 5.0f, 3.0f));
366+
ASSERT_TRUE(trans.scale == FVec3(4.0f, 2.0f, 3.0f));
367+
ASSERT_TRUE(trans.rotation == FQuat(0.7071067f, .0f, .0f, .7071067f));
368+
}
369+
354370
TEST(MathTest, MatViewTest)
355371
{
356372
const FMat3x3 v0(

Engine/Source/Runtime/Src/System/Transform.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace Runtime {
5151

5252
const auto& localToWorldMatrix = worldTransform.localToWorld.GetTransformMatrix();
5353
const auto& parentLocalToWorldMatrix = parentWorldTransform.localToWorld.GetTransformMatrix();
54-
// TODO localTransform.localToParent = parentLocalToWorldMatrix.Inverse() * localToWorldMatrix
54+
localTransform.localToParent = Common::FTransform(parentLocalToWorldMatrix.Inverse() * localToWorldMatrix);
5555
}
5656

5757
// Step2: update world transforms
@@ -66,7 +66,7 @@ namespace Runtime {
6666

6767
const auto& parentLocalToWorldMatrix = parentWorldTransform.localToWorld.GetTransformMatrix();
6868
const auto& childLocalToParentMatrix = childLocalTransform.localToParent.GetTransformMatrix();
69-
// TODO childWorldTransform.localToWorld = parentLocalToWorldMatrix * childLocalToParentMatrix
69+
childWorldTransform.localToWorld = Common::FTransform(parentLocalToWorldMatrix * childLocalToParentMatrix);
7070
};
7171

7272
for (const auto e : pendingUpdateChildrenWorldTransforms) {

0 commit comments

Comments
 (0)