diff --git a/Source/Editor/SceneGraph/Actors/SpriteRenderNode.cs b/Source/Editor/SceneGraph/Actors/SpriteRenderNode.cs
index d0566b9a3..2c07c53be 100644
--- a/Source/Editor/SceneGraph/Actors/SpriteRenderNode.cs
+++ b/Source/Editor/SceneGraph/Actors/SpriteRenderNode.cs
@@ -50,7 +50,7 @@ namespace FlaxEditor.SceneGraph.Actors
OrientedBoundingBox bounds;
bounds.Extents = Vector3.Half;
- bounds.Transformation = world;
+ world.Decompose(out bounds.Transformation);
normal = -ray.Ray.Direction;
return bounds.Intersects(ref ray.Ray, out distance);
diff --git a/Source/Editor/Scripting/TypeUtils.cs b/Source/Editor/Scripting/TypeUtils.cs
index 54616990e..84d7340f9 100644
--- a/Source/Editor/Scripting/TypeUtils.cs
+++ b/Source/Editor/Scripting/TypeUtils.cs
@@ -127,9 +127,15 @@ namespace FlaxEditor.Scripting
return ChannelMask.Red;
if (type.Type == typeof(MaterialSceneTextures))
return MaterialSceneTextures.BaseColor;
+ if (type.IsValueType)
+ {
+ var value = type.CreateInstance();
+ Utilities.Utils.InitDefaultValues(value);
+ return value;
+ }
if (ScriptType.Object.IsAssignableFrom(type))
return null;
- if (type.IsValueType || type.CanCreateInstance)
+ if (type.CanCreateInstance)
{
var value = type.CreateInstance();
Utilities.Utils.InitDefaultValues(value);
diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs
index 0f77d5c5f..0dbbf721b 100644
--- a/Source/Editor/Utilities/Utils.cs
+++ b/Source/Editor/Utilities/Utils.cs
@@ -774,9 +774,10 @@ namespace FlaxEditor.Utilities
else
orientation = Quaternion.LookRotation(dir, Vector3.Cross(Vector3.Cross(dir, Vector3.Up), dir));
Vector3 up = Vector3.Up * orientation;
- box.Transformation = Matrix.CreateWorld(min + vec * 0.5f, dir, up);
- Matrix.Invert(ref box.Transformation, out Matrix inv);
- Vector3 vecLocal = Vector3.TransformNormal(vec * 0.5f, inv);
+ Matrix world = Matrix.CreateWorld(min + vec * 0.5f, dir, up);
+ world.Decompose(out box.Transformation);
+ Matrix.Invert(ref world, out Matrix invWorld);
+ Vector3 vecLocal = Vector3.TransformNormal(vec * 0.5f, invWorld);
box.Extents.X = margin;
box.Extents.Y = margin;
box.Extents.Z = vecLocal.Z;
diff --git a/Source/Editor/Windows/Assets/MaterialWindow.cs b/Source/Editor/Windows/Assets/MaterialWindow.cs
index 644b19688..aea385967 100644
--- a/Source/Editor/Windows/Assets/MaterialWindow.cs
+++ b/Source/Editor/Windows/Assets/MaterialWindow.cs
@@ -34,6 +34,9 @@ namespace FlaxEditor.Windows.Assets
new ScriptType(typeof(ChannelMask)),
new ScriptType(typeof(bool)),
new ScriptType(typeof(int)),
+ new ScriptType(typeof(Float2)),
+ new ScriptType(typeof(Float3)),
+ new ScriptType(typeof(Float4)),
new ScriptType(typeof(Vector2)),
new ScriptType(typeof(Vector3)),
new ScriptType(typeof(Vector4)),
diff --git a/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs b/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs
index 45e2f305d..33c02da0a 100644
--- a/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs
+++ b/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs
@@ -33,6 +33,9 @@ namespace FlaxEditor.Windows.Assets
new ScriptType(typeof(ChannelMask)),
new ScriptType(typeof(bool)),
new ScriptType(typeof(int)),
+ new ScriptType(typeof(Float2)),
+ new ScriptType(typeof(Float3)),
+ new ScriptType(typeof(Float4)),
new ScriptType(typeof(Vector2)),
new ScriptType(typeof(Vector3)),
new ScriptType(typeof(Vector4)),
diff --git a/Source/Engine/Core/Math/Matrix3x3.cpp b/Source/Engine/Core/Math/Matrix3x3.cpp
index fd5673154..7296a36d1 100644
--- a/Source/Engine/Core/Math/Matrix3x3.cpp
+++ b/Source/Engine/Core/Math/Matrix3x3.cpp
@@ -201,6 +201,40 @@ void Matrix3x3::RotationQuaternion(const Quaternion& rotation, Matrix3x3& result
result.M33 = 1.0f - 2.0f * (yy + xx);
}
+void Matrix3x3::Decompose(Float3& scale, Matrix3x3& rotation) const
+{
+ // Scaling is the length of the rows
+ scale = Float3(
+ Math::Sqrt(M11 * M11 + M12 * M12 + M13 * M13),
+ Math::Sqrt(M21 * M21 + M22 * M22 + M23 * M23),
+ Math::Sqrt(M31 * M31 + M32 * M32 + M33 * M33));
+
+ // If any of the scaling factors are zero, than the rotation matrix can not exist
+ rotation = Identity;
+ if (scale.IsAnyZero())
+ return;
+
+ // Calculate an perfect orthonormal matrix (no reflections)
+ const auto at = Float3(M31 / scale.Z, M32 / scale.Z, M33 / scale.Z);
+ const auto up = Float3::Cross(at, Float3(M11 / scale.X, M12 / scale.X, M13 / scale.X));
+ const auto right = Float3::Cross(up, at);
+ rotation.SetRight(right);
+ rotation.SetUp(up);
+ rotation.SetBackward(at);
+
+ // In case of reflexions
+ scale.X = Float3::Dot(right, GetRight()) > 0.0f ? scale.X : -scale.X;
+ scale.Y = Float3::Dot(up, GetUp()) > 0.0f ? scale.Y : -scale.Y;
+ scale.Z = Float3::Dot(at, GetBackward()) > 0.0f ? scale.Z : -scale.Z;
+}
+
+void Matrix3x3::Decompose(Float3& scale, Quaternion& rotation) const
+{
+ Matrix3x3 rotationMatrix;
+ Decompose(scale, rotationMatrix);
+ Quaternion::RotationMatrix(rotationMatrix, rotation);
+}
+
bool Matrix3x3::operator==(const Matrix3x3& other) const
{
return
diff --git a/Source/Engine/Core/Math/Matrix3x3.h b/Source/Engine/Core/Math/Matrix3x3.h
index 9094b313d..1d92c622c 100644
--- a/Source/Engine/Core/Math/Matrix3x3.h
+++ b/Source/Engine/Core/Math/Matrix3x3.h
@@ -120,6 +120,90 @@ public:
String ToString() const;
public:
+ // Gets the up Float3 of the matrix; that is M21, M22, and M23.
+ Float3 GetUp() const
+ {
+ return Float3(M21, M22, M23);
+ }
+
+ // Sets Float3 of the matrix; that is M21, M22, and M23.
+ void SetUp(const Float3& value)
+ {
+ M21 = value.X;
+ M22 = value.Y;
+ M23 = value.Z;
+ }
+
+ // Gets the down Float3 of the matrix; that is -M21, -M22, and -M23.
+ Float3 GetDown() const
+ {
+ return -Float3(M21, M22, M23);
+ }
+
+ // Sets the down Float3 of the matrix; that is -M21, -M22, and -M23.
+ void SetDown(const Float3& value)
+ {
+ M21 = -value.X;
+ M22 = -value.Y;
+ M23 = -value.Z;
+ }
+
+ // Gets the right Float3 of the matrix; that is M11, M12, and M13.
+ Float3 GetRight() const
+ {
+ return Float3(M11, M12, M13);
+ }
+
+ // Sets the right Float3 of the matrix; that is M11, M12, and M13.
+ void SetRight(const Float3& value)
+ {
+ M11 = value.X;
+ M12 = value.Y;
+ M13 = value.Z;
+ }
+
+ // Gets the left Float3 of the matrix; that is -M11, -M12, and -M13.
+ Float3 GetLeft() const
+ {
+ return -Float3(M11, M12, M13);
+ }
+
+ // Sets the left Float3 of the matrix; that is -M11, -M12, and -M13.
+ void SetLeft(const Float3& value)
+ {
+ M11 = -value.X;
+ M12 = -value.Y;
+ M13 = -value.Z;
+ }
+
+ // Gets the forward Float3 of the matrix; that is -M31, -M32, and -M33.
+ Float3 GetForward() const
+ {
+ return -Float3(M31, M32, M33);
+ }
+
+ // Sets the forward Float3 of the matrix; that is -M31, -M32, and -M33.
+ void SetForward(const Float3& value)
+ {
+ M31 = -value.X;
+ M32 = -value.Y;
+ M33 = -value.Z;
+ }
+
+ // Gets the backward Float3 of the matrix; that is M31, M32, and M33.
+ Float3 GetBackward() const
+ {
+ return Float3(M31, M32, M33);
+ }
+
+ // Sets the backward Float3 of the matrix; that is M31, M32, and M33.
+ void SetBackward(const Float3& value)
+ {
+ M31 = value.X;
+ M32 = value.Y;
+ M33 = value.Z;
+ }
+
// Gets the first row in the matrix; that is M11, M12 and M13.
Float3 GetRow1() const
{
@@ -497,6 +581,22 @@ public:
/// The created rotation matrix.
static void RotationQuaternion(const Quaternion& rotation, Matrix3x3& result);
+ ///
+ /// Decomposes a matrix into a scale and rotation.
+ ///
+ /// When the method completes, contains the scaling component of the decomposed matrix.
+ /// When the method completes, contains the rotation component of the decomposed matrix.
+ /// This method is designed to decompose an scale-rotation transformation matrix only.
+ void Decompose(Float3& scale, Matrix3x3& rotation) const;
+
+ ///
+ /// Decomposes a matrix into a scale and rotation.
+ ///
+ /// When the method completes, contains the scaling component of the decomposed matrix.
+ /// When the method completes, contains the rotation component of the decomposed matrix.
+ /// This method is designed to decompose an scale-rotation transformation matrix only.
+ void Decompose(Float3& scale, Quaternion& rotation) const;
+
public:
///
/// Tests for equality between two objects.
diff --git a/Source/Engine/Core/Math/OrientedBoundingBox.cpp b/Source/Engine/Core/Math/OrientedBoundingBox.cpp
index 819fa1268..803cdf73a 100644
--- a/Source/Engine/Core/Math/OrientedBoundingBox.cpp
+++ b/Source/Engine/Core/Math/OrientedBoundingBox.cpp
@@ -3,6 +3,7 @@
#include "OrientedBoundingBox.h"
#include "BoundingSphere.h"
#include "BoundingBox.h"
+#include "Matrix.h"
#include "Ray.h"
#include "../Types/String.h"
@@ -10,32 +11,41 @@ OrientedBoundingBox::OrientedBoundingBox(const BoundingBox& bb)
{
const Vector3 center = bb.Minimum + (bb.Maximum - bb.Minimum) * 0.5f;
Extents = bb.Maximum - center;
- Matrix::Translation(center, Transformation);
+ Transformation = ::Transform(center);
+}
+
+OrientedBoundingBox::OrientedBoundingBox(const Vector3& extents, const Matrix& transformation)
+ : Extents(extents)
+{
+ transformation.Decompose(Transformation);
}
OrientedBoundingBox::OrientedBoundingBox(const Vector3& extents, const Matrix3x3& rotationScale, const Vector3& translation)
: Extents(extents)
- , Transformation(rotationScale)
+ , Transformation(translation, rotationScale)
{
- Transformation.SetTranslation(translation);
+}
+
+OrientedBoundingBox::OrientedBoundingBox(const Vector3& minimum, const Vector3& maximum)
+{
+ const Vector3 center = minimum + (maximum - minimum) * 0.5f;
+ Extents = maximum - center;
+ Transformation = ::Transform(center);
}
OrientedBoundingBox::OrientedBoundingBox(Vector3 points[], int32 pointCount)
{
ASSERT(points && pointCount > 0);
-
Vector3 minimum = points[0];
Vector3 maximum = points[0];
-
for (int32 i = 1; i < pointCount; i++)
{
Vector3::Min(minimum, points[i], minimum);
Vector3::Max(maximum, points[i], maximum);
}
-
- const Vector3 center = minimum + (maximum - minimum) / 2.0f;
+ const Vector3 center = minimum + (maximum - minimum) * 0.5f;
Extents = maximum - center;
- Matrix::Translation(center, Transformation);
+ Transformation = ::Transform(center);
}
String OrientedBoundingBox::ToString() const
@@ -45,15 +55,11 @@ String OrientedBoundingBox::ToString() const
void OrientedBoundingBox::GetCorners(Float3 corners[8]) const
{
- Float3 xv((float)Extents.X, 0, 0);
- Float3 yv(0, (float)Extents.Y, 0);
- Float3 zv(0, 0, (float)Extents.Z);
+ const Float3 xv = Transformation.LocalToWorldVector(Vector3((float)Extents.X, 0, 0));
+ const Float3 yv = Transformation.LocalToWorldVector(Vector3(0, (float)Extents.Y, 0));
+ const Float3 zv = Transformation.LocalToWorldVector(Vector3(0, 0, (float)Extents.Z));
- Float3::TransformNormal(xv, Transformation, xv);
- Float3::TransformNormal(yv, Transformation, yv);
- Float3::TransformNormal(zv, Transformation, zv);
-
- const Float3 center = Transformation.GetTranslation();
+ const Float3 center = Transformation.Translation;
corners[0] = center + xv + yv + zv;
corners[1] = center + xv + yv - zv;
@@ -67,15 +73,11 @@ void OrientedBoundingBox::GetCorners(Float3 corners[8]) const
void OrientedBoundingBox::GetCorners(Double3 corners[8]) const
{
- Double3 xv(Extents.X, 0, 0);
- Double3 yv(0, Extents.Y, 0);
- Double3 zv(0, 0, Extents.Z);
+ const Double3 xv = Transformation.LocalToWorldVector(Vector3((float)Extents.X, 0, 0));
+ const Double3 yv = Transformation.LocalToWorldVector(Vector3(0, (float)Extents.Y, 0));
+ const Double3 zv = Transformation.LocalToWorldVector(Vector3(0, 0, (float)Extents.Z));
- Double3::TransformNormal(xv, Transformation, xv);
- Double3::TransformNormal(yv, Transformation, yv);
- Double3::TransformNormal(zv, Transformation, zv);
-
- const Double3 center = Transformation.GetTranslation();
+ const Double3 center = Transformation.Translation;
corners[0] = center + xv + yv + zv;
corners[1] = center + xv + yv - zv;
@@ -89,39 +91,26 @@ void OrientedBoundingBox::GetCorners(Double3 corners[8]) const
Vector3 OrientedBoundingBox::GetSize() const
{
- Vector3 xv = Vector3(Extents.X * 2, 0, 0);
- Vector3 yv = Vector3(0, Extents.Y * 2, 0);
- Vector3 zv = Vector3(0, 0, Extents.Z * 2);
-
- Vector3::TransformNormal(xv, Transformation, xv);
- Vector3::TransformNormal(yv, Transformation, yv);
- Vector3::TransformNormal(zv, Transformation, zv);
-
+ const Vector3 xv = Transformation.LocalToWorldVector(Vector3(Extents.X * 2, 0, 0));
+ const Vector3 yv = Transformation.LocalToWorldVector(Vector3(0, Extents.Y * 2, 0));
+ const Vector3 zv = Transformation.LocalToWorldVector(Vector3(0, 0, Extents.Z * 2));
return Vector3(xv.Length(), yv.Length(), zv.Length());
}
Vector3 OrientedBoundingBox::GetSizeSquared() const
{
- Vector3 xv = Vector3(Extents.X * 2, 0, 0);
- Vector3 yv = Vector3(0, Extents.Y * 2, 0);
- Vector3 zv = Vector3(0, 0, Extents.Z * 2);
-
- Vector3::TransformNormal(xv, Transformation, xv);
- Vector3::TransformNormal(yv, Transformation, yv);
- Vector3::TransformNormal(zv, Transformation, zv);
-
+ const Vector3 xv = Transformation.LocalToWorldVector(Vector3(Extents.X * 2, 0, 0));
+ const Vector3 yv = Transformation.LocalToWorldVector(Vector3(0, Extents.Y * 2, 0));
+ const Vector3 zv = Transformation.LocalToWorldVector(Vector3(0, 0, Extents.Z * 2));
return Vector3(xv.LengthSquared(), yv.LengthSquared(), zv.LengthSquared());
}
BoundingBox OrientedBoundingBox::GetBoundingBox() const
{
BoundingBox result;
-
Vector3 corners[8];
GetCorners(corners);
-
BoundingBox::FromPoints(corners, 8, result);
-
return result;
}
@@ -135,19 +124,21 @@ void OrientedBoundingBox::GetBoundingBox(BoundingBox& result) const
void OrientedBoundingBox::Transform(const Matrix& matrix)
{
- const Matrix tmp = Transformation;
- Matrix::Multiply(tmp, matrix, Transformation);
+ ::Transform transform;
+ matrix.Decompose(transform);
+ Transformation = transform.LocalToWorld(Transformation);
+}
+
+void OrientedBoundingBox::Transform(const ::Transform& transform)
+{
+ Transformation = transform.LocalToWorld(Transformation);
}
ContainmentType OrientedBoundingBox::Contains(const Vector3& point, Real* distance) const
{
// Transform the point into the obb coordinates
- Matrix invTrans;
- Matrix::Invert(Transformation, invTrans);
-
Vector3 locPoint;
- Vector3::TransformCoordinate(point, invTrans, locPoint);
-
+ Transformation.WorldToLocal(point, locPoint);
locPoint.X = Math::Abs(locPoint.X);
locPoint.Y = Math::Abs(locPoint.Y);
locPoint.Z = Math::Abs(locPoint.Z);
@@ -161,7 +152,7 @@ ContainmentType OrientedBoundingBox::Contains(const Vector3& point, Real* distan
// Transform distance to world space
Vector3 dstVec = Vector3::UnitX * minDstToEdgeLocal;
- Vector3::TransformNormal(dstVec, Transformation, dstVec);
+ Transformation.LocalToWorldVector(dstVec, dstVec);
*distance = dstVec.Length();
}
@@ -173,49 +164,11 @@ ContainmentType OrientedBoundingBox::Contains(const Vector3& point, Real* distan
return ContainmentType::Disjoint;
}
-ContainmentType OrientedBoundingBox::Contains(int32 pointsCnt, Vector3 points[]) const
-{
- ASSERT(pointsCnt > 0);
-
- Matrix invTrans;
- Matrix::Invert(Transformation, invTrans);
-
- bool containsAll = true;
- bool containsAny = false;
-
- for (int32 i = 0; i < pointsCnt; i++)
- {
- Vector3 locPoint;
- Vector3::TransformCoordinate(points[i], invTrans, locPoint);
-
- locPoint.X = Math::Abs(locPoint.X);
- locPoint.Y = Math::Abs(locPoint.Y);
- locPoint.Z = Math::Abs(locPoint.Z);
-
- // Simple axes-aligned BB check
- if (Vector3::NearEqual(locPoint, Extents))
- containsAny = true;
- if (locPoint.X < Extents.X && locPoint.Y < Extents.Y && locPoint.Z < Extents.Z)
- containsAny = true;
- else
- containsAll = false;
- }
-
- if (containsAll)
- return ContainmentType::Contains;
- if (containsAny)
- return ContainmentType::Intersects;
- return ContainmentType::Disjoint;
-}
-
ContainmentType OrientedBoundingBox::Contains(const BoundingSphere& sphere, bool ignoreScale) const
{
- Matrix invTrans;
- Matrix::Invert(Transformation, invTrans);
-
// Transform sphere center into the obb coordinates
Vector3 locCenter;
- Vector3::TransformCoordinate(sphere.Center, invTrans, locCenter);
+ Transformation.WorldToLocal(sphere.Center, locCenter);
Real locRadius;
if (ignoreScale)
@@ -226,7 +179,7 @@ ContainmentType OrientedBoundingBox::Contains(const BoundingSphere& sphere, bool
{
// Transform sphere radius into the obb coordinates
Vector3 vRadius = Vector3::UnitX * sphere.Radius;
- Vector3::TransformNormal(vRadius, invTrans, vRadius);
+ Transformation.LocalToWorldVector(vRadius, vRadius);
locRadius = vRadius.Length();
}
@@ -238,119 +191,25 @@ ContainmentType OrientedBoundingBox::Contains(const BoundingSphere& sphere, bool
if (distance > locRadius * locRadius)
return ContainmentType::Disjoint;
-
- if (minusExtents.X + locRadius <= locCenter.X
- && locCenter.X <= Extents.X - locRadius
- && (Extents.X - minusExtents.X > locRadius
- && minusExtents.Y + locRadius <= locCenter.Y)
- && (locCenter.Y <= Extents.Y - locRadius
- && Extents.Y - minusExtents.Y > locRadius
- && (minusExtents.Z + locRadius <= locCenter.Z
- && locCenter.Z <= Extents.Z - locRadius
- && Extents.Z - minusExtents.Z > locRadius)))
- {
+ if (minusExtents.X + locRadius <= locCenter.X && locCenter.X <= Extents.X - locRadius && (Extents.X - minusExtents.X > locRadius && minusExtents.Y + locRadius <= locCenter.Y) && (locCenter.Y <= Extents.Y - locRadius && Extents.Y - minusExtents.Y > locRadius && (minusExtents.Z + locRadius <= locCenter.Z && locCenter.Z <= Extents.Z - locRadius && Extents.Z - minusExtents.Z > locRadius)))
return ContainmentType::Contains;
- }
-
return ContainmentType::Intersects;
}
-/*ContainmentType OrientedBoundingBox::Contains(const OrientedBoundingBox& obb)
-{
- Vector3 obbCorners[8];
- obb.GetCorners(obbCorners);
- auto cornersCheck = Contains(8, obbCorners);
- if (cornersCheck != ContainmentType::Disjoint)
- return cornersCheck;
-
- // http://www.3dkingdoms.com/weekly/bbox.cpp
- Vector3 SizeA = Extents;
- Vector3 SizeB = obb.Extents;
- Vector3 RotA[3];
- Vector3 RotB[3];
- GetRows(Transformation, RotA);
- GetRows(obb.Transformation, RotB);
-
- Matrix R = Matrix::Identity; // Rotation from B to A
- Matrix AR = Matrix::Identity; // absolute values of R matrix, to use with box extents
-
- Real ExtentA, ExtentB, Separation;
- int i, k;
-
- // Calculate B to A rotation matrix
- for (i = 0; i < 3; i++)
- {
- for (k = 0; k < 3; k++)
- {
- R[i, k] = Vector3::Dot(RotA[i], RotB[k]);
- AR[i, k] = Math::Abs(R[i, k]);
- }
- }
-
- // Vector separating the centers of Box B and of Box A
- Vector3 vSepWS = obb.GetCenter() - GetCenter();
-
- // Rotated into Box A's coordinates
- Vector3 vSepA = Vector3(Vector3::Dot(vSepWS, RotA[0]), Vector3::Dot(vSepWS, RotA[1]), Vector3::Dot(vSepWS, RotA[2]));
-
- // Test if any of A's basis vectors separate the box
- for (i = 0; i < 3; i++)
- {
- ExtentA = SizeA[i];
- ExtentB = Vector3::Dot(SizeB, Vector3(AR[i, 0], AR[i, 1], AR[i, 2]));
- Separation = Math::Abs(vSepA[i]);
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType::Disjoint;
- }
-
- // Test if any of B's basis vectors separate the box
- for (k = 0; k < 3; k++)
- {
- ExtentA = Vector3::Dot(SizeA, Vector3(AR[0, k], AR[1, k], AR[2, k]));
- ExtentB = SizeB[k];
- Separation = Math::Abs(Vector3::Dot(vSepA, Vector3(R[0, k], R[1, k], R[2, k])));
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType::Disjoint;
- }
-
- // Now test Cross Products of each basis vector combination ( A[i], B[k] )
- for (i = 0; i < 3; i++)
- {
- for (k = 0; k < 3; k++)
- {
- int i1 = (i + 1) % 3, i2 = (i + 2) % 3;
- int k1 = (k + 1) % 3, k2 = (k + 2) % 3;
- ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k];
- ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1];
- Separation = Math::Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]);
- if (Separation > ExtentA + ExtentB)
- return ContainmentType::Disjoint;
- }
- }
-
- // No separating axis found, the boxes overlap
- return ContainmentType::Intersects;
-}*/
-
bool OrientedBoundingBox::Intersects(const Ray& ray, Vector3& point) const
{
// Put ray in box space
- Matrix invTrans;
- Matrix::Invert(Transformation, invTrans);
-
Ray bRay;
- Vector3::TransformNormal(ray.Direction, invTrans, bRay.Direction);
- Vector3::TransformCoordinate(ray.Position, invTrans, bRay.Position);
+ Transformation.WorldToLocalVector(ray.Direction, bRay.Direction);
+ Transformation.WorldToLocal(ray.Position, bRay.Position);
// Perform a regular ray to BoundingBox check
- const BoundingBox bb = BoundingBox(-Extents, Extents);
+ const BoundingBox bb(-Extents, Extents);
const bool intersects = CollisionsHelper::RayIntersectsBox(bRay, bb, point);
// Put the result intersection back to world
if (intersects)
- Vector3::TransformCoordinate(point, Transformation, point);
+ Transformation.LocalToWorld(point, point);
return intersects;
}
@@ -366,19 +225,16 @@ bool OrientedBoundingBox::Intersects(const Ray& ray, Real& distance) const
bool OrientedBoundingBox::Intersects(const Ray& ray, Real& distance, Vector3& normal) const
{
// Put ray in box space
- Matrix invTrans;
- Matrix::Invert(Transformation, invTrans);
-
Ray bRay;
- Vector3::TransformNormal(ray.Direction, invTrans, bRay.Direction);
- Vector3::TransformCoordinate(ray.Position, invTrans, bRay.Position);
+ Transformation.WorldToLocalVector(ray.Direction, bRay.Direction);
+ Transformation.WorldToLocal(ray.Position, bRay.Position);
// Perform a regular ray to BoundingBox check
const BoundingBox bb(-Extents, Extents);
if (CollisionsHelper::RayIntersectsBox(bRay, bb, distance, normal))
{
// Put the result intersection back to world
- Vector3::TransformNormal(normal, Transformation, normal);
+ Transformation.LocalToWorldVector(normal, normal);
normal.Normalize();
return true;
}
diff --git a/Source/Engine/Core/Math/OrientedBoundingBox.cs b/Source/Engine/Core/Math/OrientedBoundingBox.cs
index 46c927c21..47c46f3cf 100644
--- a/Source/Engine/Core/Math/OrientedBoundingBox.cs
+++ b/Source/Engine/Core/Math/OrientedBoundingBox.cs
@@ -29,32 +29,16 @@ using Real = System.Single;
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
namespace FlaxEngine
{
- ///
- /// OrientedBoundingBox (OBB) is a rectangular block, much like an AABB (BoundingBox) but with an arbitrary orientation.
- ///
[Serializable]
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
- public struct OrientedBoundingBox : IEquatable, IFormattable
+ partial struct OrientedBoundingBox : IEquatable, IFormattable
{
- ///
- /// Half lengths of the box along each axis.
- ///
- public Vector3 Extents;
-
- ///
- /// The matrix which aligns and scales the box, and its translation vector represents the center of the box.
- ///
- public Matrix Transformation;
-
///
/// Creates an from a BoundingBox.
///
@@ -62,9 +46,9 @@ namespace FlaxEngine
/// Initially, the OBB is axis-aligned box, but it can be rotated and transformed later.
public OrientedBoundingBox(BoundingBox bb)
{
- Vector3 center = bb.Minimum + (bb.Maximum - bb.Minimum) / 2f;
+ Vector3 center = bb.Minimum + (bb.Maximum - bb.Minimum) * 0.5f;
Extents = bb.Maximum - center;
- Transformation = Matrix.Translation(center);
+ Transformation = new Transform(center);
}
///
@@ -75,7 +59,7 @@ namespace FlaxEngine
public OrientedBoundingBox(Vector3 extents, Matrix transformation)
{
Extents = extents;
- Transformation = transformation;
+ transformation.Decompose(out Transformation);
}
///
@@ -86,9 +70,9 @@ namespace FlaxEngine
/// Initially, the OrientedBoundingBox is axis-aligned box, but it can be rotated and transformed later.
public OrientedBoundingBox(Vector3 minimum, Vector3 maximum)
{
- Vector3 center = minimum + (maximum - minimum) / 2f;
+ Vector3 center = minimum + (maximum - minimum) * 0.5f;
Extents = maximum - center;
- Transformation = Matrix.Translation(center);
+ Transformation = new Transform(center);
}
///
@@ -100,19 +84,16 @@ namespace FlaxEngine
{
if ((points == null) || (points.Length == 0))
throw new ArgumentNullException(nameof(points));
-
- var minimum = Vector3.Maximum;
- var maximum = Vector3.Minimum;
-
- for (var i = 0; i < points.Length; ++i)
+ var minimum = points[0];
+ var maximum = points[0];
+ for (var i = 1; i < points.Length; ++i)
{
Vector3.Min(ref minimum, ref points[i], out minimum);
Vector3.Max(ref maximum, ref points[i], out maximum);
}
-
- Vector3 center = minimum + (maximum - minimum) / 2f;
+ Vector3 center = minimum + (maximum - minimum) * 0.5f;
Extents = maximum - center;
- Transformation = Matrix.Translation(center);
+ Transformation = new Transform(center);
}
///
@@ -121,25 +102,8 @@ namespace FlaxEngine
/// An array of points representing the eight corners of the bounding box.
public Vector3[] GetCorners()
{
- var xv = new Vector3(Extents.X, 0, 0);
- var yv = new Vector3(0, Extents.Y, 0);
- var zv = new Vector3(0, 0, Extents.Z);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
- Vector3 center = Transformation.TranslationVector;
-
var corners = new Vector3[8];
- corners[0] = center + xv + yv + zv;
- corners[1] = center + xv + yv - zv;
- corners[2] = center - xv + yv - zv;
- corners[3] = center - xv + yv + zv;
- corners[4] = center + xv - yv + zv;
- corners[5] = center + xv - yv - zv;
- corners[6] = center - xv - yv - zv;
- corners[7] = center - xv - yv + zv;
-
+ GetCorners(corners);
return corners;
}
@@ -147,28 +111,12 @@ namespace FlaxEngine
/// Retrieves the eight corners of the bounding box.
///
/// An array of points representing the eight corners of the bounding box.
- public void GetCorners(Vector3[] corners)
+ public unsafe void GetCorners(Vector3[] corners)
{
if (corners == null || corners.Length != 8)
throw new ArgumentException();
-
- var xv = new Vector3(Extents.X, 0, 0);
- var yv = new Vector3(0, Extents.Y, 0);
- var zv = new Vector3(0, 0, Extents.Z);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
- Vector3 center = Transformation.TranslationVector;
-
- corners[0] = center + xv + yv + zv;
- corners[1] = center + xv + yv - zv;
- corners[2] = center - xv + yv - zv;
- corners[3] = center - xv + yv + zv;
- corners[4] = center + xv - yv + zv;
- corners[5] = center + xv - yv - zv;
- corners[6] = center - xv - yv - zv;
- corners[7] = center - xv - yv + zv;
+ fixed (Vector3* ptr = corners)
+ GetCorners(ptr);
}
///
@@ -177,14 +125,10 @@ namespace FlaxEngine
/// An array of points representing the eight corners of the bounding box.
public unsafe void GetCorners(Vector3* corners)
{
- var xv = new Vector3(Extents.X, 0, 0);
- var yv = new Vector3(0, Extents.Y, 0);
- var zv = new Vector3(0, 0, Extents.Z);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
- Vector3 center = Transformation.TranslationVector;
+ Vector3 xv = Transformation.LocalToWorldVector(new Vector3(Extents.X, 0, 0));
+ Vector3 yv = Transformation.LocalToWorldVector(new Vector3(0, Extents.Y, 0));
+ Vector3 zv = Transformation.LocalToWorldVector(new Vector3(0, 0, Extents.Z));
+ Vector3 center = Transformation.Translation;
corners[0] = center + xv + yv + zv;
corners[1] = center + xv + yv - zv;
@@ -204,55 +148,32 @@ namespace FlaxEngine
{
if (corners == null)
throw new ArgumentNullException();
-
- var xv = new Vector3(Extents.X, 0, 0);
- var yv = new Vector3(0, Extents.Y, 0);
- var zv = new Vector3(0, 0, Extents.Z);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
- Vector3 center = Transformation.TranslationVector;
-
- corners.Add(center + xv + yv + zv);
- corners.Add(center + xv + yv - zv);
- corners.Add(center - xv + yv - zv);
- corners.Add(center - xv + yv + zv);
- corners.Add(center + xv - yv + zv);
- corners.Add(center + xv - yv - zv);
- corners.Add(center - xv - yv - zv);
- corners.Add(center - xv - yv + zv);
+ corners.AddRange(GetCorners());
}
///
/// Transforms this box using a transformation matrix.
///
/// The transformation matrix.
- ///
- /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which
- /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy.
- ///
+ /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy.
public void Transform(ref Matrix mat)
{
- Transformation *= mat;
+ mat.Decompose(out var transform);
+ Transformation = transform.LocalToWorld(Transformation);
}
///
/// Transforms this box using a transformation matrix.
///
/// The transformation matrix.
- ///
- /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which
- /// scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy.
- ///
+ /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which scales the Extents and keeps the Transformation matrix for rotation only, and that preserves collision detection accuracy.
public void Transform(Matrix mat)
{
- Transformation *= mat;
+ Transform(ref mat);
}
///
- /// Scales the by scaling its Extents without affecting the Transformation matrix,
- /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
+ /// Scales the by scaling its Extents without affecting the Transformation matrix, By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
///
///
public void Scale(ref Vector3 scaling)
@@ -261,8 +182,7 @@ namespace FlaxEngine
}
///
- /// Scales the by scaling its Extents without affecting the Transformation matrix,
- /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
+ /// Scales the by scaling its Extents without affecting the Transformation matrix, By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
///
///
public void Scale(Vector3 scaling)
@@ -271,8 +191,7 @@ namespace FlaxEngine
}
///
- /// Scales the by scaling its Extents without affecting the Transformation matrix,
- /// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
+ /// Scales the by scaling its Extents without affecting the Transformation matrix, By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
///
///
public void Scale(Real scaling)
@@ -286,7 +205,7 @@ namespace FlaxEngine
/// the translation vector.
public void Translate(ref Vector3 translation)
{
- Transformation.TranslationVector += translation;
+ Transformation.Translation += translation;
}
///
@@ -295,14 +214,13 @@ namespace FlaxEngine
/// the translation vector.
public void Translate(Vector3 translation)
{
- Transformation.TranslationVector += translation;
+ Transformation.Translation += translation;
}
///
/// The size of the if no scaling is applied to the transformation matrix.
///
- /// The property will return the actual size even if the scaling is applied using Scale method, but if the scaling is applied to transformation matrix, use GetSize Function instead.
- ///
+ /// The property will return the actual size even if the scaling is applied using Scale method, but if the scaling is applied to transformation matrix, use GetSize Function instead.
public Vector3 Size => Extents * 2;
///
@@ -312,13 +230,9 @@ namespace FlaxEngine
/// This method is computationally expensive, so if no scale is applied to the transformation matrix use property instead.
public Vector3 GetSize()
{
- var xv = new Vector3(Extents.X * 2, 0, 0);
- var yv = new Vector3(0, Extents.Y * 2, 0);
- var zv = new Vector3(0, 0, Extents.Z * 2);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
+ Vector3 xv = Transformation.LocalToWorldVector(new Vector3(Extents.X * 2, 0, 0));
+ Vector3 yv = Transformation.LocalToWorldVector(new Vector3(0, Extents.Y * 2, 0));
+ Vector3 zv = Transformation.LocalToWorldVector(new Vector3(0, 0, Extents.Z * 2));
return new Vector3(xv.Length, yv.Length, zv.Length);
}
@@ -328,20 +242,16 @@ namespace FlaxEngine
/// The size of the consideration
public Vector3 GetSizeSquared()
{
- var xv = new Vector3(Extents.X * 2, 0, 0);
- var yv = new Vector3(0, Extents.Y * 2, 0);
- var zv = new Vector3(0, 0, Extents.Z * 2);
- Vector3.TransformNormal(ref xv, ref Transformation, out xv);
- Vector3.TransformNormal(ref yv, ref Transformation, out yv);
- Vector3.TransformNormal(ref zv, ref Transformation, out zv);
-
+ Vector3 xv = Transformation.LocalToWorldVector(new Vector3(Extents.X * 2, 0, 0));
+ Vector3 yv = Transformation.LocalToWorldVector(new Vector3(0, Extents.Y * 2, 0));
+ Vector3 zv = Transformation.LocalToWorldVector(new Vector3(0, 0, Extents.Z * 2));
return new Vector3(xv.LengthSquared, yv.LengthSquared, zv.LengthSquared);
}
///
/// Returns the center of the .
///
- public Vector3 Center => Transformation.TranslationVector;
+ public Vector3 Center => Transformation.Translation;
///
/// Determines whether a contains a point.
@@ -351,10 +261,7 @@ namespace FlaxEngine
public ContainmentType Contains(ref Vector3 point)
{
// Transform the point into the obb coordinates
- Matrix.Invert(ref Transformation, out Matrix invTrans);
-
- Vector3.TransformCoordinate(ref point, ref invTrans, out Vector3 locPoint);
-
+ Transformation.WorldToLocal(ref point, out Vector3 locPoint);
locPoint.X = Math.Abs(locPoint.X);
locPoint.Y = Math.Abs(locPoint.Y);
locPoint.Z = Math.Abs(locPoint.Z);
@@ -377,47 +284,6 @@ namespace FlaxEngine
return Contains(ref point);
}
- ///
- /// Determines whether a contains an array of points>.
- ///
- /// The points array to test.
- /// The type of containment.
- public ContainmentType Contains(Vector3[] points)
- {
- Matrix.Invert(ref Transformation, out Matrix invTrans);
-
- var containsAll = true;
- var containsAny = false;
-
- for (var i = 0; i < points.Length; i++)
- {
- Vector3.TransformCoordinate(ref points[i], ref invTrans, out Vector3 locPoint);
-
- locPoint.X = Math.Abs(locPoint.X);
- locPoint.Y = Math.Abs(locPoint.Y);
- locPoint.Z = Math.Abs(locPoint.Z);
-
- // Simple axes-aligned BB check
- if (Mathf.NearEqual(locPoint.X, Extents.X) &&
- Mathf.NearEqual(locPoint.Y, Extents.Y) &&
- Mathf.NearEqual(locPoint.Z, Extents.Z))
- containsAny = true;
-
- if ((locPoint.X < Extents.X) && (locPoint.Y < Extents.Y) && (locPoint.Z < Extents.Z))
- containsAny = true;
- else
- containsAll = false;
- }
-
- if (containsAll)
- return ContainmentType.Contains;
-
- if (containsAny)
- return ContainmentType.Intersects;
-
- return ContainmentType.Disjoint;
- }
-
///
/// Determines whether a contains a .
///
@@ -427,10 +293,8 @@ namespace FlaxEngine
/// This method is not designed for which has a non-uniform scaling applied to its transformation matrix. But any type of scaling applied using Scale method will keep this method accurate.
public ContainmentType Contains(BoundingSphere sphere, bool ignoreScale = false)
{
- Matrix.Invert(ref Transformation, out Matrix invTrans);
-
// Transform sphere center into the obb coordinates
- Vector3.TransformCoordinate(ref sphere.Center, ref invTrans, out Vector3 locCenter);
+ Transformation.WorldToLocal(ref sphere.Center, out Vector3 locCenter);
Real locRadius;
if (ignoreScale)
@@ -439,235 +303,19 @@ namespace FlaxEngine
{
// Transform sphere radius into the obb coordinates
Vector3 vRadius = Vector3.UnitX * sphere.Radius;
- Vector3.TransformNormal(ref vRadius, ref invTrans, out vRadius);
+ Transformation.LocalToWorldVector(ref vRadius, out vRadius);
locRadius = vRadius.Length;
}
- //Perform regular BoundingBox to BoundingSphere containment check
+ // Perform regular BoundingBox to BoundingSphere containment check
Vector3 minusExtens = -Extents;
Vector3.Clamp(ref locCenter, ref minusExtens, ref Extents, out Vector3 vector);
Real distance = Vector3.DistanceSquared(ref locCenter, ref vector);
if (distance > locRadius * locRadius)
return ContainmentType.Disjoint;
-
if ((minusExtens.X + locRadius <= locCenter.X) && (locCenter.X <= Extents.X - locRadius) && (Extents.X - minusExtens.X > locRadius) && (minusExtens.Y + locRadius <= locCenter.Y) && (locCenter.Y <= Extents.Y - locRadius) && (Extents.Y - minusExtens.Y > locRadius) && (minusExtens.Z + locRadius <= locCenter.Z) && (locCenter.Z <= Extents.Z - locRadius) && (Extents.Z - minusExtens.Z > locRadius))
return ContainmentType.Contains;
-
- return ContainmentType.Intersects;
- }
-
- private static Float3[] GetRows(ref Matrix mat)
- {
- return new[]
- {
- new Float3(mat.M11, mat.M12, mat.M13),
- new Float3(mat.M21, mat.M22, mat.M23),
- new Float3(mat.M31, mat.M32, mat.M33)
- };
- }
-
- ///
- /// Check the intersection between two
- ///
- /// The OrientedBoundingBox to test.
- /// The type of containment the two objects have.
- /// For accuracy, The transformation matrix for both must not have any scaling applied to it. Anyway, scaling using Scale method will keep this method accurate.
- public ContainmentType Contains(ref OrientedBoundingBox obb)
- {
- ContainmentType cornersCheck = Contains(obb.GetCorners());
- if (cornersCheck != ContainmentType.Disjoint)
- return cornersCheck;
-
- //http://www.3dkingdoms.com/weekly/bbox.cpp
- Vector3 SizeA = Extents;
- Vector3 SizeB = obb.Extents;
- var RotA = GetRows(ref Transformation);
- var RotB = GetRows(ref obb.Transformation);
-
- var R = new Matrix(); // Rotation from B to A
- var AR = new Matrix(); // absolute values of R matrix, to use with box extents
-
- Real ExtentA, ExtentB, Separation;
- int i, k;
-
- // Calculate B to A rotation matrix
- for (i = 0; i < 3; i++)
- for (k = 0; k < 3; k++)
- {
- R[i, k] = Float3.Dot(RotA[i], RotB[k]);
- AR[i, k] = Math.Abs(R[i, k]);
- }
-
- // Vector separating the centers of Box B and of Box A
- Vector3 vSepWS = obb.Center - Center;
- // Rotated into Box A's coordinates
- var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2]));
-
- // Test if any of A's basis vectors separate the box
- for (i = 0; i < 3; i++)
- {
- ExtentA = SizeA[i];
- ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2]));
- Separation = Math.Abs(vSepA[i]);
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // Test if any of B's basis vectors separate the box
- for (k = 0; k < 3; k++)
- {
- ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k]));
- ExtentB = SizeB[k];
- Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k])));
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // Now test Cross Products of each basis vector combination ( A[i], B[k] )
- for (i = 0; i < 3; i++)
- for (k = 0; k < 3; k++)
- {
- int i1 = (i + 1) % 3, i2 = (i + 2) % 3;
- int k1 = (k + 1) % 3, k2 = (k + 2) % 3;
- ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k];
- ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1];
- Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]);
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // No separating axis found, the boxes overlap
- return ContainmentType.Intersects;
- }
-
- ///
- /// Check the intersection between an and a line defined by two points
- ///
- /// The first point in the line.
- /// The second point in the line.
- /// The type of containment the two objects have.
- /// For accuracy, The transformation matrix for the must not have any scaling applied to it. Anyway, scaling using Scale method will keep this method accurate.
- public ContainmentType ContainsLine(ref Vector3 L1, ref Vector3 L2)
- {
- ContainmentType cornersCheck = Contains(new[]
- {
- L1,
- L2
- });
- if (cornersCheck != ContainmentType.Disjoint)
- return cornersCheck;
-
- //http://www.3dkingdoms.com/weekly/bbox.cpp
- // Put line in box space
- Matrix.Invert(ref Transformation, out Matrix invTrans);
-
- Vector3.TransformCoordinate(ref L1, ref invTrans, out Vector3 LB1);
- Vector3.TransformCoordinate(ref L1, ref invTrans, out Vector3 LB2);
-
- // Get line midpoint and extent
- Vector3 LMid = (LB1 + LB2) * 0.5f;
- Vector3 L = LB1 - LMid;
- var LExt = new Vector3(Math.Abs(L.X), Math.Abs(L.Y), Math.Abs(L.Z));
-
- // Use Separating Axis Test
- // Separation vector from box center to line center is LMid, since the line is in box space
- if (Math.Abs(LMid.X) > Extents.X + LExt.X)
- return ContainmentType.Disjoint;
-
- if (Math.Abs(LMid.Y) > Extents.Y + LExt.Y)
- return ContainmentType.Disjoint;
-
- if (Math.Abs(LMid.Z) > Extents.Z + LExt.Z)
- return ContainmentType.Disjoint;
-
- // Cross products of line and each axis
- if (Math.Abs(LMid.Y * L.Z - LMid.Z * L.Y) > Extents.Y * LExt.Z + Extents.Z * LExt.Y)
- return ContainmentType.Disjoint;
-
- if (Math.Abs(LMid.X * L.Z - LMid.Z * L.X) > Extents.X * LExt.Z + Extents.Z * LExt.X)
- return ContainmentType.Disjoint;
-
- if (Math.Abs(LMid.X * L.Y - LMid.Y * L.X) > Extents.X * LExt.Y + Extents.Y * LExt.X)
- return ContainmentType.Disjoint;
-
- // No separating axis, the line intersects
- return ContainmentType.Intersects;
- }
-
- ///
- /// Check the intersection between an and
- ///
- /// The BoundingBox to test.
- /// The type of containment the two objects have.
- /// For accuracy, The transformation matrix for the must not have any scaling applied to it. Anyway, scaling using Scale method will keep this method accurate.
- public ContainmentType Contains(ref BoundingBox box)
- {
- ContainmentType cornersCheck = Contains(box.GetCorners());
- if (cornersCheck != ContainmentType.Disjoint)
- return cornersCheck;
-
- Vector3 boxCenter = box.Minimum + (box.Maximum - box.Minimum) / 2f;
- Vector3 boxExtents = box.Maximum - boxCenter;
-
- Vector3 SizeA = Extents;
- Vector3 SizeB = boxExtents;
- var RotA = GetRows(ref Transformation);
-
- Real ExtentA, ExtentB, Separation;
- int i, k;
-
- // Rotation from B to A
- Matrix.Invert(ref Transformation, out Matrix R);
- var AR = new Matrix(); // absolute values of R matrix, to use with box extents
-
- for (i = 0; i < 3; i++)
- for (k = 0; k < 3; k++)
- AR[i, k] = Math.Abs(R[i, k]);
-
- // Vector separating the centers of Box B and of Box A
- Vector3 vSepWS = boxCenter - Center;
- // Rotated into Box A's coordinates
- var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2]));
-
- // Test if any of A's basis vectors separate the box
- for (i = 0; i < 3; i++)
- {
- ExtentA = SizeA[i];
- ExtentB = Vector3.Dot(SizeB, new Vector3(AR[i, 0], AR[i, 1], AR[i, 2]));
- Separation = Math.Abs(vSepA[i]);
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // Test if any of B's basis vectors separate the box
- for (k = 0; k < 3; k++)
- {
- ExtentA = Vector3.Dot(SizeA, new Vector3(AR[0, k], AR[1, k], AR[2, k]));
- ExtentB = SizeB[k];
- Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(R[0, k], R[1, k], R[2, k])));
-
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // Now test Cross Products of each basis vector combination ( A[i], B[k] )
- for (i = 0; i < 3; i++)
- for (k = 0; k < 3; k++)
- {
- int i1 = (i + 1) % 3, i2 = (i + 2) % 3;
- int k1 = (k + 1) % 3, k2 = (k + 2) % 3;
- ExtentA = SizeA[i1] * AR[i2, k] + SizeA[i2] * AR[i1, k];
- ExtentB = SizeB[k1] * AR[i, k2] + SizeB[k2] * AR[i, k1];
- Separation = Math.Abs(vSepA[i2] * R[i1, k] - vSepA[i1] * R[i2, k]);
- if (Separation > ExtentA + ExtentB)
- return ContainmentType.Disjoint;
- }
-
- // No separating axis found, the boxes overlap
return ContainmentType.Intersects;
}
@@ -680,11 +328,9 @@ namespace FlaxEngine
public bool Intersects(ref Ray ray, out Vector3 point)
{
// Put ray in box space
- Matrix.Invert(ref Transformation, out Matrix invTrans);
-
Ray bRay;
- Vector3.TransformNormal(ref ray.Direction, ref invTrans, out bRay.Direction);
- Vector3.TransformCoordinate(ref ray.Position, ref invTrans, out bRay.Position);
+ Transformation.WorldToLocalVector(ref ray.Direction, out bRay.Direction);
+ Transformation.WorldToLocal(ref ray.Position, out bRay.Position);
// Perform a regular ray to BoundingBox check
var bb = new BoundingBox(-Extents, Extents);
@@ -692,7 +338,7 @@ namespace FlaxEngine
// Put the result intersection back to world
if (intersects)
- Vector3.TransformCoordinate(ref point, ref Transformation, out point);
+ Transformation.LocalToWorld(ref point, out point);
return intersects;
}
@@ -724,25 +370,6 @@ namespace FlaxEngine
return Intersects(ref ray, out Vector3 _);
}
- private Vector3[] GetLocalCorners()
- {
- var xv = new Vector3(Extents.X, 0, 0);
- var yv = new Vector3(0, Extents.Y, 0);
- var zv = new Vector3(0, 0, Extents.Z);
-
- var corners = new Vector3[8];
- corners[0] = +xv + yv + zv;
- corners[1] = +xv + yv - zv;
- corners[2] = -xv + yv - zv;
- corners[3] = -xv + yv + zv;
- corners[4] = +xv - yv + zv;
- corners[5] = +xv - yv - zv;
- corners[6] = -xv - yv - zv;
- corners[7] = -xv - yv + zv;
-
- return corners;
- }
-
///
/// Get the axis-aligned which contains all corners.
///
@@ -752,94 +379,6 @@ namespace FlaxEngine
return BoundingBox.FromPoints(GetCorners());
}
- ///
- /// Calculates the matrix required to transfer any point from one local coordinates to another.
- ///
- /// The source OrientedBoundingBox.
- /// The target OrientedBoundingBox.
- /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox.
- /// The matrix.
- public static Matrix GetBoxToBoxMatrix(ref OrientedBoundingBox a, ref OrientedBoundingBox b, bool noMatrixScaleApplied = false)
- {
- Matrix AtoB_Matrix;
-
- // Calculate B to A transformation matrix
- if (noMatrixScaleApplied)
- {
- var RotA = GetRows(ref a.Transformation);
- var RotB = GetRows(ref b.Transformation);
- AtoB_Matrix = new Matrix();
- int i, k;
- for (i = 0; i < 3; i++)
- for (k = 0; k < 3; k++)
- AtoB_Matrix[i, k] = Float3.Dot(RotB[i], RotA[k]);
- Vector3 v = b.Center - a.Center;
- AtoB_Matrix.M41 = Float3.Dot(v, RotA[0]);
- AtoB_Matrix.M42 = Float3.Dot(v, RotA[1]);
- AtoB_Matrix.M43 = Float3.Dot(v, RotA[2]);
- AtoB_Matrix.M44 = 1;
- }
- else
- {
- Matrix.Invert(ref a.Transformation, out Matrix AInvMat);
- AtoB_Matrix = b.Transformation * AInvMat;
- }
-
- return AtoB_Matrix;
- }
-
- ///
- /// Merge an OrientedBoundingBox B into another OrientedBoundingBox A, by expanding A to contain B and keeping A orientation.
- ///
- /// The to merge into it.
- /// The to be merged
- /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox.
- /// Unlike merging axis aligned boxes, The operation is not interchangeable, because it keeps A orientation and merge B into it.
- public static void Merge(ref OrientedBoundingBox a, ref OrientedBoundingBox b, bool noMatrixScaleApplied = false)
- {
- Matrix AtoB_Matrix = GetBoxToBoxMatrix(ref a, ref b, noMatrixScaleApplied);
-
- //Get B corners in A Space
- Vector3[] bCorners = b.GetLocalCorners();
- for (int i = 0; i < bCorners.Length; i++)
- Vector3.TransformCoordinate(ref bCorners[i], ref AtoB_Matrix, out bCorners[i]);
-
- //Get A local Bounding Box
- var A_LocalBB = new BoundingBox(-a.Extents, a.Extents);
-
- //Find B BoundingBox in A Space
- BoundingBox B_LocalBB = BoundingBox.FromPoints(bCorners);
-
- //Merger A and B local Bounding Boxes
- BoundingBox.Merge(ref B_LocalBB, ref A_LocalBB, out BoundingBox mergedBB);
-
- //Find the new Extents and Center, Transform Center back to world
- Vector3 newCenter = mergedBB.Minimum + (mergedBB.Maximum - mergedBB.Minimum) / 2f;
- a.Extents = mergedBB.Maximum - newCenter;
- Vector3.TransformCoordinate(ref newCenter, ref a.Transformation, out newCenter);
- a.Transformation.TranslationVector = newCenter;
- }
-
- ///
- /// Merge this OrientedBoundingBox into another OrientedBoundingBox, keeping the other OrientedBoundingBox orientation.
- ///
- /// The other to merge into.
- /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox.
- public void MergeInto(ref OrientedBoundingBox oob, bool noMatrixScaleApplied = false)
- {
- Merge(ref oob, ref this, noMatrixScaleApplied);
- }
-
- ///
- /// Merge another OrientedBoundingBox into this OrientedBoundingBox.
- ///
- /// The other to merge into this OrientedBoundingBox.
- /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox.
- public void Add(ref OrientedBoundingBox oob, bool noMatrixScaleApplied = false)
- {
- Merge(ref this, ref oob, noMatrixScaleApplied);
- }
-
///
/// Determines whether the specified is equal to this instance.
///
diff --git a/Source/Engine/Core/Math/OrientedBoundingBox.h b/Source/Engine/Core/Math/OrientedBoundingBox.h
index 7835de971..4a72419ef 100644
--- a/Source/Engine/Core/Math/OrientedBoundingBox.h
+++ b/Source/Engine/Core/Math/OrientedBoundingBox.h
@@ -3,19 +3,26 @@
#pragma once
-#include "Vector3.h"
-#include "Matrix.h"
-#include "CollisionsHelper.h"
+#include "Transform.h"
-// Oriented Bounding Box (OBB) is a rectangular block, much like an AABB (Bounding Box) but with an arbitrary orientation in 3D space.
-API_STRUCT(InBuild) struct FLAXENGINE_API OrientedBoundingBox
+enum class ContainmentType;
+
+///
+/// Oriented Bounding Box (OBB) is a rectangular block, much like an AABB (Bounding Box) but with an arbitrary orientation in 3D space.
+///
+API_STRUCT() struct FLAXENGINE_API OrientedBoundingBox
{
-public:
- // Half lengths of the box along each axis.
- Vector3 Extents;
+ DECLARE_SCRIPTING_TYPE_MINIMAL(OrientedBoundingBox);
- // The matrix which aligns and scales the box, and its translation vector represents the center of the box.
- Matrix Transformation;
+ ///
+ /// Half lengths of the box along each axis.
+ ///
+ API_FIELD() Vector3 Extents;
+
+ ///
+ /// The transformation which aligns and scales the box, and its translation vector represents the center of the box.
+ ///
+ API_FIELD() Transform Transformation;
public:
///
@@ -25,34 +32,16 @@ public:
{
}
- // Init
- // @param bb The BoundingBox to create from
- OrientedBoundingBox(const BoundingBox& bb);
-
- // Init
- // @param extents The half lengths of the box along each axis.
- // @param transformation The matrix which aligns and scales the box, and its translation vector represents the center of the box.
- OrientedBoundingBox(const Vector3& extents, const Matrix& transformation)
+ OrientedBoundingBox(const Vector3& extents, const Transform& transformation)
{
Extents = extents;
Transformation = transformation;
}
+ OrientedBoundingBox(const BoundingBox& bb);
+ OrientedBoundingBox(const Vector3& extents, const Matrix& transformation);
OrientedBoundingBox(const Vector3& extents, const Matrix3x3& rotationScale, const Vector3& translation);
-
- // Init
- // @param minimum The minimum vertex of the bounding box.
- // @param maximum The maximum vertex of the bounding box.
- OrientedBoundingBox(const Vector3& minimum, const Vector3& maximum)
- {
- const Vector3 center = minimum + (maximum - minimum) / 2.0f;
- Extents = maximum - center;
- Matrix::Translation(center, Transformation);
- }
-
- // Init
- // @param points The points that will be contained by the box.
- // @param pointCount Amount of the points in th array.
+ OrientedBoundingBox(const Vector3& minimum, const Vector3& maximum);
OrientedBoundingBox(Vector3 points[], int32 pointCount);
public:
@@ -77,9 +66,9 @@ public:
Vector3 GetSizeSquared() const;
// Gets the center of the OBB.
- Vector3 GetCenter() const
+ FORCE_INLINE Vector3 GetCenter() const
{
- return Transformation.GetTranslation();
+ return Transformation.Translation;
}
///
@@ -98,6 +87,7 @@ public:
// Transforms this box using a transformation matrix.
// @param mat The transformation matrix.
void Transform(const Matrix& matrix);
+ void Transform(const ::Transform& transform);
// Scales the OBB by scaling its Extents without affecting the Transformation matrix.
// By keeping Transformation matrix scaling-free, the collision detection methods will be more accurate.
@@ -119,7 +109,7 @@ public:
// @param translation the translation vector.
void Translate(const Vector3& translation)
{
- Transformation.SetTranslation(Transformation.GetTranslation() + translation);
+ Transformation.Translation += translation;
}
public:
@@ -140,12 +130,11 @@ public:
return result;
}
-private:
- static void GetRows(const Matrix& mat, Vector3 rows[3])
+ FORCE_INLINE OrientedBoundingBox operator*(const ::Transform& matrix) const
{
- rows[0] = Vector3(mat.M11, mat.M12, mat.M13);
- rows[1] = Vector3(mat.M21, mat.M22, mat.M23);
- rows[2] = Vector3(mat.M31, mat.M32, mat.M33);
+ OrientedBoundingBox result = *this;
+ result.Transform(matrix);
+ return result;
}
public:
@@ -157,8 +146,8 @@ public:
/// The result.
static void CreateCentered(const Vector3& center, const Vector3& size, OrientedBoundingBox& result)
{
- result.Extents = size / 2.0f;
- Matrix::Translation(center, result.Transformation);
+ result.Extents = size * 0.5f;
+ result.Transformation = ::Transform(center);
}
///
@@ -170,8 +159,7 @@ public:
static OrientedBoundingBox CreateCentered(const Vector3& center, const Vector3& size)
{
OrientedBoundingBox result;
- result.Extents = size / 2.0f;
- Matrix::Translation(center, result.Transformation);
+ CreateCentered(center, size, result);
return result;
}
@@ -181,12 +169,6 @@ public:
// @returns The type of containment the two objects have.
ContainmentType Contains(const Vector3& point, Real* distance = nullptr) const;
- // Determines whether a OBB contains an array of points.
- // @param pointsCnt Amount of points to test.
- // @param points The points array to test.
- // @returns The type of containment.
- ContainmentType Contains(int32 pointsCnt, Vector3 points[]) const;
-
// Determines whether a OBB contains a BoundingSphere.
// @param sphere The sphere to test.
// @param ignoreScale Optimize the check operation by assuming that OBB has no scaling applied.
diff --git a/Source/Engine/Core/Math/Transform.cpp b/Source/Engine/Core/Math/Transform.cpp
index 2a5b6c038..faca8a211 100644
--- a/Source/Engine/Core/Math/Transform.cpp
+++ b/Source/Engine/Core/Math/Transform.cpp
@@ -2,11 +2,17 @@
#include "Transform.h"
#include "Matrix.h"
-#include "Vector2.h"
+#include "Matrix3x3.h"
#include "../Types/String.h"
Transform Transform::Identity(Vector3(0, 0, 0));
+Transform::Transform(const Vector3& position, const Matrix3x3& rotationScale)
+ : Translation(position)
+{
+ rotationScale.Decompose(Scale, Orientation);
+}
+
String Transform::ToString() const
{
return String::Format(TEXT("{}"), *this);
@@ -122,11 +128,10 @@ void Transform::LocalToWorld(const Transform& other, Transform& result) const
result.Translation = Vector3(tmp.X + Translation.X, tmp.Y + Translation.Y, tmp.Z + Translation.Z);
}
-Vector3 Transform::LocalToWorldVector(const Vector3& vector) const
+void Transform::LocalToWorldVector(const Vector3& vector, Vector3& result) const
{
- Vector3 result = vector * Scale;
- Vector3::Transform(result, Orientation, result);
- return result;
+ Vector3 tmp = vector * Scale;
+ Vector3::Transform(tmp, Orientation, result);
}
void Transform::LocalToWorld(const Vector3& point, Vector3& result) const
@@ -145,9 +150,7 @@ void Transform::WorldToLocal(const Transform& other, Transform& result) const
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
const Quaternion invRotation = Orientation.Conjugated();
-
Quaternion::Multiply(invRotation, other.Orientation, result.Orientation);
result.Orientation.Normalize();
Float3::Multiply(other.Scale, invScale, result.Scale);
@@ -171,7 +174,7 @@ void Transform::WorldToLocal(const Vector3& point, Vector3& result) const
result *= invScale;
}
-Vector3 Transform::WorldToLocalVector(const Vector3& vector) const
+void Transform::WorldToLocalVector(const Vector3& vector, Vector3& result) const
{
Float3 invScale = Scale;
if (invScale.X != 0.0f)
@@ -180,13 +183,9 @@ Vector3 Transform::WorldToLocalVector(const Vector3& vector) const
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
const Quaternion invRotation = Orientation.Conjugated();
-
- Vector3 result;
Vector3::Transform(vector, invRotation, result);
-
- return result * invScale;
+ result *= invScale;
}
Transform Transform::Lerp(const Transform& t1, const Transform& t2, float amount)
diff --git a/Source/Engine/Core/Math/Transform.cs b/Source/Engine/Core/Math/Transform.cs
index f397f7a94..fdeabaa12 100644
--- a/Source/Engine/Core/Math/Transform.cs
+++ b/Source/Engine/Core/Math/Transform.cs
@@ -249,6 +249,41 @@ namespace FlaxEngine
return vector;
}
+ ///
+ /// Perform transformation of the given transform in local space
+ ///
+ /// Local space transform
+ /// World space transform
+ public void LocalToWorld(ref Transform other, out Transform result)
+ {
+ Quaternion.Multiply(ref Orientation, ref other.Orientation, out result.Orientation);
+ Float3.Multiply(ref Scale, ref other.Scale, out result.Scale);
+ result.Translation = LocalToWorld(other.Translation);
+ }
+
+ ///
+ /// Perform transformation of the given point in local space
+ ///
+ /// Local space point
+ /// World space point
+ public void LocalToWorld(ref Vector3 point, out Vector3 result)
+ {
+ Vector3 tmp = point * Scale;
+ Vector3.Transform(ref tmp, ref Orientation, out result);
+ result += Translation;
+ }
+
+ ///
+ /// Performs transformation of the given vector in local space to the world space of this transform.
+ ///
+ /// The local space vector.
+ /// World space vector
+ public void LocalToWorldVector(ref Vector3 vector, out Vector3 result)
+ {
+ Vector3 tmp = vector * Scale;
+ Vector3.Transform(ref tmp, ref Orientation, out result);
+ }
+
///
/// Perform transformation of the given points in local space
///
@@ -276,14 +311,12 @@ namespace FlaxEngine
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
Transform result;
result.Orientation = Orientation;
result.Orientation.Invert();
Quaternion.Multiply(ref result.Orientation, ref other.Orientation, out result.Orientation);
Float3.Multiply(ref other.Scale, ref invScale, out result.Scale);
result.Translation = WorldToLocal(other.Translation);
-
return result;
}
@@ -301,13 +334,9 @@ namespace FlaxEngine
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
- Quaternion invRotation = Orientation;
- invRotation.Invert();
-
+ Quaternion invRotation = Orientation.Conjugated();
Vector3 result = point - Translation;
Vector3.Transform(ref result, ref invRotation, out result);
-
return result * invScale;
}
@@ -325,15 +354,51 @@ namespace FlaxEngine
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
- Quaternion invRotation = Orientation;
- invRotation.Invert();
-
+ Quaternion invRotation = Orientation.Conjugated();
Vector3.Transform(ref vector, ref invRotation, out var result);
-
return result * invScale;
}
+ ///
+ /// Perform transformation of the given point in world space
+ ///
+ /// World space point
+ /// When the method completes, contains the local space point.
+ /// Local space point
+ public void WorldToLocal(ref Vector3 point, out Vector3 result)
+ {
+ var invScale = Scale;
+ if (invScale.X != 0.0f)
+ invScale.X = 1.0f / invScale.X;
+ if (invScale.Y != 0.0f)
+ invScale.Y = 1.0f / invScale.Y;
+ if (invScale.Z != 0.0f)
+ invScale.Z = 1.0f / invScale.Z;
+ Quaternion invRotation = Orientation.Conjugated();
+ Vector3 tmp = point - Translation;
+ Vector3.Transform(ref tmp, ref invRotation, out result);
+ result *= invScale;
+ }
+
+ ///
+ /// Perform transformation of the given vector in world space
+ ///
+ /// World space vector
+ /// Local space vector
+ public void WorldToLocalVector(ref Vector3 vector, out Vector3 result)
+ {
+ var invScale = Scale;
+ if (invScale.X != 0.0f)
+ invScale.X = 1.0f / invScale.X;
+ if (invScale.Y != 0.0f)
+ invScale.Y = 1.0f / invScale.Y;
+ if (invScale.Z != 0.0f)
+ invScale.Z = 1.0f / invScale.Z;
+ Quaternion invRotation = Orientation.Conjugated();
+ Vector3.Transform(ref vector, ref invRotation, out result);
+ result *= invScale;
+ }
+
///
/// Perform transformation of the given points in world space
///
@@ -348,10 +413,7 @@ namespace FlaxEngine
invScale.Y = 1.0f / invScale.Y;
if (invScale.Z != 0.0f)
invScale.Z = 1.0f / invScale.Z;
-
- Quaternion invRotation = Orientation;
- invRotation.Invert();
-
+ Quaternion invRotation = Orientation.Conjugated();
for (int i = 0; i < points.Length; i++)
{
result[i] = points[i] - Translation;
diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h
index 33a031fb1..33cf83d57 100644
--- a/Source/Engine/Core/Math/Transform.h
+++ b/Source/Engine/Core/Math/Transform.h
@@ -80,6 +80,8 @@ public:
{
}
+ Transform(const Vector3& position, const Matrix3x3& rotationScale);
+
public:
String ToString() const;
@@ -192,12 +194,24 @@ public:
return result;
}
+ ///
+ /// Performs transformation of the given vector in local space to the world space of this transform.
+ ///
+ /// The local space vector.
+ /// The world space vector.
+ void LocalToWorldVector(const Vector3& vector, Vector3& result) const;
+
///
/// Performs transformation of the given vector in local space to the world space of this transform.
///
/// The local space vector.
/// The world space vector.
- Vector3 LocalToWorldVector(const Vector3& vector) const;
+ Vector3 LocalToWorldVector(const Vector3& vector) const
+ {
+ Vector3 result;
+ LocalToWorldVector(vector, result);
+ return result;
+ }
///
/// Performs transformation of the given point in local space to the world space of this transform.
@@ -244,12 +258,24 @@ public:
return result;
}
+ ///
+ /// Performs transformation of the given vector in world space to the local space of this transform.
+ ///
+ /// The world space vector.
+ /// The local space vector.
+ void WorldToLocalVector(const Vector3& vector, Vector3& result) const;
+
///
/// Performs transformation of the given vector in world space to the local space of this transform.
///
/// The world space vector.
/// The local space vector.
- Vector3 WorldToLocalVector(const Vector3& vector) const;
+ Vector3 WorldToLocalVector(const Vector3& vector) const
+ {
+ Vector3 result;
+ WorldToLocalVector(vector, result);
+ return result;
+ }
public:
FORCE_INLINE Transform operator*(const Transform& other) const
diff --git a/Source/Engine/Level/Actors/BoxBrush.cpp b/Source/Engine/Level/Actors/BoxBrush.cpp
index 0f8e2d791..02e2a3973 100644
--- a/Source/Engine/Level/Actors/BoxBrush.cpp
+++ b/Source/Engine/Level/Actors/BoxBrush.cpp
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "BoxBrush.h"
+#include "Engine/Core/Math/Matrix.h"
#include "Engine/Content/Content.h"
#include "Engine/Serialization/Serialization.h"
#include "Engine/Level/Scene/Scene.h"
diff --git a/Source/Engine/Level/Actors/BoxBrush.h b/Source/Engine/Level/Actors/BoxBrush.h
index 718fd5d55..fc30aedc2 100644
--- a/Source/Engine/Level/Actors/BoxBrush.h
+++ b/Source/Engine/Level/Actors/BoxBrush.h
@@ -190,7 +190,7 @@ private:
FORCE_INLINE void UpdateBounds()
{
OrientedBoundingBox::CreateCentered(_center, _size, _bounds);
- _bounds.Transform(_transform.GetWorld());
+ _bounds.Transform(_transform);
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
}
diff --git a/Source/Engine/Level/Actors/BoxVolume.cpp b/Source/Engine/Level/Actors/BoxVolume.cpp
index 278b0bf0d..824745fd5 100644
--- a/Source/Engine/Level/Actors/BoxVolume.cpp
+++ b/Source/Engine/Level/Actors/BoxVolume.cpp
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "BoxVolume.h"
+#include "Engine/Core/Math/Matrix.h"
#include "Engine/Serialization/Serialization.h"
BoxVolume::BoxVolume(const SpawnParams& params)
@@ -54,11 +55,13 @@ namespace
else
Quaternion::LookRotation(dir, Vector3::Cross(Vector3::Cross(dir, Vector3::Up), dir), orientation);
const Vector3 up = orientation * Vector3::Up;
- Matrix::CreateWorld(min + vec * 0.5f, dir, up, box.Transformation);
- Matrix inv;
- Matrix::Invert(box.Transformation, inv);
+ Matrix world;
+ Matrix::CreateWorld(min + vec * 0.5f, dir, up, world);
+ world.Decompose(box.Transformation);
+ Matrix invWorld;
+ Matrix::Invert(world, invWorld);
Vector3 vecLocal;
- Vector3::TransformNormal(vec * 0.5f, inv, vecLocal);
+ Vector3::TransformNormal(vec * 0.5f, invWorld, vecLocal);
box.Extents.X = margin;
box.Extents.Y = margin;
box.Extents.Z = vecLocal.Z;
diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp
index f39d081bf..fb78110a1 100644
--- a/Source/Engine/Level/Actors/Decal.cpp
+++ b/Source/Engine/Level/Actors/Decal.cpp
@@ -15,7 +15,7 @@ Decal::Decal(const SpawnParams& params)
{
_world = Matrix::Scaling(_size);
_bounds.Extents = Vector3::Half;
- _bounds.Transformation = _world;
+ _world.Decompose(_bounds.Transformation);
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
}
@@ -30,8 +30,8 @@ void Decal::SetSize(const Vector3& value)
Transform t = _transform;
t.Scale *= _size;
t.GetWorld(_world);
- _bounds.Extents = Vector3::Half;
- _bounds.Transformation = _world;
+
+ _bounds.Transformation = t;
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
}
@@ -152,7 +152,7 @@ void Decal::OnTransformChanged()
t.GetWorld(_world);
_bounds.Extents = Vector3::Half;
- _bounds.Transformation = _world;
+ _bounds.Transformation = t;
_bounds.GetBoundingBox(_box);
BoundingSphere::FromBox(_box, _sphere);
diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h
index 3e2d6a18c..d6e608f6e 100644
--- a/Source/Engine/Level/Actors/Decal.h
+++ b/Source/Engine/Level/Actors/Decal.h
@@ -3,6 +3,7 @@
#pragma once
#include "../Actor.h"
+#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Math/OrientedBoundingBox.h"
#include "Engine/Content/Assets/MaterialBase.h"
#include "Engine/Content/AssetReference.h"
diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp
index efcb89ade..d3dcc2295 100644
--- a/Source/Engine/Physics/Colliders/BoxCollider.cpp
+++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp
@@ -60,11 +60,13 @@ namespace
else
Quaternion::LookRotation(dir, Float3::Cross(Float3::Cross(dir, Float3::Up), dir), orientation);
const Vector3 up = orientation * Vector3::Up;
- Matrix::CreateWorld(min + vec * 0.5f, dir, up, box.Transformation);
- Matrix inv;
- Matrix::Invert(box.Transformation, inv);
+ Matrix world;
+ Matrix::CreateWorld(min + vec * 0.5f, dir, up, world);
+ world.Decompose(box.Transformation);
+ Matrix invWorld;
+ Matrix::Invert(world, invWorld);
Vector3 vecLocal;
- Vector3::TransformNormal(vec * 0.5f, inv, vecLocal);
+ Vector3::TransformNormal(vec * 0.5f, invWorld, vecLocal);
box.Extents.X = margin;
box.Extents.Y = margin;
box.Extents.Z = vecLocal.Z;
diff --git a/Source/Engine/Physics/CollisionData.cs b/Source/Engine/Physics/CollisionData.cs
new file mode 100644
index 000000000..d84711ff6
--- /dev/null
+++ b/Source/Engine/Physics/CollisionData.cs
@@ -0,0 +1,72 @@
+// Copyright (c) 2014-2022 Wojciech Figat. All rights reserved.
+
+using System;
+
+namespace FlaxEngine
+{
+ partial class CollisionData
+ {
+ ///
+ /// Cooks the mesh collision data and updates the virtual asset. action cannot be performed on a main thread.
+ /// [Deprecated on 16.06.2022, expires on 16.06.2024]
+ ///
+ ///
+ /// Can be used only for virtual assets (see and ).
+ ///
+ /// The collision data type.
+ /// The source geometry vertex buffer with vertices positions. Cannot be empty.
+ /// The source data index buffer (triangles list). Uses 32-bit stride buffer. Cannot be empty. Length must be multiple of 3 (as 3 vertices build a triangle).
+ /// The convex mesh generation flags.
+ /// The convex mesh vertex limit. Use values in range [8;255]
+ /// True if failed, otherwise false.
+ [Obsolete("Deprecated in 1.4")]
+ public bool CookCollision(CollisionDataType type, Vector3[] vertices, uint[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
+ {
+ if (vertices == null)
+ throw new ArgumentNullException();
+ var tmp = new Float3[vertices.Length];
+ for (int i = 0; i < tmp.Length; i++)
+ tmp[i] = vertices[i];
+ return CookCollision(type, tmp, triangles, convexFlags, convexVertexLimit);
+ }
+
+ ///
+ /// Cooks the mesh collision data and updates the virtual asset. action cannot be performed on a main thread.
+ /// [Deprecated on 16.06.2022, expires on 16.06.2024]
+ ///
+ ///
+ /// Can be used only for virtual assets (see and ).
+ ///
+ /// The collision data type.
+ /// The source geometry vertex buffer with vertices positions. Cannot be empty.
+ /// The source data index buffer (triangles list). Uses 32-bit stride buffer. Cannot be empty. Length must be multiple of 3 (as 3 vertices build a triangle).
+ /// The convex mesh generation flags.
+ /// The convex mesh vertex limit. Use values in range [8;255]
+ /// True if failed, otherwise false.
+ [Obsolete("Deprecated in 1.4")]
+ public bool CookCollision(CollisionDataType type, Vector3[] vertices, int[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
+ {
+ if (vertices == null)
+ throw new ArgumentNullException();
+ var tmp = new Float3[vertices.Length];
+ for (int i = 0; i < tmp.Length; i++)
+ tmp[i] = vertices[i];
+ return CookCollision(type, tmp, triangles, convexFlags, convexVertexLimit);
+ }
+
+ ///
+ /// Extracts the collision data geometry into list of triangles.
+ /// [Deprecated on 16.06.2022, expires on 16.06.2024]
+ ///
+ /// The output vertex buffer.
+ /// The output index buffer.
+ [Obsolete("Deprecated in 1.4")]
+ public void ExtractGeometry(out Vector3[] vertexBuffer, out int[] indexBuffer)
+ {
+ ExtractGeometry(out Float3[] tmp, out indexBuffer);
+ vertexBuffer = new Vector3[tmp.Length];
+ for (int i = 0; i < tmp.Length; i++)
+ vertexBuffer[i] = tmp[i];
+ }
+ }
+}
diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
index 584211cf1..6951a95de 100644
--- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
+++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp
@@ -1074,8 +1074,10 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
}
// Write to objects buffer (this must match unpacking logic in HLSL)
+ Matrix localToWorldBounds;
+ object->Bounds.Transformation.GetWorld(localToWorldBounds);
Matrix worldToLocalBounds;
- Matrix::Invert(object->Bounds.Transformation, worldToLocalBounds);
+ Matrix::Invert(localToWorldBounds, worldToLocalBounds);
uint32 objectAddress = _objectsBuffer->Data.Count() / sizeof(Float4);
auto* objectData = _objectsBuffer->WriteReserve(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE);
objectData[0] = *(Float4*)&actorObjectBounds;
@@ -1103,13 +1105,13 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
yAxis = tileIndex == 2 || tileIndex == 3 ? Float3::Right : Float3::Up;
Float3::Cross(yAxis, zAxis, xAxis);
Float3 localSpaceOffset = -zAxis * object->Bounds.Extents;
- Float3::TransformNormal(xAxis, object->Bounds.Transformation, xAxis);
- Float3::TransformNormal(yAxis, object->Bounds.Transformation, yAxis);
- Float3::TransformNormal(zAxis, object->Bounds.Transformation, zAxis);
+ xAxis = object->Bounds.Transformation.LocalToWorldVector(xAxis);
+ yAxis = object->Bounds.Transformation.LocalToWorldVector(yAxis);
+ zAxis = object->Bounds.Transformation.LocalToWorldVector(zAxis);
xAxis.NormalizeFast();
yAxis.NormalizeFast();
zAxis.NormalizeFast();
- Float3::Transform(localSpaceOffset, object->Bounds.Transformation, tile->ViewPosition);
+ object->Bounds.Transformation.LocalToWorld(localSpaceOffset, tile->ViewPosition);
tile->ViewDirection = zAxis;
// Create view matrix
@@ -1122,7 +1124,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
OrientedBoundingBox viewBounds(object->Bounds);
viewBounds.Transform(tile->ViewMatrix);
Float3 viewExtent;
- Float3::TransformNormal(viewBounds.Extents, viewBounds.Transformation, viewExtent);
+ viewExtent = viewBounds.Transformation.LocalToWorldVector(viewBounds.Extents);
tile->ViewBoundsSize = viewExtent.GetAbsolute() * 2.0f;
// Per-tile data
diff --git a/Source/Engine/Serialization/JsonWriter.h b/Source/Engine/Serialization/JsonWriter.h
index 94130cbe7..6e5e07250 100644
--- a/Source/Engine/Serialization/JsonWriter.h
+++ b/Source/Engine/Serialization/JsonWriter.h
@@ -7,8 +7,6 @@
#include "Engine/Utilities/StringConverter.h"
struct CommonValue;
-struct Matrix;
-struct Transform;
class ISerializable;
// Helper macro for JSON serialization keys (reduces allocations count)
diff --git a/Source/Engine/UI/GUI/CanvasContainer.cs b/Source/Engine/UI/GUI/CanvasContainer.cs
index 60cfa2a78..88e844a1d 100644
--- a/Source/Engine/UI/GUI/CanvasContainer.cs
+++ b/Source/Engine/UI/GUI/CanvasContainer.cs
@@ -39,7 +39,8 @@ namespace FlaxEngine.GUI
child.Canvas.GetWorldMatrix(out var world);
Matrix.Translation((float)bounds.Extents.X, (float)bounds.Extents.Y, 0, out var offset);
- Matrix.Multiply(ref offset, ref world, out bounds.Transformation);
+ Matrix.Multiply(ref offset, ref world, out var boxWorld);
+ boxWorld.Decompose(out bounds.Transformation);
// Hit test
if (bounds.Intersects(ref ray, out Vector3 hitPoint))
diff --git a/Source/Engine/UI/UICanvas.cs b/Source/Engine/UI/UICanvas.cs
index 65d521bf9..1dc150399 100644
--- a/Source/Engine/UI/UICanvas.cs
+++ b/Source/Engine/UI/UICanvas.cs
@@ -330,7 +330,8 @@ namespace FlaxEngine
};
GetWorldMatrix(out Matrix world);
Matrix.Translation((float)bounds.Extents.X, (float)bounds.Extents.Y, 0, out Matrix offset);
- Matrix.Multiply(ref offset, ref world, out bounds.Transformation);
+ Matrix.Multiply(ref offset, ref world, out var boxWorld);
+ boxWorld.Decompose(out bounds.Transformation);
return bounds;
}
}
diff --git a/Source/Engine/UI/UIControl.cs b/Source/Engine/UI/UIControl.cs
index 0fe96f3cc..bd1d2e795 100644
--- a/Source/Engine/UI/UIControl.cs
+++ b/Source/Engine/UI/UIControl.cs
@@ -122,7 +122,8 @@ namespace FlaxEngine
canvasRoot.Canvas.GetWorldMatrix(out Matrix world);
Matrix.Translation(min.X + size.X * 0.5f, min.Y + size.Y * 0.5f, 0, out Matrix offset);
- Matrix.Multiply(ref offset, ref world, out bounds.Transformation);
+ Matrix.Multiply(ref offset, ref world, out var boxWorld);
+ boxWorld.Decompose(out bounds.Transformation);
return bounds;
}
}
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index 207f543cc..b8fa0b254 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -878,11 +878,15 @@ namespace Flax.Build.Bindings
contents.Append("protected ");
else if (fieldInfo.Access == AccessLevel.Private)
contents.Append("private ");
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsConstexpr)
+ contents.Append("const ");
+ else if (fieldInfo.IsStatic)
contents.Append("static ");
+
var returnValueType = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, classInfo);
contents.Append(returnValueType).Append(' ').Append(fieldInfo.Name);
- if (!useUnmanaged)
+
+ if (!useUnmanaged || fieldInfo.IsConstexpr)
{
var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, fieldInfo.DefaultValue, classInfo, fieldInfo.Type);
if (!string.IsNullOrEmpty(defaultValue))
@@ -1156,7 +1160,9 @@ namespace Flax.Build.Bindings
contents.Append("protected ");
else if (fieldInfo.Access == AccessLevel.Private)
contents.Append("private ");
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsConstexpr)
+ contents.Append("const ");
+ else if (fieldInfo.IsStatic)
contents.Append("static ");
string type;
@@ -1189,9 +1195,17 @@ namespace Flax.Build.Bindings
type = GenerateCSharpNativeToManaged(buildData, fieldInfo.Type, structureInfo);
contents.Append(type).Append(' ').Append(fieldInfo.Name);
- // Static fields are using C++ static value accessed via getter function binding
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsConstexpr)
{
+ // Compile-time constant
+ var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, fieldInfo.DefaultValue, structureInfo, fieldInfo.Type);
+ if (!string.IsNullOrEmpty(defaultValue))
+ contents.Append(" = ").Append(defaultValue);
+ contents.AppendLine(";");
+ }
+ else if (fieldInfo.IsStatic)
+ {
+ // Static fields are using C++ static value accessed via getter function binding
contents.AppendLine();
contents.AppendLine(indent + "{");
indent += " ";
@@ -1386,7 +1400,7 @@ namespace Flax.Build.Bindings
else if (type is InjectCodeInfo injectCodeInfo && string.Equals(injectCodeInfo.Lang, "csharp", StringComparison.OrdinalIgnoreCase))
{
// `using` directives needs to go above the generated code
- foreach(var code in injectCodeInfo.Code.Split(';'))
+ foreach (var code in injectCodeInfo.Code.Split(';'))
{
if (code.StartsWith("using"))
CSharpUsedNamespaces.Add(code.Substring(6));
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
index ae4b71271..32a35d1e9 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs
@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
partial class BindingsGenerator
{
private static readonly Dictionary TypeCache = new Dictionary();
- private const int CacheVersion = 14;
+ private const int CacheVersion = 15;
internal static void Write(BinaryWriter writer, string e)
{
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
index 2908695e0..e96365d8b 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
@@ -1384,7 +1384,7 @@ namespace Flax.Build.Bindings
private static bool GenerateCppAutoSerializationSkip(BuildData buildData, ApiTypeInfo caller, MemberInfo memberInfo, TypeInfo typeInfo)
{
- if (memberInfo.IsStatic)
+ if (memberInfo.IsStatic || memberInfo.IsConstexpr)
return true;
if (memberInfo.Access != AccessLevel.Public && !memberInfo.HasAttribute("Serialize"))
return true;
@@ -1691,7 +1691,7 @@ namespace Flax.Build.Bindings
// Fields
foreach (var fieldInfo in classInfo.Fields)
{
- if (!useScripting || !useCSharp || fieldInfo.IsHidden)
+ if (!useScripting || !useCSharp || fieldInfo.IsHidden || fieldInfo.IsConstexpr)
continue;
if (fieldInfo.Getter != null)
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Getter, "{0}");
@@ -1853,6 +1853,9 @@ namespace Flax.Build.Bindings
// Fields
foreach (var fieldInfo in structureInfo.Fields)
{
+ if (fieldInfo.IsConstexpr)
+ continue;
+
// Static fields are using C++ static value accessed via getter function binding
if (fieldInfo.IsStatic)
{
@@ -1977,7 +1980,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < structureInfo.Fields.Count; i++)
{
var fieldInfo = structureInfo.Fields[i];
- if (fieldInfo.IsReadOnly || fieldInfo.IsStatic || fieldInfo.Access == AccessLevel.Private)
+ if (fieldInfo.IsReadOnly || fieldInfo.IsStatic || fieldInfo.IsConstexpr || fieldInfo.Access == AccessLevel.Private)
continue;
if (i == 0)
contents.AppendLine($" if (name == TEXT(\"{fieldInfo.Name}\"))");
@@ -1993,7 +1996,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < structureInfo.Fields.Count; i++)
{
var fieldInfo = structureInfo.Fields[i];
- if (fieldInfo.IsReadOnly || fieldInfo.IsStatic || fieldInfo.Access == AccessLevel.Private)
+ if (fieldInfo.IsReadOnly || fieldInfo.IsStatic || fieldInfo.IsConstexpr || fieldInfo.Access == AccessLevel.Private)
continue;
if (i == 0)
contents.AppendLine($" if (name == TEXT(\"{fieldInfo.Name}\"))");
@@ -2205,7 +2208,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < structureInfo.Fields.Count; i++)
{
var fieldInfo = structureInfo.Fields[i];
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue;
var fieldType = fieldInfo.Type;
var fieldApiType = FindApiTypeInfo(buildData, fieldType, structureInfo);
@@ -2450,7 +2453,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < fields.Count; i++)
{
var fieldInfo = fields[i];
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue;
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
@@ -2482,7 +2485,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < fields.Count; i++)
{
var fieldInfo = fields[i];
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue;
CppNonPodTypesConvertingGeneration = true;
@@ -2531,7 +2534,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < fields.Count; i++)
{
var fieldInfo = fields[i];
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue;
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
@@ -2566,7 +2569,7 @@ namespace Flax.Build.Bindings
for (var i = 0; i < fields.Count; i++)
{
var fieldInfo = fields[i];
- if (fieldInfo.IsStatic)
+ if (fieldInfo.IsStatic || fieldInfo.IsConstexpr)
continue;
CppNonPodTypesConvertingGeneration = true;
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
index 457787a22..e9c017692 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
@@ -1155,6 +1155,11 @@ namespace Flax.Build.Bindings
desc.IsStatic = true;
context.Tokenizer.NextToken();
}
+ else if (!desc.IsConstexpr && token.Value == "constexpr")
+ {
+ desc.IsConstexpr = true;
+ context.Tokenizer.NextToken();
+ }
else if (!isMutable && token.Value == "mutable")
{
isMutable = true;
diff --git a/Source/Tools/Flax.Build/Bindings/MemberInfo.cs b/Source/Tools/Flax.Build/Bindings/MemberInfo.cs
index 842aa2f54..1422e25a7 100644
--- a/Source/Tools/Flax.Build/Bindings/MemberInfo.cs
+++ b/Source/Tools/Flax.Build/Bindings/MemberInfo.cs
@@ -12,6 +12,7 @@ namespace Flax.Build.Bindings
public string Name;
public string[] Comment;
public bool IsStatic;
+ public bool IsConstexpr;
public bool IsDeprecated;
public bool IsHidden;
public AccessLevel Access;
@@ -27,6 +28,7 @@ namespace Flax.Build.Bindings
writer.Write(Name);
BindingsGenerator.Write(writer, Comment);
writer.Write(IsStatic);
+ writer.Write(IsConstexpr);
writer.Write(IsDeprecated);
writer.Write(IsHidden);
writer.Write((byte)Access);
@@ -38,6 +40,7 @@ namespace Flax.Build.Bindings
Name = reader.ReadString();
Comment = BindingsGenerator.Read(reader, Comment);
IsStatic = reader.ReadBoolean();
+ IsConstexpr = reader.ReadBoolean();
IsDeprecated = reader.ReadBoolean();
IsHidden = reader.ReadBoolean();
Access = (AccessLevel)reader.ReadByte();