Fix large worlds rendering of meshes
Add `Double4x4` for higher precision matrices operations #2985
This commit is contained in:
115
Source/Engine/Core/Math/Double4x4.h
Normal file
115
Source/Engine/Core/Math/Double4x4.h
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Vector4.h"
|
||||
|
||||
/// <summary>
|
||||
/// Represents a 4x4 mathematical matrix using double-precision floating-point values.
|
||||
/// </summary>
|
||||
struct FLAXENGINE_API Double4x4
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// <summary>Value at row 1 column 1 of the matrix.</summary>
|
||||
double M11;
|
||||
|
||||
/// <summary>Value at row 1 column 2 of the matrix.</summary>
|
||||
double M12;
|
||||
|
||||
/// <summary>Value at row 1 column 3 of the matrix.</summary>
|
||||
double M13;
|
||||
|
||||
/// <summary>Value at row 1 column 4 of the matrix.</summary>
|
||||
double M14;
|
||||
|
||||
/// <summary>Value at row 2 column 1 of the matrix.</summary>
|
||||
double M21;
|
||||
|
||||
/// <summary>Value at row 2 column 2 of the matrix.</summary>
|
||||
double M22;
|
||||
|
||||
/// <summary>Value at row 2 column 3 of the matrix.</summary>
|
||||
double M23;
|
||||
|
||||
/// <summary>Value at row 2 column 4 of the matrix.</summary>
|
||||
double M24;
|
||||
|
||||
/// <summary>Value at row 3 column 1 of the matrix.</summary>
|
||||
double M31;
|
||||
|
||||
/// <summary>Value at row 3 column 2 of the matrix.</summary>
|
||||
double M32;
|
||||
|
||||
/// <summary>Value at row 3 column 3 of the matrix.</summary>
|
||||
double M33;
|
||||
|
||||
/// <summary>Value at row 3 column 4 of the matrix.</summary>
|
||||
double M34;
|
||||
|
||||
/// <summary>Value at row 4 column 1 of the matrix.</summary>
|
||||
double M41;
|
||||
|
||||
/// <summary>Value at row 4 column 2 of the matrix.</summary>
|
||||
double M42;
|
||||
|
||||
/// <summary>Value at row 4 column 3 of the matrix.</summary>
|
||||
double M43;
|
||||
|
||||
/// <summary>Value at row 4 column 4 of the matrix.</summary>
|
||||
double M44;
|
||||
};
|
||||
|
||||
double Values[4][4];
|
||||
double Raw[16];
|
||||
};
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Empty constructor.
|
||||
/// </summary>
|
||||
Double4x4() = default;
|
||||
|
||||
Double4x4(const Matrix& matrix);
|
||||
|
||||
public:
|
||||
// Inverts the matrix.
|
||||
void Invert()
|
||||
{
|
||||
Invert(*this, *this);
|
||||
}
|
||||
|
||||
// Calculates the inverse of the specified matrix.
|
||||
static Double4x4 Invert(const Double4x4& value)
|
||||
{
|
||||
Double4x4 result;
|
||||
Invert(value, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculates the inverse of the specified matrix.
|
||||
static void Invert(const Double4x4& value, Double4x4& result);
|
||||
|
||||
// Calculates the product of two matrices.
|
||||
static void Multiply(const Double4x4& left, const Double4x4& right, Double4x4& result);
|
||||
|
||||
// Creates a matrix that contains both the X, Y and Z rotation, as well as scaling and translation.
|
||||
static void Transformation(const Float3& scaling, const Quaternion& rotation, const Vector3& translation, Double4x4& result);
|
||||
|
||||
public:
|
||||
Double4x4 operator*(const Double4x4& other) const
|
||||
{
|
||||
Double4x4 result;
|
||||
Multiply(*this, other, result);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct TIsPODType<Double4x4>
|
||||
{
|
||||
enum { Value = true };
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Double4x4.h"
|
||||
#include "Matrix3x3.h"
|
||||
#include "Matrix3x4.h"
|
||||
#include "Vector2.h"
|
||||
@@ -28,6 +29,12 @@ Matrix::Matrix(const Matrix3x3& matrix)
|
||||
M44 = 1.0f;
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Double4x4& matrix)
|
||||
{
|
||||
for (int32 i = 0; i < 16; i++)
|
||||
Raw[i] = (float)matrix.Raw[i];
|
||||
}
|
||||
|
||||
String Matrix::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("{}"), *this);
|
||||
@@ -924,3 +931,144 @@ void Matrix3x4::SetMatrixTranspose(const Matrix& m)
|
||||
dst[10] = src[10];
|
||||
dst[11] = src[14];
|
||||
}
|
||||
|
||||
Double4x4::Double4x4(const Matrix& matrix)
|
||||
{
|
||||
for (int32 i = 0; i < 16; i++)
|
||||
Raw[i] = matrix.Raw[i];
|
||||
}
|
||||
|
||||
void Double4x4::Invert(const Double4x4& value, Double4x4& result)
|
||||
{
|
||||
const double b0 = value.M31 * value.M42 - value.M32 * value.M41;
|
||||
const double b1 = value.M31 * value.M43 - value.M33 * value.M41;
|
||||
const double b2 = value.M34 * value.M41 - value.M31 * value.M44;
|
||||
const double b3 = value.M32 * value.M43 - value.M33 * value.M42;
|
||||
const double b4 = value.M34 * value.M42 - value.M32 * value.M44;
|
||||
const double b5 = value.M33 * value.M44 - value.M34 * value.M43;
|
||||
|
||||
const double d11 = value.M22 * b5 + value.M23 * b4 + value.M24 * b3;
|
||||
const double d12 = value.M21 * b5 + value.M23 * b2 + value.M24 * b1;
|
||||
const double d13 = value.M21 * -b4 + value.M22 * b2 + value.M24 * b0;
|
||||
const double d14 = value.M21 * b3 + value.M22 * -b1 + value.M23 * b0;
|
||||
|
||||
double det = value.M11 * d11 - value.M12 * d12 + value.M13 * d13 - value.M14 * d14;
|
||||
if (Math::Abs(det) <= 1e-12)
|
||||
{
|
||||
Platform::MemoryClear(&result, sizeof(Double4x4));
|
||||
return;
|
||||
}
|
||||
|
||||
det = 1.0 / det;
|
||||
|
||||
const double a0 = value.M11 * value.M22 - value.M12 * value.M21;
|
||||
const double a1 = value.M11 * value.M23 - value.M13 * value.M21;
|
||||
const double a2 = value.M14 * value.M21 - value.M11 * value.M24;
|
||||
const double a3 = value.M12 * value.M23 - value.M13 * value.M22;
|
||||
const double a4 = value.M14 * value.M22 - value.M12 * value.M24;
|
||||
const double a5 = value.M13 * value.M24 - value.M14 * value.M23;
|
||||
|
||||
const double d21 = value.M12 * b5 + value.M13 * b4 + value.M14 * b3;
|
||||
const double d22 = value.M11 * b5 + value.M13 * b2 + value.M14 * b1;
|
||||
const double d23 = value.M11 * -b4 + value.M12 * b2 + value.M14 * b0;
|
||||
const double d24 = value.M11 * b3 + value.M12 * -b1 + value.M13 * b0;
|
||||
|
||||
const double d31 = value.M42 * a5 + value.M43 * a4 + value.M44 * a3;
|
||||
const double d32 = value.M41 * a5 + value.M43 * a2 + value.M44 * a1;
|
||||
const double d33 = value.M41 * -a4 + value.M42 * a2 + value.M44 * a0;
|
||||
const double d34 = value.M41 * a3 + value.M42 * -a1 + value.M43 * a0;
|
||||
|
||||
const double d41 = value.M32 * a5 + value.M33 * a4 + value.M34 * a3;
|
||||
const double d42 = value.M31 * a5 + value.M33 * a2 + value.M34 * a1;
|
||||
const double d43 = value.M31 * -a4 + value.M32 * a2 + value.M34 * a0;
|
||||
const double d44 = value.M31 * a3 + value.M32 * -a1 + value.M33 * a0;
|
||||
|
||||
result.M11 = +d11 * det;
|
||||
result.M12 = -d21 * det;
|
||||
result.M13 = +d31 * det;
|
||||
result.M14 = -d41 * det;
|
||||
result.M21 = -d12 * det;
|
||||
result.M22 = +d22 * det;
|
||||
result.M23 = -d32 * det;
|
||||
result.M24 = +d42 * det;
|
||||
result.M31 = +d13 * det;
|
||||
result.M32 = -d23 * det;
|
||||
result.M33 = +d33 * det;
|
||||
result.M34 = -d43 * det;
|
||||
result.M41 = -d14 * det;
|
||||
result.M42 = +d24 * det;
|
||||
result.M43 = -d34 * det;
|
||||
result.M44 = +d44 * det;
|
||||
}
|
||||
|
||||
void Double4x4::Multiply(const Double4x4& left, const Double4x4& right, Double4x4& result)
|
||||
{
|
||||
result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41;
|
||||
result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42;
|
||||
result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43;
|
||||
result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44;
|
||||
result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41;
|
||||
result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42;
|
||||
result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43;
|
||||
result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44;
|
||||
result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41;
|
||||
result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42;
|
||||
result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43;
|
||||
result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44;
|
||||
result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41;
|
||||
result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42;
|
||||
result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43;
|
||||
result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44;
|
||||
}
|
||||
|
||||
void Double4x4::Transformation(const Float3& scaling, const Quaternion& rotation, const Vector3& translation, Double4x4& result)
|
||||
{
|
||||
// Equivalent to:
|
||||
//result =
|
||||
// Matrix.Scaling(scaling)
|
||||
// *Matrix.RotationX(rotation.X)
|
||||
// *Matrix.RotationY(rotation.Y)
|
||||
// *Matrix.RotationZ(rotation.Z)
|
||||
// *Matrix.Position(translation);
|
||||
|
||||
// Rotation
|
||||
const float xx = rotation.X * rotation.X;
|
||||
const float yy = rotation.Y * rotation.Y;
|
||||
const float zz = rotation.Z * rotation.Z;
|
||||
const float xy = rotation.X * rotation.Y;
|
||||
const float zw = rotation.Z * rotation.W;
|
||||
const float zx = rotation.Z * rotation.X;
|
||||
const float yw = rotation.Y * rotation.W;
|
||||
const float yz = rotation.Y * rotation.Z;
|
||||
const float xw = rotation.X * rotation.W;
|
||||
result.M11 = 1.0f - 2.0f * (yy + zz);
|
||||
result.M12 = 2.0f * (xy + zw);
|
||||
result.M13 = 2.0f * (zx - yw);
|
||||
result.M21 = 2.0f * (xy - zw);
|
||||
result.M22 = 1.0f - 2.0f * (zz + xx);
|
||||
result.M23 = 2.0f * (yz + xw);
|
||||
result.M31 = 2.0f * (zx + yw);
|
||||
result.M32 = 2.0f * (yz - xw);
|
||||
result.M33 = 1.0f - 2.0f * (yy + xx);
|
||||
|
||||
// Position
|
||||
result.M41 = translation.X;
|
||||
result.M42 = translation.Y;
|
||||
result.M43 = translation.Z;
|
||||
|
||||
// Scale
|
||||
result.M11 *= scaling.X;
|
||||
result.M12 *= scaling.X;
|
||||
result.M13 *= scaling.X;
|
||||
result.M21 *= scaling.Y;
|
||||
result.M22 *= scaling.Y;
|
||||
result.M23 *= scaling.Y;
|
||||
result.M31 *= scaling.Z;
|
||||
result.M32 *= scaling.Z;
|
||||
result.M33 *= scaling.Z;
|
||||
|
||||
result.M14 = 0.0;
|
||||
result.M24 = 0.0;
|
||||
result.M34 = 0.0;
|
||||
result.M44 = 1.0;
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ public:
|
||||
}
|
||||
|
||||
explicit Matrix(const Matrix3x3& matrix);
|
||||
explicit Matrix(const Double4x4& matrix);
|
||||
|
||||
public:
|
||||
String ToString() const;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "Transform.h"
|
||||
#include "Double4x4.h"
|
||||
#include "Matrix.h"
|
||||
#include "Matrix3x3.h"
|
||||
#include "../Types/String.h"
|
||||
@@ -57,6 +58,11 @@ void Transform::GetWorld(Matrix& result) const
|
||||
Matrix::Transformation(Scale, Orientation, Translation, result);
|
||||
}
|
||||
|
||||
void Transform::GetWorld(Double4x4& result) const
|
||||
{
|
||||
Double4x4::Transformation(Scale, Orientation, Translation, result);
|
||||
}
|
||||
|
||||
Transform Transform::Add(const Vector3& translation) const
|
||||
{
|
||||
Transform result;
|
||||
|
||||
@@ -136,6 +136,12 @@ public:
|
||||
/// <param name="result">World matrix</param>
|
||||
void GetWorld(Matrix& result) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets world matrix that describes transformation as a 4 by 4 matrix.
|
||||
/// </summary>
|
||||
/// <param name="result">World matrix</param>
|
||||
void GetWorld(Double4x4& result) const;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Adds translation to this transform.
|
||||
|
||||
Reference in New Issue
Block a user