From f287ed6c300184c5787e3f380fa6bbb882d6623a Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Tue, 24 Oct 2023 19:59:47 +0200
Subject: [PATCH 01/79] init
---
Source/Engine/Core/Math/Float2.cs | 27 +++++++++++++++++++++++++++
Source/Engine/Core/Math/Vector3.cs | 15 +++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/Source/Engine/Core/Math/Float2.cs b/Source/Engine/Core/Math/Float2.cs
index 3ca6f51d7..4ded4cf92 100644
--- a/Source/Engine/Core/Math/Float2.cs
+++ b/Source/Engine/Core/Math/Float2.cs
@@ -1273,6 +1273,33 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// funcion for grid snaping snap to absolute world grid
+ ///
desined for snaping using a ray / draging object
+ ///
+ ///
+ ///
+ /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
+ public static Float2 SnapToGrid(Float2 Translation, Float2 GridSize)
+ {
+ Translation.X = Mathf.Ceil((Translation.X - (GridSize.X * 0.5f)) / GridSize.Y) * GridSize.X;
+ Translation.Y = Mathf.Ceil((Translation.Y - (GridSize.Y * 0.5f)) / GridSize.X) * GridSize.Y;
+ return Translation;
+ }
+ ///
+ /// funcion for grid snaping snap to absolute world grid
+ ///
desined for snaping using a ray / draging object
+ ///
+ ///
+ ///
+ /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
+ public static Float2 SnapToGrid(Float2 Translation, float GridSize)
+ {
+ Translation.X = Mathf.Ceil((Translation.X - (GridSize * 0.5f)) / GridSize) * GridSize;
+ Translation.Y = Mathf.Ceil((Translation.Y - (GridSize * 0.5f)) / GridSize) * GridSize;
+ return Translation;
+ }
+
///
/// Adds two vectors.
///
diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs
index 280093619..b7cc396ee 100644
--- a/Source/Engine/Core/Math/Vector3.cs
+++ b/Source/Engine/Core/Math/Vector3.cs
@@ -1671,6 +1671,21 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// funcion for grid snaping snap to absolute world grid
+ ///
desined for snaping using a ray / draging object
+ ///
+ ///
+ ///
+ /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
+ public static Vector3 SnapToGrid(Vector3 Translation, float GridSize)
+ {
+ Translation.X = Mathr.Ceil((Translation.X - (GridSize * 0.5f)) / GridSize) * GridSize;
+ Translation.Y = Mathr.Ceil((Translation.Y - (GridSize * 0.5f)) / GridSize) * GridSize;
+ Translation.Z = Mathr.Ceil((Translation.Z - (GridSize * 0.5f)) / GridSize) * GridSize;
+ return Translation;
+ }
+
///
/// Adds two vectors.
///
From 39aebc6c851adc3a45750fa996abbdbcfca2aed9 Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Wed, 25 Oct 2023 12:10:23 +0200
Subject: [PATCH 02/79] Update Vector3.cs
---
Source/Engine/Core/Math/Vector3.cs | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs
index b7cc396ee..ad1797644 100644
--- a/Source/Engine/Core/Math/Vector3.cs
+++ b/Source/Engine/Core/Math/Vector3.cs
@@ -1678,12 +1678,26 @@ namespace FlaxEngine
///
///
/// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Vector3 SnapToGrid(Vector3 Translation, float GridSize)
+ public static Vector3 SnapToGrid(Vector3 translation, float gridSize)
{
- Translation.X = Mathr.Ceil((Translation.X - (GridSize * 0.5f)) / GridSize) * GridSize;
- Translation.Y = Mathr.Ceil((Translation.Y - (GridSize * 0.5f)) / GridSize) * GridSize;
- Translation.Z = Mathr.Ceil((Translation.Z - (GridSize * 0.5f)) / GridSize) * GridSize;
- return Translation;
+ translation.X = Mathr.Ceil((translation.X - (gridSize * 0.5f)) / gridSize) * gridSize;
+ translation.Y = Mathr.Ceil((translation.Y - (gridSize * 0.5f)) / gridSize) * gridSize;
+ translation.Z = Mathr.Ceil((translation.Z - (gridSize * 0.5f)) / gridSize) * gridSize;
+ return translation;
+ }
+ ///
+ /// funcion for grid snaping snap to absolute world grid
+ ///
desined for snaping using a ray / draging object
+ ///
+ ///
+ ///
+ /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
+ public static Vector3 SnapToGrid(Vector3 translation, Float3 gridSize)
+ {
+ translation.X = Mathr.Ceil((translation.X - (gridSize.X * 0.5f)) / gridSize.X) * gridSize.X;
+ translation.Y = Mathr.Ceil((translation.Y - (gridSize.Y * 0.5f)) / gridSize.Y) * gridSize.Y;
+ translation.Z = Mathr.Ceil((translation.Z - (gridSize.Z * 0.5f)) / gridSize.Z) * gridSize.Z;
+ return translation;
}
///
From 4fb35579b5e8199a081a21e800bb1ed4390f3080 Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Wed, 25 Oct 2023 12:12:22 +0200
Subject: [PATCH 03/79] Update Float2.cs
---
Source/Engine/Core/Math/Float2.cs | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/Source/Engine/Core/Math/Float2.cs b/Source/Engine/Core/Math/Float2.cs
index 4ded4cf92..d33cc7fea 100644
--- a/Source/Engine/Core/Math/Float2.cs
+++ b/Source/Engine/Core/Math/Float2.cs
@@ -1280,11 +1280,11 @@ namespace FlaxEngine
///
///
/// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Float2 SnapToGrid(Float2 Translation, Float2 GridSize)
+ public static Float2 SnapToGrid(Float2 translation, Float2 gridSize)
{
- Translation.X = Mathf.Ceil((Translation.X - (GridSize.X * 0.5f)) / GridSize.Y) * GridSize.X;
- Translation.Y = Mathf.Ceil((Translation.Y - (GridSize.Y * 0.5f)) / GridSize.X) * GridSize.Y;
- return Translation;
+ translation.X = Mathf.Ceil((translation.X - (gridSize.X * 0.5f)) / gridSize.Y) * gridSize.X;
+ translation.Y = Mathf.Ceil((translation.Y - (gridSize.Y * 0.5f)) / gridSize.X) * gridSize.Y;
+ return translation;
}
///
/// funcion for grid snaping snap to absolute world grid
@@ -1295,9 +1295,9 @@ namespace FlaxEngine
/// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
public static Float2 SnapToGrid(Float2 Translation, float GridSize)
{
- Translation.X = Mathf.Ceil((Translation.X - (GridSize * 0.5f)) / GridSize) * GridSize;
- Translation.Y = Mathf.Ceil((Translation.Y - (GridSize * 0.5f)) / GridSize) * GridSize;
- return Translation;
+ translation.X = Mathf.Ceil((translation.X - (gridSize * 0.5f)) / gridSize) * gridSize;
+ translation.Y = Mathf.Ceil((translation.Y - (gridSize * 0.5f)) / gridSize) * gridSize;
+ return translation;
}
///
From ec0205871249c4e463269e135b06cf8fcfc7985b Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Wed, 25 Oct 2023 16:56:45 +0200
Subject: [PATCH 04/79] Update Float2.cs
---
Source/Engine/Core/Math/Float2.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Core/Math/Float2.cs b/Source/Engine/Core/Math/Float2.cs
index d33cc7fea..38fb7534a 100644
--- a/Source/Engine/Core/Math/Float2.cs
+++ b/Source/Engine/Core/Math/Float2.cs
@@ -1293,7 +1293,7 @@ namespace FlaxEngine
///
///
/// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Float2 SnapToGrid(Float2 Translation, float GridSize)
+ public static Float2 SnapToGrid(Float2 translation, float gridSize)
{
translation.X = Mathf.Ceil((translation.X - (gridSize * 0.5f)) / gridSize) * gridSize;
translation.Y = Mathf.Ceil((translation.Y - (gridSize * 0.5f)) / gridSize) * gridSize;
From 4fb2d3f7f3e89486e8aaba7d7ae441c8d7d26548 Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Thu, 7 Dec 2023 23:55:10 +0100
Subject: [PATCH 05/79] sync
---
Source/Editor/Gizmo/TransformGizmo.cs | 4 +-
.../Editor/Gizmo/TransformGizmoBase.Draw.cs | 255 ++++++++++--------
.../Gizmo/TransformGizmoBase.Selection.cs | 7 +-
Source/Editor/Gizmo/TransformGizmoBase.cs | 112 +++++++-
.../Editor/SceneGraph/Actors/FoliageNode.cs | 13 +-
Source/Editor/SceneGraph/SceneGraphNode.cs | 68 ++++-
.../Editor/Tools/Foliage/EditFoliageGizmo.cs | 6 +-
7 files changed, 330 insertions(+), 135 deletions(-)
diff --git a/Source/Editor/Gizmo/TransformGizmo.cs b/Source/Editor/Gizmo/TransformGizmo.cs
index 4a3fa39ba..f9d18bafd 100644
--- a/Source/Editor/Gizmo/TransformGizmo.cs
+++ b/Source/Editor/Gizmo/TransformGizmo.cs
@@ -255,9 +255,9 @@ namespace FlaxEditor.Gizmo
protected override int SelectionCount => _selectionParents.Count;
///
- protected override Transform GetSelectedObject(int index)
+ protected override SceneGraphNode GetSelectedObject(int index)
{
- return _selectionParents[index].Transform;
+ return _selectionParents[index];
}
///
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
index 0d421a17e..8cc049716 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
@@ -72,139 +72,160 @@ namespace FlaxEditor.Gizmo
const float gizmoModelsScale2RealGizmoSize = 0.075f;
Mesh sphereMesh, cubeMesh;
+ cubeMesh = _modelCube.LODs[0].Meshes[0];
+
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
+ Matrix.Multiply(ref m3, ref world, out m1);
+ mx1 = m1;
+ mx1.M41 += 0.05f;
+
switch (_activeMode)
{
- case Mode.Translate:
- {
- if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
- cubeMesh = _modelCube.LODs[0].Meshes[0];
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
- Matrix.Multiply(ref m3, ref world, out m1);
- mx1 = m1;
- mx1.M41 += 0.05f;
+ case Mode.Translate:
+ {
+ if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
- // X axis
- Matrix.RotationY(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
- // Y axis
- Matrix.RotationX(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
+ // X axis
+ Matrix.RotationY(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
- // Z axis
- Matrix.RotationX(Mathf.Pi, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+ // Y axis
+ Matrix.RotationX(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
- // XY plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
+ // Z axis
+ Matrix.RotationX(Mathf.Pi, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
- // ZX plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
+ // XY plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
- // YZ plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
+ // ZX plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
- // Center sphere
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+ // YZ plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
- break;
+ // Center sphere
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
+
+ case Mode.Rotate:
+ {
+ if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
+
+ // X axis
+ Matrix.RotationZ(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // Y axis
+ rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
+
+ // Z axis
+ Matrix.RotationX(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // Center box
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
+
+ case Mode.Scale:
+ {
+ if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
+ cubeMesh = _modelCube.LODs[0].Meshes[0];
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
+
+ // X axis
+ Matrix.RotationY(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref mx1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // Y axis
+ Matrix.RotationX(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Z axis
+ Matrix.RotationX(Mathf.Pi, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // XY plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // ZX plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // YZ plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Center box
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
}
-
- case Mode.Rotate:
+ if (verts != null && selectedvert != -1)
{
- if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
- Matrix.Multiply(ref m3, ref world, out m1);
- mx1 = m1;
- mx1.M41 += 0.05f;
+ Transform t = GetSelectedObject(0).Transform;
+ Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
+ Matrix matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
+ cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
- // X axis
- Matrix.RotationZ(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+ if (otherVerts != null && otherSelectedvert != -1)
+ {
+ t = otherTransform;
+ Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
+ matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
+ cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
+ DebugDraw.DrawLine(other, selected, Color.Aqua);
+ }
- // Y axis
- rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
+ //t = otherTransform;
+ //for (int i = 0; i < otherVerts.Length; i++)
+ //{
+ // Matrix matrix = new Transform(((otherVerts[i].Position * t.Orientation) * t.Scale) + t.Translation, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
+ // cubeMesh.Draw(ref renderContext, i == otherSelectedvert ? _materialAxisFocus : _materialSphere, ref matrix);
+ //}
- // Z axis
- Matrix.RotationX(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+ //t = GetSelectedObject(0).Transform;
- // Center box
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
-
- break;
- }
-
- case Mode.Scale:
- {
- if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
- cubeMesh = _modelCube.LODs[0].Meshes[0];
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
- Matrix.Multiply(ref m3, ref world, out m1);
- mx1 = m1;
- mx1.M41 -= 0.05f;
-
- // X axis
- Matrix.RotationY(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref mx1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // Y axis
- Matrix.RotationX(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Z axis
- Matrix.RotationX(Mathf.Pi, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // XY plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // ZX plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // YZ plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Center box
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
-
- break;
- }
}
}
}
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
index 86c0a6afe..1ebe0f254 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
@@ -27,7 +27,7 @@ namespace FlaxEditor.Gizmo
// Get center point
Vector3 center = Vector3.Zero;
for (int i = 0; i < count; i++)
- center += GetSelectedObject(i).Translation;
+ center += GetSelectedObject(i).Transform.Translation;
// Return arithmetic average or whatever it means
return center / count;
@@ -47,6 +47,11 @@ namespace FlaxEditor.Gizmo
private void SelectAxis()
{
+ if (Owner.IsControlDown)
+ {
+
+ }
+
// Get mouse ray
Ray ray = Owner.MouseRay;
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs
index 6123d348a..dfae81dc1 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.cs
@@ -108,7 +108,7 @@ namespace FlaxEditor.Gizmo
_startTransforms.Capacity = Mathf.NextPowerOfTwo(count);
for (var i = 0; i < count; i++)
{
- _startTransforms.Add(GetSelectedObject(i));
+ _startTransforms.Add(GetSelectedObject(i).Transform);
}
GetSelectedObjectsBounds(out _startBounds, out _navigationDirty);
@@ -139,7 +139,7 @@ namespace FlaxEditor.Gizmo
{
case PivotType.ObjectCenter:
if (SelectionCount > 0)
- Position = GetSelectedObject(0).Translation;
+ Position = GetSelectedObject(0).Transform.Translation;
break;
case PivotType.SelectionCenter:
Position = GetSelectionCenter();
@@ -180,7 +180,7 @@ namespace FlaxEditor.Gizmo
_screenScale = (float)(vLength.Length / GizmoScaleFactor * gizmoSize);
}
// Setup world
- Quaternion orientation = GetSelectedObject(0).Orientation;
+ Quaternion orientation = GetSelectedObject(0).Transform.Orientation;
_gizmoWorld = new Transform(position, orientation, new Float3(_screenScale));
if (_activeTransformSpace == TransformSpace.World && _activeMode != Mode.Scale)
{
@@ -394,6 +394,13 @@ namespace FlaxEditor.Gizmo
///
public override bool IsControllingMouse => _isTransforming;
+ //vertex snaping stff
+ Mesh.Vertex[] verts;
+ Mesh.Vertex[] otherVerts;
+ Transform otherTransform;
+ bool hasSelectedVertex;
+ int selectedvert;
+ int otherSelectedvert;
///
public override void Update(float dt)
{
@@ -429,12 +436,22 @@ namespace FlaxEditor.Gizmo
UpdateRotate(dt);
break;
}
+ VertexSnap();
}
else
{
// If nothing selected, try to select any axis
if (!isLeftBtnDown && !Owner.IsRightMouseButtonDown)
+ {
+ if (Owner.IsAltKeyDown)
+ SelectVertexSnaping();
SelectAxis();
+ }
+ else
+ {
+ verts = null;
+ otherVerts = null;
+ }
}
// Set positions of the gizmo
@@ -516,6 +533,93 @@ namespace FlaxEditor.Gizmo
// Update
UpdateMatrices();
}
+ void SelectVertexSnaping()
+ {
+ //this
+ if (GetSelectedObject(0).EditableObject is Actor e)
+ {
+ if (e is StaticModel model)
+ {
+ verts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+ var ray = Owner.MouseRay;
+ var bb = model.EditorBox;
+ //select vertex
+ if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 point))
+ {
+ point = GetSelectedObject(0).Transform.WorldToLocal(point);
+ Real lastdistance = Vector3.Distance(point, verts[0].Position);
+ for (int i = 0; i < verts.Length; i++)
+ {
+ var d = Vector3.Distance(point, verts[i].Position);
+ if (d <= lastdistance)
+ {
+ lastdistance = d;
+ selectedvert = i;
+ }
+ }
+ }
+ }
+ }
+ }
+ void VertexSnap()
+ {
+ Profiler.BeginEvent("VertexSnap");
+ //ray cast others
+ if (verts != null)
+ {
+ var ray = Owner.MouseRay;
+
+ SceneGraphNode.RayCastData rayCast = new SceneGraphNode.RayCastData()
+ {
+ Ray = ray,
+ Exclude = new List() { (Actor)GetSelectedObject(0).EditableObject },
+ Scan = new List() { typeof(StaticModel) }
+ };
+ var actor = GetSelectedObject(0).ParentScene.RayCast(ref rayCast, out var distance, out var _);
+ if (actor != null)
+ {
+ if (actor.EditableObject is StaticModel model)
+ {
+ otherTransform = model.Transform;
+ Vector3 p = rayCast.Ray.Position + (rayCast.Ray.Direction * distance);
+
+ otherVerts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+
+ p = actor.Transform.WorldToLocal(p);
+ Real lastdistance = Vector3.Distance(p, otherVerts[0].Position);
+
+ for (int i = 0; i < otherVerts.Length; i++)
+ {
+ var d = Vector3.Distance(p, otherVerts[i].Position);
+ if (d <= lastdistance)
+ {
+ lastdistance = d;
+ otherSelectedvert = i;
+ }
+ }
+ if(lastdistance > 25)
+ {
+ otherSelectedvert = -1;
+ otherVerts = null;
+ }
+ }
+ }
+ }
+
+ if (verts != null && otherVerts != null)
+ {
+ Transform t = GetSelectedObject(0).Transform;
+ Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
+
+ t = otherTransform;
+ Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
+
+ // Translation
+ _translationDelta = -(selected - other);
+ }
+
+ Profiler.EndEvent();
+ }
///
/// Gets a value indicating whether this tool can transform objects.
@@ -536,7 +640,7 @@ namespace FlaxEditor.Gizmo
/// Gets the selected object transformation.
///
/// The selected object index.
- protected abstract Transform GetSelectedObject(int index);
+ protected abstract SceneGraphNode GetSelectedObject(int index);
///
/// Gets the selected objects bounding box (contains the whole selection).
diff --git a/Source/Editor/SceneGraph/Actors/FoliageNode.cs b/Source/Editor/SceneGraph/Actors/FoliageNode.cs
index 9cb405092..50756170a 100644
--- a/Source/Editor/SceneGraph/Actors/FoliageNode.cs
+++ b/Source/Editor/SceneGraph/Actors/FoliageNode.cs
@@ -10,10 +10,21 @@ namespace FlaxEditor.SceneGraph.Actors
[HideInEditor]
public sealed class FoliageNode : ActorNode
{
+ private FoliageInstance instance;
+ ///
+ /// The selected instance index
+ ///
+ public int SelectedInstanceIndex;
+
///
- public FoliageNode(Actor actor)
+ public FoliageNode(Foliage actor, int selectedInstanceIndex = -1)
: base(actor)
{
+ SelectedInstanceIndex = selectedInstanceIndex;
+ if (selectedInstanceIndex != -1)
+ {
+ instance = actor.GetInstance(selectedInstanceIndex);
+ }
}
}
}
diff --git a/Source/Editor/SceneGraph/SceneGraphNode.cs b/Source/Editor/SceneGraph/SceneGraphNode.cs
index 672a239dc..4ca8034e1 100644
--- a/Source/Editor/SceneGraph/SceneGraphNode.cs
+++ b/Source/Editor/SceneGraph/SceneGraphNode.cs
@@ -13,6 +13,7 @@ using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Windows;
using FlaxEngine;
+using System.Runtime.CompilerServices;
namespace FlaxEditor.SceneGraph
{
@@ -216,6 +217,29 @@ namespace FlaxEditor.SceneGraph
/// The flags.
///
public FlagTypes Flags;
+
+ ///
+ /// The exclude list actors specyfaied in
+ ///
+ public List Exclude = new List();
+
+ ///
+ /// The scan for types
+ ///
+ public List Scan = new List();
+
+ ///
+ /// if this is true it will include the types specyfaied in
+ /// otherwise it will include all types excluding types specyfaied in
+ ///
+ public bool ExcludeScan;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ public RayCastData()
+ {
+ }
}
///
@@ -271,16 +295,18 @@ namespace FlaxEditor.SceneGraph
normal = Vector3.Up;
return null;
}
-
- // Check itself
SceneGraphNode minTarget = null;
Real minDistance = Real.MaxValue;
Vector3 minDistanceNormal = Vector3.Up;
- if (RayCastSelf(ref ray, out distance, out normal))
+ if (Mask(ref ray))
{
- minTarget = this;
- minDistance = distance;
- minDistanceNormal = normal;
+ // Check itself
+ if (RayCastSelf(ref ray, out distance, out normal))
+ {
+ minTarget = this;
+ minDistance = distance;
+ minDistanceNormal = normal;
+ }
}
// Check all children
@@ -294,12 +320,40 @@ namespace FlaxEditor.SceneGraph
minDistanceNormal = normal;
}
}
-
// Return result
distance = minDistance;
normal = minDistanceNormal;
return minTarget;
}
+ ///
+ /// Masks the objects base of and .
+ ///
+ /// The ray.
+ /// true if can pass through mask
+ private bool Mask(ref RayCastData ray)
+ {
+ //filter actors
+ for (int j = 0; j < ray.Exclude.Count; j++)
+ {
+ if ((EditableObject is Actor a) && a == ray.Exclude[j])
+ {
+ //remove form exclude
+ //because it is pased by ref and funcion is recursive it will slowly shrink the list untile nothing is left
+ //micro optimization
+ ray.Exclude.RemoveAt(j);
+ return false;
+ }
+ }
+ //filter types
+ for (int i = 0; i < ray.Scan.Count; i++)
+ {
+ if (EditableObject.GetType() != ray.Scan[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
///
/// Checks if given ray intersects with the node.
diff --git a/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs b/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
index 0c0172b36..1ba8ef445 100644
--- a/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
+++ b/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
@@ -3,6 +3,7 @@
using System;
using FlaxEditor.Gizmo;
using FlaxEditor.SceneGraph;
+using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Tools.Foliage.Undo;
using FlaxEngine;
@@ -69,7 +70,7 @@ namespace FlaxEditor.Tools.Foliage
}
///
- protected override Transform GetSelectedObject(int index)
+ protected override SceneGraphNode GetSelectedObject(int index)
{
var foliage = GizmoMode.SelectedFoliage;
if (!foliage)
@@ -77,8 +78,7 @@ namespace FlaxEditor.Tools.Foliage
var instanceIndex = GizmoMode.SelectedInstanceIndex;
if (instanceIndex < 0 || instanceIndex >= foliage.InstancesCount)
throw new InvalidOperationException("No foliage instance selected.");
- var instance = foliage.GetInstance(instanceIndex);
- return foliage.Transform.LocalToWorld(instance.Transform);
+ return new FoliageNode(foliage, instanceIndex);
}
///
From d8f110793be909d9e6ada7e37d6ae2c52a4180be Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Fri, 8 Dec 2023 18:41:52 +0100
Subject: [PATCH 06/79] done ?
---
.../Editor/Gizmo/TransformGizmoBase.Draw.cs | 2 +-
.../Editor/Gizmo/TransformGizmoBase.Types.cs | 16 +-
Source/Editor/Gizmo/TransformGizmoBase.cs | 369 +++++++++++-------
3 files changed, 236 insertions(+), 151 deletions(-)
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
index 8cc049716..33521a084 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
@@ -203,7 +203,7 @@ namespace FlaxEditor.Gizmo
}
if (verts != null && selectedvert != -1)
{
- Transform t = GetSelectedObject(0).Transform;
+ Transform t = thisTransform;
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
Matrix matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Types.cs b/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
index 377bd28a0..d622a8fcf 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
@@ -12,42 +12,42 @@ namespace FlaxEditor.Gizmo
///
/// None.
///
- None,
+ None = 0,
///
/// The X axis.
///
- X,
+ X = 1,
///
/// The Y axis.
///
- Y,
+ Y = 2,
///
/// The Z axis.
///
- Z,
+ Z = 4,
///
/// The XY plane.
///
- XY,
+ XY = X|Y,
///
/// The ZX plane.
///
- ZX,
+ ZX = Z|X,
///
/// The YZ plane.
///
- YZ,
+ YZ = Y|Z,
///
/// The center point.
///
- Center,
+ Center = 8,
};
///
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs
index dfae81dc1..51e363014 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.cs
@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEngine;
+using FlaxEditor.Surface;
namespace FlaxEditor.Gizmo
{
@@ -137,16 +138,22 @@ namespace FlaxEditor.Gizmo
{
switch (_activePivotType)
{
- case PivotType.ObjectCenter:
- if (SelectionCount > 0)
- Position = GetSelectedObject(0).Transform.Translation;
- break;
- case PivotType.SelectionCenter:
- Position = GetSelectionCenter();
- break;
- case PivotType.WorldOrigin:
- Position = Vector3.Zero;
- break;
+ case PivotType.ObjectCenter:
+ if (SelectionCount > 0)
+ Position = GetSelectedObject(0).Transform.Translation;
+ break;
+ case PivotType.SelectionCenter:
+ Position = GetSelectionCenter();
+ break;
+ case PivotType.WorldOrigin:
+ Position = Vector3.Zero;
+ break;
+ }
+ if(verts != null)
+ {
+ Transform t = thisTransform;
+ Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
+ Position += -(Position - selected);
}
Position += _translationDelta;
}
@@ -210,88 +217,88 @@ namespace FlaxEditor.Gizmo
Real intersection;
switch (_activeAxis)
{
- case Axis.X:
- {
- var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, 0, 0);
- }
- break;
- }
- case Axis.Y:
- {
- var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, _tDelta.Y, 0);
- }
- break;
- }
- case Axis.Z:
- {
- var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, 0, _tDelta.Z);
- }
- break;
- }
- case Axis.YZ:
- {
- if (ray.Intersects(ref planeYZ, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, _tDelta.Y, _tDelta.Z);
- }
- break;
- }
- case Axis.XY:
- {
- if (ray.Intersects(ref planeXY, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, _tDelta.Y, 0);
- }
- break;
- }
- case Axis.ZX:
- {
- if (ray.Intersects(ref planeZX, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, 0, _tDelta.Z);
- }
- break;
- }
- case Axis.Center:
- {
- var gizmoToView = Position - Owner.ViewPosition;
- var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- }
- delta = _tDelta;
- break;
- }
+ case Axis.X:
+ {
+ var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, 0, 0);
+ }
+ break;
+ }
+ case Axis.Y:
+ {
+ var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, _tDelta.Y, 0);
+ }
+ break;
+ }
+ case Axis.Z:
+ {
+ var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, 0, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.YZ:
+ {
+ if (ray.Intersects(ref planeYZ, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, _tDelta.Y, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.XY:
+ {
+ if (ray.Intersects(ref planeXY, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, _tDelta.Y, 0);
+ }
+ break;
+ }
+ case Axis.ZX:
+ {
+ if (ray.Intersects(ref planeZX, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, 0, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.Center:
+ {
+ var gizmoToView = Position - Owner.ViewPosition;
+ var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ }
+ delta = _tDelta;
+ break;
+ }
}
// Modifiers
@@ -364,30 +371,30 @@ namespace FlaxEditor.Gizmo
switch (_activeAxis)
{
- case Axis.X:
- case Axis.Y:
- case Axis.Z:
- {
- Float3 dir;
- if (_activeAxis == Axis.X)
- dir = Float3.Right * _gizmoWorld.Orientation;
- else if (_activeAxis == Axis.Y)
- dir = Float3.Up * _gizmoWorld.Orientation;
- else
- dir = Float3.Forward * _gizmoWorld.Orientation;
+ case Axis.X:
+ case Axis.Y:
+ case Axis.Z:
+ {
+ Float3 dir;
+ if (_activeAxis == Axis.X)
+ dir = Float3.Right * _gizmoWorld.Orientation;
+ else if (_activeAxis == Axis.Y)
+ dir = Float3.Up * _gizmoWorld.Orientation;
+ else
+ dir = Float3.Forward * _gizmoWorld.Orientation;
- Float3 viewDir = Owner.ViewPosition - Position;
- Float3.Dot(ref viewDir, ref dir, out float dot);
- if (dot < 0.0f)
- delta *= -1;
+ Float3 viewDir = Owner.ViewPosition - Position;
+ Float3.Dot(ref viewDir, ref dir, out float dot);
+ if (dot < 0.0f)
+ delta *= -1;
- Quaternion.RotationAxis(ref dir, delta, out _rotationDelta);
- break;
- }
+ Quaternion.RotationAxis(ref dir, delta, out _rotationDelta);
+ break;
+ }
- default:
- _rotationDelta = Quaternion.Identity;
- break;
+ default:
+ _rotationDelta = Quaternion.Identity;
+ break;
}
}
@@ -398,6 +405,8 @@ namespace FlaxEditor.Gizmo
Mesh.Vertex[] verts;
Mesh.Vertex[] otherVerts;
Transform otherTransform;
+ StaticModel SelectedModel;
+ Transform thisTransform => SelectedModel.Transform;
bool hasSelectedVertex;
int selectedvert;
int otherSelectedvert;
@@ -428,22 +437,25 @@ namespace FlaxEditor.Gizmo
{
switch (_activeMode)
{
- case Mode.Scale:
- case Mode.Translate:
- UpdateTranslateScale();
- break;
- case Mode.Rotate:
- UpdateRotate(dt);
- break;
+ case Mode.Translate:
+ UpdateTranslateScale();
+ VertexSnap();
+ break;
+ case Mode.Scale:
+ UpdateTranslateScale();
+ break;
+ case Mode.Rotate:
+ UpdateRotate(dt);
+ break;
}
- VertexSnap();
+
}
else
{
// If nothing selected, try to select any axis
if (!isLeftBtnDown && !Owner.IsRightMouseButtonDown)
{
- if (Owner.IsAltKeyDown)
+ if (Owner.IsAltKeyDown && _activeMode == Mode.Translate)
SelectVertexSnaping();
SelectAxis();
}
@@ -535,31 +547,72 @@ namespace FlaxEditor.Gizmo
}
void SelectVertexSnaping()
{
- //this
- if (GetSelectedObject(0).EditableObject is Actor e)
+ Vector3 point = Vector3.Zero;
+ var ray = Owner.MouseRay;
+ Real lastdistance = Real.MaxValue;
+ StaticModel Lastmodel = null;
+ int index = 0;
+
+ int i = 0;
+ //get first
+ for (; i < SelectionCount; i++)
{
- if (e is StaticModel model)
+ if (GetSelectedObject(i).EditableObject is StaticModel model)
{
- verts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
- var ray = Owner.MouseRay;
var bb = model.EditorBox;
- //select vertex
- if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 point))
+ if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 p))
{
- point = GetSelectedObject(0).Transform.WorldToLocal(point);
- Real lastdistance = Vector3.Distance(point, verts[0].Position);
- for (int i = 0; i < verts.Length; i++)
+ Lastmodel = model;
+ point = p;
+ index = 0;
+ break;
+ }
+ }
+ }
+
+ if (Lastmodel == null) // nothing to do return
+ return;
+
+ //find closest bounding box in selection
+ for (; i < SelectionCount; i++)
+ {
+ if (GetSelectedObject(i).EditableObject is StaticModel model)
+ {
+ var bb = model.EditorBox;
+ //check for other we might have one closer
+ var d = Vector3.Distance(model.Transform.Translation, ray.Position);
+ if (lastdistance < d)
+ {
+ if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 p))
{
- var d = Vector3.Distance(point, verts[i].Position);
- if (d <= lastdistance)
- {
- lastdistance = d;
- selectedvert = i;
- }
+ lastdistance = d;
+ Lastmodel = model;
+ point = p;
+ index = i;
}
}
}
}
+ SelectedModel = Lastmodel;
+
+ //find closest vertex to bounding box point (collision detection approximation)
+ //[ToDo] replace this with collision detection with is suporting concave shapes (compute shader)
+ point = thisTransform.WorldToLocal(point);
+
+ //[To Do] comlite this there is not suport for multy mesh model
+ verts = Lastmodel.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+
+ lastdistance = Vector3.Distance(point, verts[0].Position);
+ for (int j = 0; j < verts.Length; j++)
+ {
+ var d = Vector3.Distance(point, verts[j].Position);
+ if (d <= lastdistance)
+ {
+ lastdistance = d;
+ selectedvert = j;
+ }
+
+ }
}
void VertexSnap()
{
@@ -572,9 +625,14 @@ namespace FlaxEditor.Gizmo
SceneGraphNode.RayCastData rayCast = new SceneGraphNode.RayCastData()
{
Ray = ray,
- Exclude = new List() { (Actor)GetSelectedObject(0).EditableObject },
+ Exclude = new List() {},
Scan = new List() { typeof(StaticModel) }
};
+ for (int i = 0; i < SelectionCount; i++)
+ {
+ rayCast.Exclude.Add((Actor)GetSelectedObject(i).EditableObject);
+ }
+ //grab scene and raycast
var actor = GetSelectedObject(0).ParentScene.RayCast(ref rayCast, out var distance, out var _);
if (actor != null)
{
@@ -583,11 +641,13 @@ namespace FlaxEditor.Gizmo
otherTransform = model.Transform;
Vector3 p = rayCast.Ray.Position + (rayCast.Ray.Direction * distance);
+ //[To Do] comlite this there is not suport for multy mesh model
otherVerts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+ //find closest vertex to bounding box point (collision detection approximation)
+ //[ToDo] replace this with collision detection with is suporting concave shapes (compute shader)
p = actor.Transform.WorldToLocal(p);
Real lastdistance = Vector3.Distance(p, otherVerts[0].Position);
-
for (int i = 0; i < otherVerts.Length; i++)
{
var d = Vector3.Distance(p, otherVerts[i].Position);
@@ -597,6 +657,7 @@ namespace FlaxEditor.Gizmo
otherSelectedvert = i;
}
}
+
if(lastdistance > 25)
{
otherSelectedvert = -1;
@@ -608,19 +669,43 @@ namespace FlaxEditor.Gizmo
if (verts != null && otherVerts != null)
{
- Transform t = GetSelectedObject(0).Transform;
+ Transform t = thisTransform;
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
t = otherTransform;
Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
// Translation
- _translationDelta = -(selected - other);
+ var projection = -(selected - other);
+
+ //at some point
+ //Quaternion inverse = t.Orientation;
+ //inverse.Invert();
+ //projection *= inverse; //world to local
+ //flip mask
+ //var Not = ~_activeAxis;
+ //LockAxisWorld(Not, ref projection); //lock axis
+ //projection *= t.Orientation; //local to world
+
+ _translationDelta = projection;
}
Profiler.EndEvent();
}
+ ///
+ /// zeros the component using the
+ ///
+ public static void LockAxisWorld(Axis lockAxis, ref Vector3 v)
+ {
+ if (lockAxis.HasFlag(Axis.X))
+ v.X = 0;
+ if (lockAxis.HasFlag(Axis.Y))
+ v.Y = 0;
+ if (lockAxis.HasFlag(Axis.Z))
+ v.Z = 0;
+ }
+
///
/// Gets a value indicating whether this tool can transform objects.
///
From eb30344e77cdeee9c46a361ca859f9f76b4d18fa Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Fri, 8 Dec 2023 18:57:49 +0100
Subject: [PATCH 07/79] Update TransformGizmoBase.cs
---
Source/Editor/Gizmo/TransformGizmoBase.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs
index 51e363014..ddd3272ee 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.cs
@@ -439,7 +439,8 @@ namespace FlaxEditor.Gizmo
{
case Mode.Translate:
UpdateTranslateScale();
- VertexSnap();
+ if (Owner.UseSnapping)
+ VertexSnap();
break;
case Mode.Scale:
UpdateTranslateScale();
@@ -459,7 +460,7 @@ namespace FlaxEditor.Gizmo
SelectVertexSnaping();
SelectAxis();
}
- else
+ else if (Owner.IsAltKeyDown)
{
verts = null;
otherVerts = null;
From f65ded4501872447111eee2360ecc1a0397652b1 Mon Sep 17 00:00:00 2001
From: nothingTVatYT
Date: Thu, 14 Dec 2023 15:51:20 +0100
Subject: [PATCH 08/79] implement MoveFileToRecycleBin on Linux
---
Source/Engine/Content/Content.cpp | 2 +-
.../Engine/Platform/Linux/LinuxFileSystem.cpp | 66 +++++++++++++++++++
.../Engine/Platform/Linux/LinuxFileSystem.h | 3 +
3 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp
index 982ae599f..24bae188b 100644
--- a/Source/Engine/Content/Content.cpp
+++ b/Source/Engine/Content/Content.cpp
@@ -585,7 +585,7 @@ void Content::deleteFileSafety(const StringView& path, const Guid& id)
}
}
-#if PLATFORM_WINDOWS
+#if PLATFORM_WINDOWS || PLATFORM_LINUX
// Safety way - move file to the recycle bin
if (FileSystem::MoveFileToRecycleBin(path))
{
diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
index 97cde4a1c..8ff650f9f 100644
--- a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
+++ b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
@@ -24,6 +24,8 @@
#include
#include
+#include "ThirdParty/curl/curl.h"
+
const DateTime UnixEpoch(1970, 1, 1);
bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames)
@@ -511,6 +513,70 @@ out_error:
return true;
}
+bool LinuxFileSystem::MoveFileToRecycleBin(const StringView& path)
+{
+ String trashDir;
+ GetSpecialFolderPath(SpecialFolder::LocalAppData, trashDir);
+ trashDir += TEXT("/Trash");
+ String filesDir = trashDir + TEXT("/files");
+ String infoDir = trashDir + TEXT("/info");
+ String trashName = getBaseName(path);
+ String dst = filesDir / trashName;
+
+ int fd = -1;
+ if (FileExists(dst))
+ {
+ String ext = GetExtension(path);
+ dst = filesDir / getNameWithoutExtension(path) / TEXT("XXXXXX.") / ext;
+ char *base = dst.ToStringAnsi().Get();
+ char *extension = GetExtension(path).ToStringAnsi().Get();
+ int templateLength = strlen(base) + 7 + strlen(extension);
+ char *templateString = dst.ToStringAnsi().Get();
+ fd = mkstemps(templateString, ext.Length());
+ dst = filesDir / String(templateString);
+ trashName = getBaseName(dst);
+ }
+ if (fd != -1)
+ close(fd);
+
+ if (!MoveFile(dst, path, true))
+ {
+ // not MoveFile means success so write the info file
+ String infoFile = infoDir / trashName + TEXT(".trashinfo");
+ StringBuilder trashInfo;
+ const char *ansiPath = path.ToStringAnsi().Get();
+ char *encoded = curl_escape(ansiPath, strlen(ansiPath));
+ DateTime now = DateTime::Now();
+ String rfcDate = String::Format(TEXT("{0}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}"),
+ now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
+ trashInfo.AppendLine(TEXT("[Trash Info]")).Append(TEXT("Path=")).Append(encoded).Append(TEXT('\n'));
+ trashInfo.Append(TEXT("DeletionDate=")).Append(rfcDate).Append(TEXT("\n\0"));
+ free(encoded);
+ // a failure to write the info file is considered non-fatal according to the FreeDesktop.org specification
+ FileBase::WriteAllText(infoFile, trashInfo, Encoding::ANSI);
+ // return false on success as the Windows pendant does
+ return false;
+ }
+ return true;
+}
+
+String LinuxFileSystem::getBaseName(const StringView& path)
+{
+ String baseName = path.Substring(path.FindLast('/') + 1);
+ if (baseName.IsEmpty())
+ baseName = path;
+ return baseName;
+}
+
+String LinuxFileSystem::getNameWithoutExtension(const StringView& path)
+{
+ String baseName = getBaseName(path);
+ const int pos = baseName.FindLast('.');
+ if (pos > 0)
+ return baseName.Left(pos);
+ return baseName;
+}
+
bool LinuxFileSystem::getFilesFromDirectoryTop(Array& results, const char* path, const char* searchPattern)
{
size_t pathLength;
diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.h b/Source/Engine/Platform/Linux/LinuxFileSystem.h
index 6184d6720..0abe88084 100644
--- a/Source/Engine/Platform/Linux/LinuxFileSystem.h
+++ b/Source/Engine/Platform/Linux/LinuxFileSystem.h
@@ -24,6 +24,7 @@ public:
static bool GetChildDirectories(Array& results, const String& directory);
static bool FileExists(const StringView& path);
static bool DeleteFile(const StringView& path);
+ static bool MoveFileToRecycleBin(const StringView& path);
static uint64 GetFileSize(const StringView& path);
static bool IsReadOnly(const StringView& path);
static bool SetReadOnly(const StringView& path, bool isReadOnly);
@@ -50,6 +51,8 @@ private:
static bool getFilesFromDirectoryTop(Array& results, const char* path, const char* searchPattern);
static bool getFilesFromDirectoryAll(Array& results, const char* path, const char* searchPattern);
+ static String getBaseName(const StringView& path);
+ static String getNameWithoutExtension(const StringView& path);
};
#endif
From 8c45659b2a31e8af2488f377420749a8dc630a19 Mon Sep 17 00:00:00 2001
From: nothingTVatYT
Date: Thu, 14 Dec 2023 17:29:08 +0100
Subject: [PATCH 09/79] use own encoder and some more error handling
---
.../Engine/Platform/Linux/LinuxFileSystem.cpp | 74 ++++++++++++++-----
.../Engine/Platform/Linux/LinuxFileSystem.h | 1 +
2 files changed, 57 insertions(+), 18 deletions(-)
diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
index 8ff650f9f..da422f29a 100644
--- a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
+++ b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
@@ -24,8 +24,6 @@
#include
#include
-#include "ThirdParty/curl/curl.h"
-
const DateTime UnixEpoch(1970, 1, 1);
bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, Array& filenames)
@@ -436,6 +434,7 @@ bool LinuxFileSystem::MoveFile(const StringView& dst, const StringView& src, boo
return false;
}
}
+ LOG(Error, "Cannot copy {} to {}", src, dst);
return true;
}
return false;
@@ -518,22 +517,26 @@ bool LinuxFileSystem::MoveFileToRecycleBin(const StringView& path)
String trashDir;
GetSpecialFolderPath(SpecialFolder::LocalAppData, trashDir);
trashDir += TEXT("/Trash");
- String filesDir = trashDir + TEXT("/files");
- String infoDir = trashDir + TEXT("/info");
+ const String filesDir = trashDir + TEXT("/files");
+ const String infoDir = trashDir + TEXT("/info");
String trashName = getBaseName(path);
String dst = filesDir / trashName;
int fd = -1;
if (FileExists(dst))
{
- String ext = GetExtension(path);
- dst = filesDir / getNameWithoutExtension(path) / TEXT("XXXXXX.") / ext;
- char *base = dst.ToStringAnsi().Get();
- char *extension = GetExtension(path).ToStringAnsi().Get();
- int templateLength = strlen(base) + 7 + strlen(extension);
- char *templateString = dst.ToStringAnsi().Get();
- fd = mkstemps(templateString, ext.Length());
- dst = filesDir / String(templateString);
+ const String ext = GetExtension(path);
+ dst = filesDir / getNameWithoutExtension(path) + TEXT("XXXXXX.") + ext;
+ const char *templateString = dst.ToStringAnsi().Get();
+ char writableName[strlen(templateString) + 1];
+ strcpy(writableName, templateString);
+ fd = mkstemps(writableName, ext.Length() + 1);
+ if (fd < 0)
+ {
+ LOG(Error, "Cannot create a temporary file as {0}, errno={1}", String(writableName), errno);
+ return true;
+ }
+ dst = String(writableName);
trashName = getBaseName(dst);
}
if (fd != -1)
@@ -542,16 +545,23 @@ bool LinuxFileSystem::MoveFileToRecycleBin(const StringView& path)
if (!MoveFile(dst, path, true))
{
// not MoveFile means success so write the info file
- String infoFile = infoDir / trashName + TEXT(".trashinfo");
+ const String infoFile = infoDir / trashName + TEXT(".trashinfo");
StringBuilder trashInfo;
const char *ansiPath = path.ToStringAnsi().Get();
- char *encoded = curl_escape(ansiPath, strlen(ansiPath));
- DateTime now = DateTime::Now();
- String rfcDate = String::Format(TEXT("{0}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}"),
- now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
+ // in the worst case the length will be tripled
+ const int maxLength = strlen(ansiPath) * 3 + 1;
+ char encoded[maxLength];
+ if (!UrnEncodePath(ansiPath, encoded, maxLength))
+ {
+ // unlikely but better keep something
+ strcpy(encoded, ansiPath);
+ }
+ const DateTime now = DateTime::Now();
+ const String rfcDate = String::Format(TEXT("{0}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}"),
+ now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
trashInfo.AppendLine(TEXT("[Trash Info]")).Append(TEXT("Path=")).Append(encoded).Append(TEXT('\n'));
trashInfo.Append(TEXT("DeletionDate=")).Append(rfcDate).Append(TEXT("\n\0"));
- free(encoded);
+
// a failure to write the info file is considered non-fatal according to the FreeDesktop.org specification
FileBase::WriteAllText(infoFile, trashInfo, Encoding::ANSI);
// return false on success as the Windows pendant does
@@ -577,6 +587,34 @@ String LinuxFileSystem::getNameWithoutExtension(const StringView& path)
return baseName;
}
+bool LinuxFileSystem::UrnEncodePath(const char *path, char *result, const int maxLength)
+{
+ static auto digits = "0123456789ABCDEF";
+ const char *src = path;
+ char *dest = result;
+ while (*src)
+ {
+ if (*src <= 0x20 || *src > 0x7f || *src == '%')
+ {
+ if (dest - result + 4 > maxLength)
+ return false;
+ *dest++ = '%';
+ *dest++ = digits[*src>>4 & 0xf];
+ *dest = digits[*src & 0xf];
+ }
+ else
+ {
+ *dest = *src;
+ }
+ src++;
+ dest++;
+ if (dest - result == maxLength)
+ return false;
+ }
+ *dest = 0;
+ return true;
+}
+
bool LinuxFileSystem::getFilesFromDirectoryTop(Array& results, const char* path, const char* searchPattern)
{
size_t pathLength;
diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.h b/Source/Engine/Platform/Linux/LinuxFileSystem.h
index 0abe88084..ca02b4121 100644
--- a/Source/Engine/Platform/Linux/LinuxFileSystem.h
+++ b/Source/Engine/Platform/Linux/LinuxFileSystem.h
@@ -49,6 +49,7 @@ public:
private:
+ static bool UrnEncodePath(const char *path, char *result, int maxLength);
static bool getFilesFromDirectoryTop(Array& results, const char* path, const char* searchPattern);
static bool getFilesFromDirectoryAll(Array& results, const char* path, const char* searchPattern);
static String getBaseName(const StringView& path);
From bd3454008619e10b8303f138d8be94785c6c20a7 Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 18:03:48 +0300
Subject: [PATCH 10/79] Fix for resetting local transform of new created prefab
child
---
Source/Editor/SceneGraph/ActorNode.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Source/Editor/SceneGraph/ActorNode.cs b/Source/Editor/SceneGraph/ActorNode.cs
index 7c5a6c1ba..c0ee43c83 100644
--- a/Source/Editor/SceneGraph/ActorNode.cs
+++ b/Source/Editor/SceneGraph/ActorNode.cs
@@ -294,6 +294,9 @@ namespace FlaxEditor.SceneGraph
///
public virtual void PostSpawn()
{
+ _actor.LocalPosition = Vector3.Zero;
+ _actor.LocalEulerAngles = Vector3.Zero;
+ _actor.LocalScale = Vector3.One;
}
///
From c41d1aaec51a693882b85fa7d671e96e0c92d6e6 Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 18:25:59 +0300
Subject: [PATCH 11/79] Update ActorNode.cs
---
Source/Editor/SceneGraph/ActorNode.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Source/Editor/SceneGraph/ActorNode.cs b/Source/Editor/SceneGraph/ActorNode.cs
index c0ee43c83..7c5a6c1ba 100644
--- a/Source/Editor/SceneGraph/ActorNode.cs
+++ b/Source/Editor/SceneGraph/ActorNode.cs
@@ -294,9 +294,6 @@ namespace FlaxEditor.SceneGraph
///
public virtual void PostSpawn()
{
- _actor.LocalPosition = Vector3.Zero;
- _actor.LocalEulerAngles = Vector3.Zero;
- _actor.LocalScale = Vector3.One;
}
///
From 101e33868b4167681c906835d94a38ed1448827a Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 18:27:16 +0300
Subject: [PATCH 12/79] fix local transform prefab child
---
Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index 478439e0e..e80d300c4 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -366,6 +366,9 @@ namespace FlaxEditor.Windows.Assets
actor.Transform = parentActor.Transform;
actor.StaticFlags = parentActor.StaticFlags;
actor.Layer = parentActor.Layer;
+ _actor.LocalPosition = Vector3.Zero;
+ _actor.LocalEulerAngles = Vector3.Zero;
+ _actor.LocalScale = Vector3.One;
// Rename actor to identify it easily
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parentActor.GetChild(x) == null);
From 25b69449bc9d8eedc04659a5917f4b0f2ecda357 Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 18:40:33 +0300
Subject: [PATCH 13/79] fix _actor > actor
---
Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index e80d300c4..2489f7ec4 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -366,9 +366,9 @@ namespace FlaxEditor.Windows.Assets
actor.Transform = parentActor.Transform;
actor.StaticFlags = parentActor.StaticFlags;
actor.Layer = parentActor.Layer;
- _actor.LocalPosition = Vector3.Zero;
- _actor.LocalEulerAngles = Vector3.Zero;
- _actor.LocalScale = Vector3.One;
+ actor.LocalPosition = Vector3.Zero;
+ actor.LocalEulerAngles = Vector3.Zero;
+ actor.LocalScale = Vector3.One;
// Rename actor to identify it easily
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parentActor.GetChild(x) == null);
From 7eb0600549a3fffe6d6a2b08da73d6d2d6abbb00 Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 18:50:07 +0300
Subject: [PATCH 14/79] fix transform identity
---
Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index 2489f7ec4..ca2e14295 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -366,9 +366,7 @@ namespace FlaxEditor.Windows.Assets
actor.Transform = parentActor.Transform;
actor.StaticFlags = parentActor.StaticFlags;
actor.Layer = parentActor.Layer;
- actor.LocalPosition = Vector3.Zero;
- actor.LocalEulerAngles = Vector3.Zero;
- actor.LocalScale = Vector3.One;
+ actor.LocalTransform = Transform.Identity;
// Rename actor to identify it easily
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parentActor.GetChild(x) == null);
From 3133c6fb1b6cbb432d3ab93304d55162b54b44c0 Mon Sep 17 00:00:00 2001
From: Abra <47716519+abrasivetroop@users.noreply.github.com>
Date: Wed, 20 Dec 2023 19:02:52 +0300
Subject: [PATCH 15/79] remove transform/
---
Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index ca2e14295..27fe7c254 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -363,10 +363,9 @@ namespace FlaxEditor.Windows.Assets
if (parentActor != null)
{
// Match the parent
- actor.Transform = parentActor.Transform;
+ actor.LocalTransform = Transform.Identity;
actor.StaticFlags = parentActor.StaticFlags;
actor.Layer = parentActor.Layer;
- actor.LocalTransform = Transform.Identity;
// Rename actor to identify it easily
actor.Name = Utilities.Utils.IncrementNameNumber(actor.Name, x => parentActor.GetChild(x) == null);
From d016305690c71268f3a48689ec68a1b427d853cc Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sun, 31 Dec 2023 15:00:31 -0400
Subject: [PATCH 16/79] Add tank vehicle physics
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 91 ++-
Source/Engine/Physics/Actors/WheeledVehicle.h | 66 +-
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 591 ++++++++++++------
3 files changed, 518 insertions(+), 230 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index afb5309ea..9051c7eed 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -14,7 +14,7 @@
#include "Engine/Core/Log.h"
#endif
-WheeledVehicle::WheeledVehicle(const SpawnParams& params)
+WheeledVehicle::WheeledVehicle(const SpawnParams ¶ms)
: RigidBody(params)
{
_useCCD = 1;
@@ -33,12 +33,22 @@ void WheeledVehicle::SetDriveType(DriveTypes value)
Setup();
}
-const Array& WheeledVehicle::GetWheels() const
+void WheeledVehicle::SetDriveMode(DriveModes value)
+{
+ _driveMode = value;
+}
+
+WheeledVehicle::DriveModes WheeledVehicle::GetDriveMode() const
+{
+ return _driveMode;
+}
+
+const Array &WheeledVehicle::GetWheels() const
{
return _wheels;
}
-void WheeledVehicle::SetWheels(const Array& value)
+void WheeledVehicle::SetWheels(const Array &value)
{
#if WITH_VEHICLE
// Don't recreate whole vehicle when some wheel properties are only changed (eg. suspension)
@@ -47,8 +57,8 @@ void WheeledVehicle::SetWheels(const Array& value)
bool softUpdate = true;
for (int32 wheelIndex = 0; wheelIndex < value.Count(); wheelIndex++)
{
- auto& oldWheel = _wheels.Get()[wheelIndex];
- auto& newWheel = value.Get()[wheelIndex];
+ auto &oldWheel = _wheels.Get()[wheelIndex];
+ auto &newWheel = value.Get()[wheelIndex];
if (oldWheel.Type != newWheel.Type ||
Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) ||
oldWheel.Collider != newWheel.Collider)
@@ -74,7 +84,7 @@ WheeledVehicle::EngineSettings WheeledVehicle::GetEngine() const
return _engine;
}
-void WheeledVehicle::SetEngine(const EngineSettings& value)
+void WheeledVehicle::SetEngine(const EngineSettings &value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -88,7 +98,7 @@ WheeledVehicle::DifferentialSettings WheeledVehicle::GetDifferential() const
return _differential;
}
-void WheeledVehicle::SetDifferential(const DifferentialSettings& value)
+void WheeledVehicle::SetDifferential(const DifferentialSettings &value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -102,7 +112,7 @@ WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const
return _gearbox;
}
-void WheeledVehicle::SetGearbox(const GearboxSettings& value)
+void WheeledVehicle::SetGearbox(const GearboxSettings &value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -131,11 +141,35 @@ void WheeledVehicle::SetHandbrake(float value)
_handBrake = Math::Saturate(value);
}
+void WheeledVehicle::SetTankLeftThrottle(float value)
+{
+ _tankLeftThrottle = Math::Clamp(value, -1.0f, 1.0f);
+}
+
+void WheeledVehicle::SetTankRightThrottle(float value)
+{
+ _tankRightThrottle = Math::Clamp(value, -1.0f, 1.0f);
+}
+
+void WheeledVehicle::SetTankLeftBrake(float value)
+{
+ _tankLeftBrake = Math::Saturate(value);
+}
+
+void WheeledVehicle::SetTankRightBrake(float value)
+{
+ _tankRightBrake = Math::Saturate(value);
+}
+
void WheeledVehicle::ClearInput()
{
_throttle = 0;
_steering = 0;
_brake = 0;
+ _tankLeftThrottle = 0;
+ _tankRightThrottle = 0;
+ _tankLeftBrake = 0;
+ _tankRightBrake = 0;
_handBrake = 0;
}
@@ -200,12 +234,12 @@ void WheeledVehicle::SetTargetGear(int32 value)
#endif
}
-void WheeledVehicle::GetWheelState(int32 index, WheelState& result)
+void WheeledVehicle::GetWheelState(int32 index, WheelState &result)
{
if (index >= 0 && index < _wheels.Count())
{
const auto collider = _wheels[index].Collider.Get();
- for (auto& wheelData : _wheelsData)
+ for (auto &wheelData : _wheelsData)
{
if (wheelData.Collider == collider)
{
@@ -223,7 +257,7 @@ void WheeledVehicle::Setup()
return;
// Release previous
- void* scene = GetPhysicsScene()->GetPhysicsScene();
+ void *scene = GetPhysicsScene()->GetPhysicsScene();
if (_vehicle)
{
PhysicsBackend::RemoveVehicle(scene, this);
@@ -246,10 +280,10 @@ void WheeledVehicle::Setup()
#if USE_EDITOR
-void WheeledVehicle::DrawPhysicsDebug(RenderView& view)
+void WheeledVehicle::DrawPhysicsDebug(RenderView &view)
{
// Wheels shapes
- for (const auto& data : _wheelsData)
+ for (const auto &data : _wheelsData)
{
int32 wheelIndex = 0;
for (; wheelIndex < _wheels.Count(); wheelIndex++)
@@ -259,7 +293,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view)
}
if (wheelIndex == _wheels.Count())
break;
- const auto& wheel = _wheels[wheelIndex];
+ const auto &wheel = _wheels[wheelIndex];
if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
{
const Vector3 currentPos = wheel.Collider->GetPosition();
@@ -280,7 +314,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view)
void WheeledVehicle::OnDebugDrawSelected()
{
// Wheels shapes
- for (const auto& data : _wheelsData)
+ for (const auto &data : _wheelsData)
{
int32 wheelIndex = 0;
for (; wheelIndex < _wheels.Count(); wheelIndex++)
@@ -290,7 +324,7 @@ void WheeledVehicle::OnDebugDrawSelected()
}
if (wheelIndex == _wheels.Count())
break;
- const auto& wheel = _wheels[wheelIndex];
+ const auto &wheel = _wheels[wheelIndex];
if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
{
const Vector3 currentPos = wheel.Collider->GetPosition();
@@ -314,6 +348,14 @@ void WheeledVehicle::OnDebugDrawSelected()
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(data.State.TireContactPoint, 5.0f), Color::Green, 0, false);
}
}
+
+ // Draw wheels axes
+ if (wheelIndex % 2 == 0 && wheelIndex + 1 < _wheels.Count())
+ {
+ const Vector3 wheelPos = _wheels[wheelIndex].Collider->GetPosition();
+ const Vector3 nextWheelPos = _wheels[wheelIndex + 1].Collider->GetPosition();
+ DEBUG_DRAW_LINE(wheelPos, nextWheelPos, Color::Yellow, 0, false);
+ }
}
// Center of mass
@@ -324,13 +366,14 @@ void WheeledVehicle::OnDebugDrawSelected()
#endif
-void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj)
+void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
{
RigidBody::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(WheeledVehicle);
SERIALIZE_MEMBER(DriveType, _driveType);
+ SERIALIZE_MEMBER(DriveModes, _driveMode);
SERIALIZE_MEMBER(Wheels, _wheels);
SERIALIZE(UseReverseAsBrake);
SERIALIZE(UseAnalogSteering);
@@ -339,11 +382,12 @@ void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj)
SERIALIZE_MEMBER(Gearbox, _gearbox);
}
-void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
+void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
{
RigidBody::Deserialize(stream, modifier);
DESERIALIZE_MEMBER(DriveType, _driveType);
+ DESERIALIZE_MEMBER(DriveModes, _driveMode);
DESERIALIZE_MEMBER(Wheels, _wheels);
DESERIALIZE(UseReverseAsBrake);
DESERIALIZE(UseAnalogSteering);
@@ -355,7 +399,7 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier*
_fixInvalidForwardDir |= modifier->EngineBuild < 6341;
}
-void WheeledVehicle::OnColliderChanged(Collider* c)
+void WheeledVehicle::OnColliderChanged(Collider *c)
{
RigidBody::OnColliderChanged(c);
@@ -378,7 +422,7 @@ void WheeledVehicle::OnActiveInTreeChanged()
Setup();
}
-void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene* previous)
+void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene *previous)
{
RigidBody::OnPhysicsSceneChanged(previous);
@@ -401,9 +445,10 @@ void WheeledVehicle::OnTransformChanged()
// Transform all vehicle children around the vehicle origin to fix the vehicle facing direction
const Quaternion rotationDelta(0.0f, -0.7071068f, 0.0f, 0.7071068f);
const Vector3 origin = GetPosition();
- for (Actor* child : Children)
+ for (Actor *child : Children)
{
- Transform trans = child->GetTransform();;
+ Transform trans = child->GetTransform();
+ ;
const Vector3 pivotOffset = trans.Translation - origin;
if (pivotOffset.IsZero())
{
@@ -423,7 +468,7 @@ void WheeledVehicle::OnTransformChanged()
}
}
-void WheeledVehicle::BeginPlay(SceneBeginData* data)
+void WheeledVehicle::BeginPlay(SceneBeginData *data)
{
RigidBody::BeginPlay(data);
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 3a329edc4..49c00b17a 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -26,6 +26,18 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
DriveNW,
// Non-drivable vehicle.
NoDrive,
+ Tank,
+ };
+ ///
+ /// Vehicle driving types.
+ /// Used only on tanks to specify the drive mode.
+ ///
+ API_ENUM() enum class DriveModes
+ {
+ // Drive turning the vehicle using only one track
+ Standard,
+ // Drive turning the vehicle using all tracks inverse direction.
+ Special
};
///
@@ -128,6 +140,11 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
API_FIELD() bool AutoGear = true;
+ ///
+ /// Number of gears to move to forward
+ ///
+ API_FIELD(Attributes = "Limit(1, 30)") int ForwardGearsRatios = 5;
+
///
/// Time it takes to switch gear. Specified in seconds (s).
///
@@ -322,8 +339,9 @@ private:
void* _vehicle = nullptr;
DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
+ DriveModes _driveMode = DriveModes::Standard;
Array> _wheelsData;
- float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f;
+ float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake;
Array _wheels;
EngineSettings _engine;
DifferentialSettings _differential;
@@ -347,17 +365,27 @@ public:
///
/// Gets the vehicle driving model type.
///
- API_PROPERTY(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const;
+ API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const;
///
/// Sets the vehicle driving model type.
///
API_PROPERTY() void SetDriveType(DriveTypes value);
+ ///
+ /// Used only for tanks, set the drive mode.
+ ///
+ API_PROPERTY() void SetDriveMode(DriveModes value);
+
+ ///
+ /// Gets the vehicle driving mode. Used only on tanks
+ ///
+ API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") DriveModes GetDriveMode() const;
+
///
/// Gets the vehicle wheels settings.
///
- API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const;
+ API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const;
///
/// Sets the vehicle wheels settings.
@@ -367,7 +395,7 @@ public:
///
/// Gets the vehicle engine settings.
///
- API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const;
+ API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const;
///
/// Sets the vehicle engine settings.
@@ -377,7 +405,7 @@ public:
///
/// Gets the vehicle differential settings.
///
- API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const;
+ API_PROPERTY(Attributes="EditorOrder(6), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const;
///
/// Sets the vehicle differential settings.
@@ -387,7 +415,7 @@ public:
///
/// Gets the vehicle gearbox settings.
///
- API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const;
+ API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const;
///
/// Sets the vehicle gearbox settings.
@@ -419,6 +447,32 @@ public:
/// The value (0,1 range).
API_FUNCTION() void SetHandbrake(float value);
+ ///
+ /// Sets the input for tank left track throttle. It is the analog accelerator pedal value in range (-1,1) where 1 represents the pedal fully pressed to move to forward, 0 to represents the
+ /// pedal in its rest state and -1 represents the pedal fully pressed to move to backward. The track direction will be inverted if the vehicle current gear is rear.
+ ///
+ /// The value (-1,1 range).
+ API_FUNCTION() void SetTankLeftThrottle(float value);
+
+ ///
+ /// Sets the input for tank right track throttle. It is the analog accelerator pedal value in range (-1,1) where 1 represents the pedal fully pressed to move to forward, 0 to represents the
+ /// pedal in its rest state and -1 represents the pedal fully pressed to move to backward. The track direction will be inverted if the vehicle current gear is rear.
+ ///
+ /// The value (-1,1 range).
+ API_FUNCTION() void SetTankRightThrottle(float value);
+
+ ///
+ /// Sets the input for tank brakes the left track. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
+ ///
+ /// The value (0,1 range).
+ API_FUNCTION() void SetTankLeftBrake(float value);
+
+ ///
+ /// Sets the input for tank brakes the right track. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
+ ///
+ /// The value (0,1 range).
+ API_FUNCTION() void SetTankRightBrake(float value);
+
///
/// Clears all the vehicle control inputs to the default values (throttle, steering, breaks).
///
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index cbc381142..99bc093fc 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
#include
#include
#endif
@@ -961,7 +962,6 @@ void PhysicalMaterial::UpdatePhysicsMaterial()
bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& output)
{
- PROFILE_CPU();
ENSURE_CAN_COOK;
if (input.VertexCount == 0)
LOG(Warning, "Empty mesh data for collision cooking.");
@@ -1005,7 +1005,6 @@ bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& outpu
bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& output)
{
- PROFILE_CPU();
ENSURE_CAN_COOK;
if (input.VertexCount == 0 || input.IndexCount == 0)
LOG(Warning, "Empty mesh data for collision cooking.");
@@ -1040,7 +1039,6 @@ bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& out
bool CollisionCooking::CookHeightField(int32 cols, int32 rows, const PhysicsBackend::HeightFieldSample* data, WriteStream& stream)
{
- PROFILE_CPU();
ENSURE_CAN_COOK;
PxHeightFieldDesc heightFieldDesc;
@@ -1386,62 +1384,172 @@ void PhysicsBackend::EndSimulateScene(void* scene)
WheelVehiclesCache.Add(drive);
wheelsCount += drive->mWheelsSimData.getNbWheels();
+ const float deadZone = 0.1f;
+ bool isTank = wheelVehicle->_driveType == WheeledVehicle::DriveTypes::Tank;
float throttle = wheelVehicle->_throttle;
+ float steering = wheelVehicle->_steering;
float brake = wheelVehicle->_brake;
+ float leftThrottle = wheelVehicle->_tankLeftThrottle;
+ float rightThrottle = wheelVehicle->_tankRightThrottle;
+ float leftBrake = Math::Max(wheelVehicle->_tankLeftBrake, wheelVehicle->_handBrake);
+ float rightBrake = Math::Max(wheelVehicle->_tankRightBrake, wheelVehicle->_handBrake);
+
+ WheeledVehicle::DriveModes vehicleDriveMode = wheelVehicle->_driveMode;
+
+ if (isTank)
+ {
+ // Converting default vehicle controls to tank controls.
+ if (throttle != 0 || steering != 0)
+ {
+ leftThrottle = throttle + steering;
+ rightThrottle = throttle - steering;
+ }
+ }
+
+ // Converting special tank drive mode to standard tank mode when is turning.
+ if (isTank && vehicleDriveMode == WheeledVehicle::DriveModes::Standard)
+ {
+ // Special inputs when turning vehicle -1 1 to left or 1 -1 to turn right
+ // to:
+ // Standard inputs when turning vehicle 0 1 to left or 1 0 to turn right
+
+ if (leftThrottle < -deadZone && rightThrottle > deadZone)
+ {
+ leftThrottle = 0;
+ }
+ else if (leftThrottle > deadZone && rightThrottle < -deadZone)
+ {
+ rightThrottle = 0;
+ }
+ }
+
if (wheelVehicle->UseReverseAsBrake)
{
const float invalidDirectionThreshold = 80.0f;
const float breakThreshold = 8.0f;
const float forwardSpeed = wheelVehicle->GetForwardSpeed();
+ int currentGear = wheelVehicle->GetCurrentGear();
+ // Tank tracks direction: 1 forward -1 backward 0 neutral
+ bool toForward = false;
+ toForward |= throttle > deadZone;
+ toForward |= (leftThrottle > deadZone) && (rightThrottle > deadZone); // 1 1
+ bool toBackward = false;
+ toBackward |= throttle < -deadZone;
+ toBackward |= (leftThrottle < -deadZone) && (rightThrottle < -deadZone); // -1 -1
+ toBackward |= (leftThrottle < -deadZone) && (rightThrottle < deadZone); // -1 0
+ toBackward |= (leftThrottle < deadZone) && (rightThrottle < -deadZone); // 0 -1
+
+ bool isTankTurning = false;
+
+ if (isTank)
+ {
+ isTankTurning |= leftThrottle > deadZone && rightThrottle < -deadZone; // 1 -1
+ isTankTurning |= leftThrottle < -deadZone && rightThrottle > deadZone; // -1 1
+ isTankTurning |= leftThrottle < deadZone && rightThrottle > deadZone; // 0 1
+ isTankTurning |= leftThrottle > deadZone && rightThrottle < deadZone; // 1 0
+ isTankTurning |= leftThrottle < -deadZone && rightThrottle < deadZone; // -1 0
+ isTankTurning |= leftThrottle < deadZone && rightThrottle < -deadZone; // 0 -1
+
+ if (toForward || toBackward)
+ {
+ isTankTurning = false;
+ }
+ }
+
// Automatic gear change when changing driving direction
if (Math::Abs(forwardSpeed) < invalidDirectionThreshold)
{
- if (throttle < -ZeroTolerance && wheelVehicle->GetCurrentGear() >= 0 && wheelVehicle->GetTargetGear() >= 0)
+ int targetGear = wheelVehicle->GetTargetGear();
+ if (toBackward && currentGear > 0 && targetGear >= 0)
{
- wheelVehicle->SetCurrentGear(-1);
+ currentGear = -1;
}
- else if (throttle > ZeroTolerance && wheelVehicle->GetCurrentGear() <= 0 && wheelVehicle->GetTargetGear() <= 0)
+ else if (!toBackward && currentGear <= 0 && targetGear <= 0)
{
- wheelVehicle->SetCurrentGear(1);
+ currentGear = 1;
+ }
+ else if (isTankTurning && currentGear <= 0)
+ {
+ currentGear = 1;
+ }
+
+ if (wheelVehicle->GetCurrentGear() != currentGear)
+ {
+ wheelVehicle->SetCurrentGear(currentGear);
}
}
// Automatic break when changing driving direction
- if (throttle > 0.0f)
+ if (toForward)
{
if (forwardSpeed < -invalidDirectionThreshold)
{
brake = 1.0f;
+ leftBrake = 1.0f;
+ rightBrake = 1.0f;
}
}
- else if (throttle < 0.0f)
+ else if (toBackward)
{
if (forwardSpeed > invalidDirectionThreshold)
{
brake = 1.0f;
+ leftBrake = 1.0f;
+ rightBrake = 1.0f;
}
}
else
{
- if (forwardSpeed < breakThreshold && forwardSpeed > -breakThreshold)
+ if (forwardSpeed < breakThreshold && forwardSpeed > -breakThreshold && !isTankTurning) // not accelerating, very slow speed -> stop
{
brake = 1.0f;
+ leftBrake = 1.0f;
+ rightBrake = 1.0f;
}
}
// Block throttle if user is changing driving direction
- if ((throttle > 0.0f && wheelVehicle->GetTargetGear() < 0) || (throttle < 0.0f && wheelVehicle->GetTargetGear() > 0))
+ if ((toForward && currentGear < 0) || (toBackward && currentGear > 0))
{
throttle = 0.0f;
+ leftThrottle = 0;
+ rightThrottle = 0;
}
throttle = Math::Abs(throttle);
+
+ if (isTank)
+ {
+ // invert acceleration when moving to backward because tank inputs can be < 0
+ if (currentGear < 0)
+ {
+ float lt = -leftThrottle;
+ float rt = -rightThrottle;
+ float lb = leftBrake;
+ float rb = rightBrake;
+ leftThrottle = rt;
+ rightThrottle = lt;
+ leftBrake = rb;
+ rightBrake = lb;
+ }
+ }
}
else
{
throttle = Math::Max(throttle, 0.0f);
}
+
+ // Force brake the another side track to turn more faster.
+ if (Math::Abs(leftThrottle) > deadZone && Math::Abs(rightThrottle) < deadZone)
+ {
+ rightBrake = 1.0f;
+ }
+ if (Math::Abs(rightThrottle) > deadZone && Math::Abs(leftThrottle) < deadZone)
+ {
+ leftBrake = 1.0f;
+ }
+
// @formatter:off
// Reference: PhysX SDK docs
// TODO: expose input control smoothing data
@@ -1518,11 +1626,23 @@ void PhysicsBackend::EndSimulateScene(void* scene)
PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, steerVsForwardSpeed, rawInputData, scenePhysX->LastDeltaTime, false, *(PxVehicleDriveNW*)drive);
break;
}
+ case WheeledVehicle::DriveTypes::Tank:
+ {
+ PxVehicleDriveTankRawInputData driveMode = vehicleDriveMode == WheeledVehicle::DriveModes::Standard ? PxVehicleDriveTankControlModel::eSTANDARD : PxVehicleDriveTankControlModel::eSPECIAL;
+ PxVehicleDriveTankRawInputData rawInputData = PxVehicleDriveTankRawInputData(driveMode);
+ rawInputData.setAnalogAccel(Math::Max(Math::Abs(leftThrottle), Math::Abs(rightThrottle)));
+ rawInputData.setAnalogLeftBrake(leftBrake);
+ rawInputData.setAnalogRightBrake(rightBrake);
+ rawInputData.setAnalogLeftThrust(leftThrottle);
+ rawInputData.setAnalogRightThrust(rightThrottle);
+
+ PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank*)drive);
+ break;
+ }
}
}
else
- {
- const float deadZone = 0.1f;
+ {
switch (wheelVehicle->_driveTypeCurrent)
{
case WheeledVehicle::DriveTypes::Drive4W:
@@ -1547,6 +1667,26 @@ void PhysicsBackend::EndSimulateScene(void* scene)
PxVehicleDriveNWSmoothDigitalRawInputsAndSetAnalogInputs(keySmoothing, steerVsForwardSpeed, rawInputData, scenePhysX->LastDeltaTime, false, *(PxVehicleDriveNW*)drive);
break;
}
+ case WheeledVehicle::DriveTypes::Tank:
+ {
+ // Convert analogic inputs to digital inputs.
+ leftThrottle = Math::Round(leftThrottle);
+ rightThrottle = Math::Round(rightThrottle);
+ leftBrake = Math::Round(leftBrake);
+ rightBrake = Math::Round(rightBrake);
+
+ PxVehicleDriveTankRawInputData driveMode = vehicleDriveMode == WheeledVehicle::DriveModes::Standard ? PxVehicleDriveTankControlModel::eSTANDARD : PxVehicleDriveTankControlModel::eSPECIAL;
+ PxVehicleDriveTankRawInputData rawInputData = PxVehicleDriveTankRawInputData(driveMode);
+ rawInputData.setAnalogAccel(Math::Max(Math::Abs(leftThrottle), Math::Abs(rightThrottle)));
+ rawInputData.setAnalogLeftBrake(leftBrake);
+ rawInputData.setAnalogRightBrake(rightBrake);
+ rawInputData.setAnalogLeftThrust(leftThrottle);
+ rawInputData.setAnalogRightThrust(rightThrottle);
+
+ // Needs to pass analogic values to vehicle to maintein current moviment direction because digital inputs accept only true/false values to tracks thrust instead of -1 to 1
+ PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank *)drive);
+ break;
+ }
}
}
}
@@ -2803,7 +2943,7 @@ void PhysicsBackend::SetHingeJointLimit(void* joint, const LimitAngularRange& va
void PhysicsBackend::SetHingeJointDrive(void* joint, const HingeJointDrive& value)
{
auto jointPhysX = (PxRevoluteJoint*)joint;
- jointPhysX->setDriveVelocity(value.Velocity);
+ jointPhysX->setDriveVelocity(Math::Max(value.Velocity, 0.0f));
jointPhysX->setDriveForceLimit(Math::Max(value.ForceLimit, 0.0f));
jointPhysX->setDriveGearRatio(Math::Max(value.GearRatio, 0.0f));
jointPhysX->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, value.FreeSpin);
@@ -3086,6 +3226,147 @@ int32 PhysicsBackend::MoveController(void* controller, void* shape, const Vector
#if WITH_VEHICLE
+PxVehicleDifferential4WData CreatePxVehicleDifferential4WData(const WheeledVehicle::DifferentialSettings& settings)
+{
+ PxVehicleDifferential4WData differential4WData;
+ differential4WData.mType = (PxVehicleDifferential4WData::Enum)settings.Type;
+ differential4WData.mFrontRearSplit = settings.FrontRearSplit;
+ differential4WData.mFrontLeftRightSplit = settings.FrontLeftRightSplit;
+ differential4WData.mRearLeftRightSplit = settings.RearLeftRightSplit;
+ differential4WData.mCentreBias = settings.CentreBias;
+ differential4WData.mFrontBias = settings.FrontBias;
+ differential4WData.mRearBias = settings.RearBias;
+ return differential4WData;
+}
+
+PxVehicleDifferentialNWData CreatePxVehicleDifferentialNWData(const WheeledVehicle::DifferentialSettings& settings, const Array>& wheels)
+{
+ PxVehicleDifferentialNWData differentialNwData;
+ for (int32 i = 0; i < wheels.Count(); i++)
+ differentialNwData.setDrivenWheel(i, true);
+
+ return differentialNwData;
+}
+
+PxVehicleEngineData CreatePxVehicleEngineData(const WheeledVehicle::EngineSettings& settings)
+{
+ PxVehicleEngineData engineData;
+ engineData.mMOI = M2ToCm2(settings.MOI);
+ engineData.mPeakTorque = M2ToCm2(settings.MaxTorque);
+ engineData.mMaxOmega = RpmToRadPerS(settings.MaxRotationSpeed);
+ engineData.mDampingRateFullThrottle = M2ToCm2(0.15f);
+ engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
+ engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ return engineData;
+}
+
+PxVehicleGearsData CreatePxVehicleGearsData(const WheeledVehicle::GearboxSettings& settings)
+{
+ PxVehicleGearsData gears;
+
+ // Total gears is forward gears + neutral/rear gears
+ int gearsAmount = settings.ForwardGearsRatios + 2;
+
+ // Setup gears torque/top speed relations
+ // Higher torque = less speed
+ // Low torque = high speed
+
+ // Example:
+ // ForwardGearsRatios = 4
+ // GearRev = -5
+ // Gear0 = 0
+ // Gear1 = 4.2
+ // Gear2 = 3.4
+ // Gear3 = 2.6
+ // Gear4 = 1.8
+ // Gear5 = 1
+
+ gears.mRatios[0] = -(gearsAmount - 2); // reverse
+ gears.mRatios[1] = 0; // neutral
+
+ // Setup all gears except neutral and reverse
+ for (int i = gearsAmount; i > 2; i--) {
+
+ float gearsRatios = settings.ForwardGearsRatios;
+ float currentGear = i - 2;
+
+ gears.mRatios[i] = Math::Lerp(gearsRatios, 1.0f, (currentGear / gearsRatios));
+ }
+
+ // reset unused gears
+ for (int i = gearsAmount; i < PxVehicleGearsData::eGEARSRATIO_COUNT; i++)
+ gears.mRatios[i] = 0;
+
+ gears.mSwitchTime = Math::Max(settings.SwitchTime, 0.0f);
+ gears.mNbRatios = Math::Clamp(gearsAmount, 2, (int)PxVehicleGearsData::eGEARSRATIO_COUNT);
+ return gears;
+}
+
+PxVehicleAutoBoxData CreatePxVehicleAutoBoxData()
+{
+ return PxVehicleAutoBoxData();
+}
+
+PxVehicleClutchData CreatePxVehicleClutchData(const WheeledVehicle::GearboxSettings& settings)
+{
+ PxVehicleClutchData clutch;
+ clutch.mStrength = M2ToCm2(settings.ClutchStrength);
+ return clutch;
+}
+
+PxVehicleSuspensionData CreatePxVehicleSuspensionData(const WheeledVehicle::Wheel& settings, const PxReal wheelSprungMass)
+{
+ PxVehicleSuspensionData suspensionData;
+ const float suspensionFrequency = 7.0f;
+ suspensionData.mMaxCompression = settings.SuspensionMaxRaise;
+ suspensionData.mMaxDroop = settings.SuspensionMaxDrop;
+ suspensionData.mSprungMass = wheelSprungMass;
+ suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass;
+ suspensionData.mSpringDamperRate = settings.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass);
+ return suspensionData;
+}
+
+PxVehicleTireData CreatePxVehicleTireData(const WheeledVehicle::Wheel& settings)
+{
+ PxVehicleTireData tire;
+ int32 tireIndex = WheelTireTypes.Find(settings.TireFrictionScale);
+ if (tireIndex == -1)
+ {
+ // New tire type
+ tireIndex = WheelTireTypes.Count();
+ WheelTireTypes.Add(settings.TireFrictionScale);
+ WheelTireFrictionsDirty = true;
+ }
+ tire.mType = tireIndex;
+ tire.mLatStiffX = settings.TireLateralMax;
+ tire.mLatStiffY = settings.TireLateralStiffness;
+ tire.mLongitudinalStiffnessPerUnitGravity = settings.TireLongitudinalStiffness;
+ return tire;
+}
+
+PxVehicleWheelData CreatePxVehicleWheelData(const WheeledVehicle::Wheel& settings)
+{
+ PxVehicleWheelData wheelData;
+ wheelData.mMass = settings.Mass;
+ wheelData.mRadius = settings.Radius;
+ wheelData.mWidth = settings.Width;
+ wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius);
+ wheelData.mDampingRate = M2ToCm2(settings.DampingRate);
+ wheelData.mMaxSteer = settings.MaxSteerAngle * DegreesToRadians;
+ wheelData.mMaxBrakeTorque = M2ToCm2(settings.MaxBrakeTorque);
+ wheelData.mMaxHandBrakeTorque = M2ToCm2(settings.MaxHandBrakeTorque);
+ return wheelData;
+}
+
+PxVehicleAckermannGeometryData CreatePxVehicleAckermannGeometryData(PxVehicleWheelsSimData* wheelsSimData)
+{
+ PxVehicleAckermannGeometryData ackermann;
+ ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z);
+ ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x);
+ ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x);
+ return ackermann;
+}
+
bool SortWheels(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
{
return (int32)a.Type < (int32)b.Type;
@@ -3158,42 +3439,14 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
data.Collider = wheel.Collider;
data.LocalOrientation = wheel.Collider->GetLocalOrientation();
- PxVehicleSuspensionData suspensionData;
- const float suspensionFrequency = 7.0f;
- suspensionData.mMaxCompression = wheel.SuspensionMaxRaise;
- suspensionData.mMaxDroop = wheel.SuspensionMaxDrop;
- suspensionData.mSprungMass = sprungMasses[i];
- suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass;
- suspensionData.mSpringDamperRate = wheel.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass);
-
- PxVehicleTireData tire;
- int32 tireIndex = WheelTireTypes.Find(wheel.TireFrictionScale);
- if (tireIndex == -1)
- {
- // New tire type
- tireIndex = WheelTireTypes.Count();
- WheelTireTypes.Add(wheel.TireFrictionScale);
- WheelTireFrictionsDirty = true;
- }
- tire.mType = tireIndex;
- tire.mLatStiffX = wheel.TireLateralMax;
- tire.mLatStiffY = wheel.TireLateralStiffness;
- tire.mLongitudinalStiffnessPerUnitGravity = wheel.TireLongitudinalStiffness;
-
- PxVehicleWheelData wheelData;
- wheelData.mMass = wheel.Mass;
- wheelData.mRadius = wheel.Radius;
- wheelData.mWidth = wheel.Width;
- wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius);
- wheelData.mDampingRate = M2ToCm2(wheel.DampingRate);
- wheelData.mMaxSteer = wheel.MaxSteerAngle * DegreesToRadians;
- wheelData.mMaxBrakeTorque = M2ToCm2(wheel.MaxBrakeTorque);
- wheelData.mMaxHandBrakeTorque = M2ToCm2(wheel.MaxHandBrakeTorque);
-
PxVec3 centreOffset = centerOfMassOffset.transformInv(offsets[i]);
PxVec3 forceAppPointOffset(centreOffset.x, wheel.SuspensionForceOffset, centreOffset.z);
- wheelsSimData->setTireData(i, tire);
+ const PxVehicleTireData& tireData = CreatePxVehicleTireData(wheel);
+ const PxVehicleWheelData& wheelData = CreatePxVehicleWheelData(wheel);
+ const PxVehicleSuspensionData& suspensionData = CreatePxVehicleSuspensionData(wheel, sprungMasses[i]);
+
+ wheelsSimData->setTireData(i,tireData);
wheelsSimData->setWheelData(i, wheelData);
wheelsSimData->setSuspensionData(i, suspensionData);
wheelsSimData->setSuspTravelDirection(i, centerOfMassOffset.rotate(PxVec3(0.0f, -1.0f, 0.0f)));
@@ -3260,48 +3513,19 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
case WheeledVehicle::DriveTypes::Drive4W:
{
PxVehicleDriveSimData4W driveSimData;
+ const PxVehicleDifferential4WData& differentialData = CreatePxVehicleDifferential4WData(differential);
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
+ const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
+ const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
- // Differential
- PxVehicleDifferential4WData differential4WData;
- differential4WData.mType = (PxVehicleDifferential4WData::Enum)differential.Type;
- differential4WData.mFrontRearSplit = differential.FrontRearSplit;
- differential4WData.mFrontLeftRightSplit = differential.FrontLeftRightSplit;
- differential4WData.mRearLeftRightSplit = differential.RearLeftRightSplit;
- differential4WData.mCentreBias = differential.CentreBias;
- differential4WData.mFrontBias = differential.FrontBias;
- differential4WData.mRearBias = differential.RearBias;
- driveSimData.setDiffData(differential4WData);
-
- // Engine
- PxVehicleEngineData engineData;
- engineData.mMOI = M2ToCm2(engine.MOI);
- engineData.mPeakTorque = M2ToCm2(engine.MaxTorque);
- engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed);
- engineData.mDampingRateFullThrottle = M2ToCm2(0.15f);
- engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
- engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ driveSimData.setDiffData(differentialData);
driveSimData.setEngineData(engineData);
-
- // Gears
- PxVehicleGearsData gears;
- gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f);
- driveSimData.setGearsData(gears);
-
- // Auto Box
- PxVehicleAutoBoxData autoBox;
- driveSimData.setAutoBoxData(autoBox);
-
- // Clutch
- PxVehicleClutchData clutch;
- clutch.mStrength = M2ToCm2(gearbox.ClutchStrength);
- driveSimData.setClutchData(clutch);
-
- // Ackermann steer accuracy
- PxVehicleAckermannGeometryData ackermann;
- ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z);
- ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x);
- ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x);
- driveSimData.setAckermannGeometryData(ackermann);
+ driveSimData.setGearsData(gearsData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(cluchData);
+ driveSimData.setAckermannGeometryData(geometryData);
// Create vehicle drive
auto drive4W = PxVehicleDrive4W::allocate(wheels.Count());
@@ -3315,36 +3539,18 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
case WheeledVehicle::DriveTypes::DriveNW:
{
PxVehicleDriveSimDataNW driveSimData;
+ const PxVehicleDifferentialNWData& differentialData = CreatePxVehicleDifferentialNWData(differential, wheels);
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
+ const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
+ const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
- // Differential
- PxVehicleDifferentialNWData differentialNwData;
- for (int32 i = 0; i < wheels.Count(); i++)
- differentialNwData.setDrivenWheel(i, true);
- driveSimData.setDiffData(differentialNwData);
-
- // Engine
- PxVehicleEngineData engineData;
- engineData.mMOI = M2ToCm2(engine.MOI);
- engineData.mPeakTorque = M2ToCm2(engine.MaxTorque);
- engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed);
- engineData.mDampingRateFullThrottle = M2ToCm2(0.15f);
- engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
- engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ driveSimData.setDiffData(differentialData);
driveSimData.setEngineData(engineData);
-
- // Gears
- PxVehicleGearsData gears;
- gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f);
- driveSimData.setGearsData(gears);
-
- // Auto Box
- PxVehicleAutoBoxData autoBox;
- driveSimData.setAutoBoxData(autoBox);
-
- // Clutch
- PxVehicleClutchData clutch;
- clutch.mStrength = M2ToCm2(gearbox.ClutchStrength);
- driveSimData.setClutchData(clutch);
+ driveSimData.setGearsData(gearsData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(cluchData);
// Create vehicle drive
auto driveNW = PxVehicleDriveNW::allocate(wheels.Count());
@@ -3364,6 +3570,32 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
vehicle = driveNo;
break;
}
+ case WheeledVehicle::DriveTypes::Tank:
+ {
+ PxVehicleDriveSimData4W driveSimData;
+ const PxVehicleDifferential4WData &differentialData = CreatePxVehicleDifferential4WData(differential);
+ const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine);
+ const PxVehicleGearsData &gearsData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData();
+ const PxVehicleClutchData &cluchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAckermannGeometryData &geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
+
+ driveSimData.setDiffData(differentialData);
+ driveSimData.setEngineData(engineData);
+ driveSimData.setGearsData(gearsData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(cluchData);
+ driveSimData.setAckermannGeometryData(geometryData);
+
+ // Create vehicle drive
+ auto driveTank = PxVehicleDriveTank::allocate(wheels.Count());
+ driveTank->setup(PhysX, actorPhysX, *wheelsSimData, driveSimData, wheels.Count());
+ driveTank->setToRestState();
+ driveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
+ driveTank->mDriveDynData.setUseAutoGears(gearbox.AutoGear);
+ vehicle = driveTank;
+ break;
+ }
default:
CRASH;
}
@@ -3385,6 +3617,9 @@ void PhysicsBackend::DestroyVehicle(void* vehicle, int32 driveType)
case WheeledVehicle::DriveTypes::NoDrive:
((PxVehicleNoDrive*)vehicle)->free();
break;
+ case WheeledVehicle::DriveTypes::Tank:
+ ((PxVehicleDriveTank*)vehicle)->free();
+ break;
}
}
@@ -3395,42 +3630,11 @@ void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor)
for (uint32 i = 0; i < wheelsSimData->getNbWheels(); i++)
{
auto& wheel = actor->_wheels[i];
-
- // Update suspension data
- PxVehicleSuspensionData suspensionData = wheelsSimData->getSuspensionData(i);
- const float suspensionFrequency = 7.0f;
- suspensionData.mMaxCompression = wheel.SuspensionMaxRaise;
- suspensionData.mMaxDroop = wheel.SuspensionMaxDrop;
- suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass;
- suspensionData.mSpringDamperRate = wheel.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass);
+ const PxVehicleSuspensionData& suspensionData = CreatePxVehicleSuspensionData(wheel, wheelsSimData->getSuspensionData(i).mSprungMass);
+ const PxVehicleTireData& tireData = CreatePxVehicleTireData(wheel);
+ const PxVehicleWheelData& wheelData = CreatePxVehicleWheelData(wheel);
wheelsSimData->setSuspensionData(i, suspensionData);
-
- // Update tire data
- PxVehicleTireData tire;
- int32 tireIndex = WheelTireTypes.Find(wheel.TireFrictionScale);
- if (tireIndex == -1)
- {
- // New tire type
- tireIndex = WheelTireTypes.Count();
- WheelTireTypes.Add(wheel.TireFrictionScale);
- WheelTireFrictionsDirty = true;
- }
- tire.mType = tireIndex;
- tire.mLatStiffX = wheel.TireLateralMax;
- tire.mLatStiffY = wheel.TireLateralStiffness;
- tire.mLongitudinalStiffnessPerUnitGravity = wheel.TireLongitudinalStiffness;
- wheelsSimData->setTireData(i, tire);
-
- // Update wheel data
- PxVehicleWheelData wheelData;
- wheelData.mMass = wheel.Mass;
- wheelData.mRadius = wheel.Radius;
- wheelData.mWidth = wheel.Width;
- wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius);
- wheelData.mDampingRate = M2ToCm2(wheel.DampingRate);
- wheelData.mMaxSteer = wheel.MaxSteerAngle * DegreesToRadians;
- wheelData.mMaxBrakeTorque = M2ToCm2(wheel.MaxBrakeTorque);
- wheelData.mMaxHandBrakeTorque = M2ToCm2(wheel.MaxHandBrakeTorque);
+ wheelsSimData->setTireData(i, tireData);
wheelsSimData->setWheelData(i, wheelData);
}
}
@@ -3444,28 +3648,24 @@ void PhysicsBackend::SetVehicleEngine(void* vehicle, const void* value)
case PxVehicleTypes::eDRIVE4W:
{
auto drive4W = (PxVehicleDrive4W*)drive;
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData;
- PxVehicleEngineData engineData;
- engineData.mMOI = M2ToCm2(engine.MOI);
- engineData.mPeakTorque = M2ToCm2(engine.MaxTorque);
- engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed);
- engineData.mDampingRateFullThrottle = M2ToCm2(0.15f);
- engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
- engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
driveSimData.setEngineData(engineData);
break;
}
case PxVehicleTypes::eDRIVENW:
{
auto drive4W = (PxVehicleDriveNW*)drive;
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
PxVehicleDriveSimDataNW& driveSimData = drive4W->mDriveSimData;
- PxVehicleEngineData engineData;
- engineData.mMOI = M2ToCm2(engine.MOI);
- engineData.mPeakTorque = M2ToCm2(engine.MaxTorque);
- engineData.mMaxOmega = RpmToRadPerS(engine.MaxRotationSpeed);
- engineData.mDampingRateFullThrottle = M2ToCm2(0.15f);
- engineData.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
- engineData.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ driveSimData.setEngineData(engineData);
+ break;
+ }
+ case PxVehicleTypes::eDRIVETANK:
+ {
+ auto driveTank = (PxVehicleDriveTank*)drive;
+ const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine);
+ PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData;
driveSimData.setEngineData(engineData);
break;
}
@@ -3481,16 +3681,9 @@ void PhysicsBackend::SetVehicleDifferential(void* vehicle, const void* value)
case PxVehicleTypes::eDRIVE4W:
{
auto drive4W = (PxVehicleDrive4W*)drive;
+ const PxVehicleDifferential4WData& differentialData = CreatePxVehicleDifferential4WData(differential);
PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData;
- PxVehicleDifferential4WData differential4WData;
- differential4WData.mType = (PxVehicleDifferential4WData::Enum)differential.Type;
- differential4WData.mFrontRearSplit = differential.FrontRearSplit;
- differential4WData.mFrontLeftRightSplit = differential.FrontLeftRightSplit;
- differential4WData.mRearLeftRightSplit = differential.RearLeftRightSplit;
- differential4WData.mCentreBias = differential.CentreBias;
- differential4WData.mFrontBias = differential.FrontBias;
- differential4WData.mRearBias = differential.RearBias;
- driveSimData.setDiffData(differential4WData);
+ driveSimData.setDiffData(differentialData);
break;
}
}
@@ -3507,41 +3700,37 @@ void PhysicsBackend::SetVehicleGearbox(void* vehicle, const void* value)
case PxVehicleTypes::eDRIVE4W:
{
auto drive4W = (PxVehicleDrive4W*)drive;
+ const PxVehicleGearsData& gearData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
PxVehicleDriveSimData4W& driveSimData = drive4W->mDriveSimData;
-
- // Gears
- PxVehicleGearsData gears;
- gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f);
- driveSimData.setGearsData(gears);
-
- // Auto Box
- PxVehicleAutoBoxData autoBox;
- driveSimData.setAutoBoxData(autoBox);
-
- // Clutch
- PxVehicleClutchData clutch;
- clutch.mStrength = M2ToCm2(gearbox.ClutchStrength);
- driveSimData.setClutchData(clutch);
+ driveSimData.setGearsData(gearData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(clutchData);
break;
}
case PxVehicleTypes::eDRIVENW:
{
auto drive4W = (PxVehicleDriveNW*)drive;
+ const PxVehicleGearsData& gearData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
PxVehicleDriveSimDataNW& driveSimData = drive4W->mDriveSimData;
-
- // Gears
- PxVehicleGearsData gears;
- gears.mSwitchTime = Math::Max(gearbox.SwitchTime, 0.0f);
- driveSimData.setGearsData(gears);
-
- // Auto Box
- PxVehicleAutoBoxData autoBox;
- driveSimData.setAutoBoxData(autoBox);
-
- // Clutch
- PxVehicleClutchData clutch;
- clutch.mStrength = M2ToCm2(gearbox.ClutchStrength);
- driveSimData.setClutchData(clutch);
+ driveSimData.setGearsData(gearData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(clutchData);
+ break;
+ }
+ case PxVehicleTypes::eDRIVETANK:
+ {
+ auto driveTank = (PxVehicleDriveTank *)drive;
+ const PxVehicleGearsData &gearData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleClutchData &clutchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData();
+ PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData;
+ driveSimData.setGearsData(gearData);
+ driveSimData.setAutoBoxData(autoBoxData);
+ driveSimData.setClutchData(clutchData);
break;
}
}
From 6a2d7e9444244e820ae102ae9eb158abbd7a4b6b Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sun, 31 Dec 2023 22:11:30 -0400
Subject: [PATCH 17/79] auto sort wheels based on wheel position
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 7 ++--
Source/Engine/Physics/Actors/WheeledVehicle.h | 22 ----------
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 40 +++++++++++++++----
3 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 9051c7eed..a68bc23c7 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -59,9 +59,7 @@ void WheeledVehicle::SetWheels(const Array &value)
{
auto &oldWheel = _wheels.Get()[wheelIndex];
auto &newWheel = value.Get()[wheelIndex];
- if (oldWheel.Type != newWheel.Type ||
- Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) ||
- oldWheel.Collider != newWheel.Collider)
+ if (Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) || oldWheel.Collider != newWheel.Collider)
{
softUpdate = false;
break;
@@ -352,6 +350,9 @@ void WheeledVehicle::OnDebugDrawSelected()
// Draw wheels axes
if (wheelIndex % 2 == 0 && wheelIndex + 1 < _wheels.Count())
{
+ if (!_wheels[wheelIndex].Collider || !_wheels[wheelIndex + 1].Collider)
+ continue;
+
const Vector3 wheelPos = _wheels[wheelIndex].Collider->GetPosition();
const Vector3 nextWheelPos = _wheels[wheelIndex + 1].Collider->GetPosition();
DEBUG_DRAW_LINE(wheelPos, nextWheelPos, Color::Yellow, 0, false);
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 49c00b17a..acf20310f 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -158,23 +158,6 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
API_FIELD(Attributes="Limit(0)") float ClutchStrength = 10.0f;
};
- ///
- /// Vehicle wheel types.
- ///
- API_ENUM() enum class WheelTypes
- {
- // Left wheel of the front axle.
- FrontLeft,
- // Right wheel of the front axle.
- FrontRight,
- // Left wheel of the rear axle.
- RearLeft,
- // Right wheel of the rear axle.
- RearRight,
- // Non-drivable wheel.
- NoDrive,
- };
-
///
/// Vehicle wheel settings.
///
@@ -183,11 +166,6 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
DECLARE_SCRIPTING_TYPE_MINIMAL(Wheel);
API_AUTO_SERIALIZATION();
- ///
- /// Wheel placement type.
- ///
- API_FIELD(Attributes="EditorOrder(0)") WheelTypes Type = WheelTypes::FrontLeft;
-
///
/// Combined mass of the wheel and the tire in kg. Typically, a wheel has mass between 20Kg and 80Kg but can be lower and higher depending on the vehicle.
///
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 99bc093fc..e55b80008 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -58,7 +58,9 @@
#if WITH_PVD
#include
#endif
-
+#if USE_EDITOR
+#include "Editor/Editor.h"
+#endif
// Temporary memory size used by the PhysX during the simulation. Must be multiply of 4kB and 16bit aligned.
#define PHYSX_SCRATCH_BLOCK_SIZE (1024 * 128)
@@ -3367,18 +3369,42 @@ PxVehicleAckermannGeometryData CreatePxVehicleAckermannGeometryData(PxVehicleWhe
return ackermann;
}
-bool SortWheels(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
+bool SortWheelsFrontToBack(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
{
- return (int32)a.Type < (int32)b.Type;
+ return a.Collider && b.Collider && a.Collider->GetLocalPosition().Z > b.Collider->GetLocalPosition().Z;
}
void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
{
- // TODO: handle PxVehicleDrive4WWheelOrder internally rather than sorting wheels directly on the vehicle
- if (actor->_driveType == WheeledVehicle::DriveTypes::Drive4W)
+#if USE_EDITOR
+ if (Editor::IsPlayMode)
+#endif
{
- // Drive4W requires wheels to match order from PxVehicleDrive4WWheelOrder enum
- Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheels);
+ // Physx vehicles needs to have all wheels sorted to apply controls correctly.
+ // Its needs to know what wheels are on front to turn wheel to correctly side
+ // and needs to know wheel side to apply throttle to correctly direction for each track when using tanks.
+
+ if (actor->_driveType == WheeledVehicle::DriveTypes::Drive4W)
+ Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack);
+
+ // sort wheels by side
+ if (actor->_driveType == WheeledVehicle::DriveTypes::Tank)
+ {
+ for (int i = 0; i < actor->_wheels.Count() - 1; i += 2)
+ {
+ auto a = actor->_wheels[i];
+ auto b = actor->_wheels[i + 1];
+
+ if (!a.Collider || !b.Collider)
+ continue;
+
+ if (a.Collider->GetLocalPosition().X > b.Collider->GetLocalPosition().X)
+ {
+ actor->_wheels[i] = b;
+ actor->_wheels[i + 1] = a;
+ }
+ }
+ }
}
// Get wheels
From 967569c3e27b222b7735df2ad145dfab8d41cc2a Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sun, 31 Dec 2023 22:43:04 -0400
Subject: [PATCH 18/79] Small fix vehicle tank inputs
---
Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index e55b80008..cb1d094a4 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1403,8 +1403,8 @@ void PhysicsBackend::EndSimulateScene(void* scene)
// Converting default vehicle controls to tank controls.
if (throttle != 0 || steering != 0)
{
- leftThrottle = throttle + steering;
- rightThrottle = throttle - steering;
+ leftThrottle = Math::Clamp(throttle + steering, -1.0f, 1.0f);
+ rightThrottle = Math::Clamp(throttle - steering, -1.0f, 1.0f);
}
}
@@ -1418,10 +1418,12 @@ void PhysicsBackend::EndSimulateScene(void* scene)
if (leftThrottle < -deadZone && rightThrottle > deadZone)
{
leftThrottle = 0;
+ leftBrake = 1;
}
else if (leftThrottle > deadZone && rightThrottle < -deadZone)
{
rightThrottle = 0;
+ rightBrake = 1;
}
}
From 07de7a26dd55fd0aaec3ea637cc7a4ec02f60d41 Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Mon, 1 Jan 2024 11:15:16 -0400
Subject: [PATCH 19/79] Expose vehicle pad smooth inputs
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 13 ++++
Source/Engine/Physics/Actors/WheeledVehicle.h | 66 ++++++++++++++++++-
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 56 ++++++++--------
3 files changed, 104 insertions(+), 31 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index a68bc23c7..243d9cc48 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -48,6 +48,16 @@ const Array &WheeledVehicle::GetWheels() const
return _wheels;
}
+WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
+{
+ return _driveControl;
+}
+
+void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
+{
+ _driveControl = value;
+}
+
void WheeledVehicle::SetWheels(const Array &value)
{
#if WITH_VEHICLE
@@ -376,11 +386,13 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
SERIALIZE_MEMBER(DriveType, _driveType);
SERIALIZE_MEMBER(DriveModes, _driveMode);
SERIALIZE_MEMBER(Wheels, _wheels);
+ SERIALIZE_MEMBER(DriveControl, _driveControl);
SERIALIZE(UseReverseAsBrake);
SERIALIZE(UseAnalogSteering);
SERIALIZE_MEMBER(Engine, _engine);
SERIALIZE_MEMBER(Differential, _differential);
SERIALIZE_MEMBER(Gearbox, _gearbox);
+
}
void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
@@ -390,6 +402,7 @@ void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *
DESERIALIZE_MEMBER(DriveType, _driveType);
DESERIALIZE_MEMBER(DriveModes, _driveMode);
DESERIALIZE_MEMBER(Wheels, _wheels);
+ DESERIALIZE_MEMBER(DriveControl, _driveControl);
DESERIALIZE(UseReverseAsBrake);
DESERIALIZE(UseAnalogSteering);
DESERIALIZE_MEMBER(Engine, _engine);
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index acf20310f..bfa3dc294 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -83,6 +83,55 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
OpenRearDrive,
};
+ ///
+ /// Vehicle drive control settings.
+ ///
+ API_STRUCT() struct DriveControlSettings : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(DriveControlSettings);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// Acceleration input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
+
+ ///
+ /// Deceleration input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(11)") float FallRateAcceleration = 10.0f;
+
+ ///
+ /// Brake input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(12)") float RiseRateBrake = 6.0f;
+
+ ///
+ /// Release brake sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(13)") float FallRateBrake = 10.0f;
+
+ ///
+ /// Brake input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
+
+ ///
+ /// Release handbrake sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(15)") float FallRateHandBrake = 12.0f;
+
+ ///
+ /// Steer input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(16)") float RiseRateSteer = 2.5f;
+
+ ///
+ /// Release steer input sensitive.
+ ///
+ API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(17)") float FallRateSteer = 5.0f;
+ };
+
///
/// Vehicle differential settings.
///
@@ -321,6 +370,7 @@ private:
Array> _wheelsData;
float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake;
Array _wheels;
+ DriveControlSettings _driveControl;
EngineSettings _engine;
DifferentialSettings _differential;
GearboxSettings _gearbox;
@@ -365,6 +415,16 @@ public:
///
API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const;
+ ///
+ /// Gets the vehicle drive control settings.
+ ///
+ API_PROPERTY(Attributes = "EditorOrder(5), EditorDisplay(\"Vehicle\")") DriveControlSettings GetDriveControl() const;
+
+ ///
+ /// Sets the vehicle drive control settings.
+ ///
+ API_PROPERTY() void SetDriveControl(DriveControlSettings& value);
+
///
/// Sets the vehicle wheels settings.
///
@@ -373,7 +433,7 @@ public:
///
/// Gets the vehicle engine settings.
///
- API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const;
+ API_PROPERTY(Attributes="EditorOrder(6), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const;
///
/// Sets the vehicle engine settings.
@@ -383,7 +443,7 @@ public:
///
/// Gets the vehicle differential settings.
///
- API_PROPERTY(Attributes="EditorOrder(6), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const;
+ API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const;
///
/// Sets the vehicle differential settings.
@@ -393,7 +453,7 @@ public:
///
/// Gets the vehicle gearbox settings.
///
- API_PROPERTY(Attributes="EditorOrder(7), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const;
+ API_PROPERTY(Attributes="EditorOrder(8), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const;
///
/// Sets the vehicle gearbox settings.
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index cb1d094a4..19743396c 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1557,38 +1557,38 @@ void PhysicsBackend::EndSimulateScene(void* scene)
// @formatter:off
// Reference: PhysX SDK docs
// TODO: expose input control smoothing data
- static constexpr PxVehiclePadSmoothingData padSmoothing =
- {
- {
- 6.0f, // rise rate eANALOG_INPUT_ACCEL
- 6.0f, // rise rate eANALOG_INPUT_BRAKE
- 12.0f, // rise rate eANALOG_INPUT_HANDBRAKE
- 2.5f, // rise rate eANALOG_INPUT_STEER_LEFT
- 2.5f, // rise rate eANALOG_INPUT_STEER_RIGHT
- },
- {
- 10.0f, // fall rate eANALOG_INPUT_ACCEL
- 10.0f, // fall rate eANALOG_INPUT_BRAKE
- 12.0f, // fall rate eANALOG_INPUT_HANDBRAKE
- 5.0f, // fall rate eANALOG_INPUT_STEER_LEFT
- 5.0f, // fall rate eANALOG_INPUT_STEER_RIGHT
- }
- };
- static constexpr PxVehicleKeySmoothingData keySmoothing =
+ PxVehiclePadSmoothingData padSmoothing =
+ {
+ {
+ wheelVehicle->_driveControl.RiseRateAcceleration, // rise rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.RiseRateBrake, // rise rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.RiseRateHandBrake, // rise rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_RIGHT
+ },
+ {
+ wheelVehicle->_driveControl.FallRateAcceleration, // fall rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.FallRateBrake, // fall rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.FallRateHandBrake, // fall rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
+ }
+ };
+ PxVehicleKeySmoothingData keySmoothing =
{
{
- 3.0f, // rise rate eANALOG_INPUT_ACCEL
- 3.0f, // rise rate eANALOG_INPUT_BRAKE
- 10.0f, // rise rate eANALOG_INPUT_HANDBRAKE
- 2.5f, // rise rate eANALOG_INPUT_STEER_LEFT
- 2.5f, // rise rate eANALOG_INPUT_STEER_RIGHT
+ wheelVehicle->_driveControl.RiseRateAcceleration, // rise rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.RiseRateBrake, // rise rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.RiseRateHandBrake, // rise rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_RIGHT
},
{
- 5.0f, // fall rate eANALOG_INPUT__ACCEL
- 5.0f, // fall rate eANALOG_INPUT__BRAKE
- 10.0f, // fall rate eANALOG_INPUT__HANDBRAKE
- 5.0f, // fall rate eANALOG_INPUT_STEER_LEFT
- 5.0f // fall rate eANALOG_INPUT_STEER_RIGHT
+ wheelVehicle->_driveControl.FallRateAcceleration, // fall rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.FallRateBrake, // fall rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.FallRateHandBrake, // fall rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
}
};
// Reference: PhysX SDK docs
From 045943ef27b257ad99d8407cc914dca0e7aaab39 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Mon, 1 Jan 2024 19:11:45 -0500
Subject: [PATCH 20/79] Fix prefab scale and rotation.
---
Source/Engine/ContentImporters/ImportModel.cpp | 4 +++-
Source/Engine/Tools/ModelTool/ModelTool.cpp | 10 ++++++++--
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index baac1defb..b6fd483d3 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -665,7 +665,9 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
// Setup node in hierarchy
nodeToActor.Add(nodeIndex, nodeActor);
nodeActor->SetName(node.Name);
- nodeActor->SetLocalTransform(node.LocalTransform);
+
+ // Only set translation, since scale and rotation is applied earlier.
+ nodeActor->SetLocalTransform(Transform(node.LocalTransform.Translation));
if (nodeIndex == 0)
{
// Special case for root actor to link any unlinked nodes
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index e2b2f5d8d..ac9cda8b6 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1292,7 +1292,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
!
#endif
}
- if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type != ModelType::Prefab)
+ if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
{
// Perform simple nodes mapping to single node (will transform meshes to model local space)
SkeletonMapping skeletonMapping(data.Nodes, nullptr);
@@ -1312,7 +1312,13 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex)
{
// Transform vertices
- const auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
+ auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
+ if (options.Type == ModelType::Prefab)
+ {
+ // Cancel out translation during mesh transformation, to set translation during prefab generation time.
+ transformationMatrix = transformationMatrix * transformationMatrix.Translation(transformationMatrix.GetTranslation() * -1.0f);
+ }
+
if (!transformationMatrix.IsIdentity())
mesh.TransformBuffer(transformationMatrix);
}
From 827365679376134569561c2bfd83a20827f72059 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Mon, 1 Jan 2024 20:24:13 -0500
Subject: [PATCH 21/79] Fix major issue with transformation.
---
.../Engine/ContentImporters/ImportModel.cpp | 5 +++-
Source/Engine/Tools/ModelTool/ModelTool.cpp | 30 +++++++++++++++----
2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index b6fd483d3..ac2bacd25 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -666,8 +666,11 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
nodeToActor.Add(nodeIndex, nodeActor);
nodeActor->SetName(node.Name);
+ Transform positionOffset = Transform::Identity;
+ positionOffset.Translation = node.LocalTransform.Translation;
+ LOG(Warning, "node name: {0}, offset transform: {1}", node.Name, positionOffset);
// Only set translation, since scale and rotation is applied earlier.
- nodeActor->SetLocalTransform(Transform(node.LocalTransform.Translation));
+ nodeActor->SetLocalTransform(positionOffset);
if (nodeIndex == 0)
{
// Special case for root actor to link any unlinked nodes
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index ac9cda8b6..899f67a1f 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1292,7 +1292,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
!
#endif
}
- if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
+ if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && !(options.Type == ModelType::Prefab))
{
// Perform simple nodes mapping to single node (will transform meshes to model local space)
SkeletonMapping skeletonMapping(data.Nodes, nullptr);
@@ -1313,11 +1313,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
{
// Transform vertices
auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
- if (options.Type == ModelType::Prefab)
- {
- // Cancel out translation during mesh transformation, to set translation during prefab generation time.
- transformationMatrix = transformationMatrix * transformationMatrix.Translation(transformationMatrix.GetTranslation() * -1.0f);
- }
if (!transformationMatrix.IsIdentity())
mesh.TransformBuffer(transformationMatrix);
@@ -1328,6 +1323,29 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
}
}
}
+ if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type == ModelType::Prefab)
+ {
+ // Apply just the scale and rotations.
+ for (int32 lodIndex = 0; lodIndex < data.LODs.Count(); lodIndex++)
+ {
+ for (int32 meshIndex = 0; meshIndex < data.LODs[lodIndex].Meshes.Count(); meshIndex++)
+ {
+ auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex];
+ auto& node = data.Nodes[mesh.NodeIndex];
+
+ // Transform vertices
+ auto transformationMatrix = Matrix::Identity;
+ transformationMatrix.SetScaleVector(node.LocalTransform.Scale);
+
+ Matrix rotation;
+ node.LocalTransform.GetRotation(rotation);
+ transformationMatrix = transformationMatrix * rotation;
+
+ if (!transformationMatrix.IsIdentity())
+ mesh.TransformBuffer(transformationMatrix);
+ }
+ }
+ }
if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Animations))
{
for (auto& animation : data.Animations)
From ab51ca6e705e8110db9e14e7e40f7e16bf8c93c3 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Mon, 1 Jan 2024 21:35:18 -0500
Subject: [PATCH 22/79] Change behavior when Use Local Origin is checked.
---
.../Engine/ContentImporters/ImportModel.cpp | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index ac2bacd25..a2629baf4 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -666,11 +666,20 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
nodeToActor.Add(nodeIndex, nodeActor);
nodeActor->SetName(node.Name);
- Transform positionOffset = Transform::Identity;
- positionOffset.Translation = node.LocalTransform.Translation;
- LOG(Warning, "node name: {0}, offset transform: {1}", node.Name, positionOffset);
- // Only set translation, since scale and rotation is applied earlier.
- nodeActor->SetLocalTransform(positionOffset);
+ // When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that.
+ if (!(nodeIndex == 0 && options.UseLocalOrigin))
+ {
+ // Only set translation, since scale and rotation is applied earlier.
+ Transform positionOffset = Transform::Identity;
+ positionOffset.Translation = node.LocalTransform.Translation;
+ if (options.UseLocalOrigin)
+ {
+ positionOffset.Translation += data.Nodes[0].LocalTransform.Translation;
+ }
+
+ nodeActor->SetLocalTransform(positionOffset);
+ }
+
if (nodeIndex == 0)
{
// Special case for root actor to link any unlinked nodes
From 8bd84e0616609916e8262a4dd353833d502cc1d8 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Tue, 2 Jan 2024 03:52:57 -0500
Subject: [PATCH 23/79] Fix sub-mesh reimporting with some potentially hacky
workarounds?
---
Source/Engine/ContentImporters/ImportModel.cpp | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index a2629baf4..08c9e707f 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -269,7 +269,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
// Import all of the objects recursive but use current model data to skip loading file again
options.Cached = &cached;
- Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath)
+ Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData& meshData)
{
// Recursive importing of the split object
String postFix = objectName;
@@ -279,6 +279,17 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
// TODO: check for name collisions with material/texture assets
outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax");
splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above)
+
+ if (splitOptions.Type == ModelTool::ModelType::Model)
+ {
+ // These settings interfere with submesh reimporting.
+ splitOptions.CenterGeometry = false;
+ splitOptions.UseLocalOrigin = false;
+
+ // This properly sets the transformation of the mesh during reimport.
+ splitOptions.Translation = meshData.OriginTranslation * -1.0f;
+ }
+
return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions);
};
auto splitOptions = options;
@@ -294,7 +305,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
splitOptions.Type = ModelTool::ModelType::Model;
splitOptions.ObjectIndex = groupIndex;
- if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath))
+ if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, *group.First()))
{
prefabObjects.Add(prefabObject);
}
@@ -305,7 +316,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
auto& animation = data->Animations[i];
splitOptions.Type = ModelTool::ModelType::Animation;
splitOptions.ObjectIndex = i;
- splitImport(splitOptions, animation.Name, prefabObject.AssetPath);
+ splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData());
}
}
else if (options.SplitObjects)
From 31adfd2c9cfe50276e19fe658a27a6934a2d323c Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Tue, 2 Jan 2024 04:27:35 -0500
Subject: [PATCH 24/79] Attempt to fix builds on unix.
---
Source/Engine/ContentImporters/ImportModel.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index 08c9e707f..c034bbc0e 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -316,7 +316,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
auto& animation = data->Animations[i];
splitOptions.Type = ModelTool::ModelType::Animation;
splitOptions.ObjectIndex = i;
- splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData());
+ splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData::MeshData());
}
}
else if (options.SplitObjects)
From 6178cb1bf4f014b09ae339650597885957dd2cca Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Tue, 2 Jan 2024 12:36:17 -0500
Subject: [PATCH 25/79] attempt 2 at fixing the build regression.
---
Source/Engine/ContentImporters/ImportModel.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index c034bbc0e..67479db24 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -316,7 +316,9 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
auto& animation = data->Animations[i];
splitOptions.Type = ModelTool::ModelType::Animation;
splitOptions.ObjectIndex = i;
- splitImport(splitOptions, animation.Name, prefabObject.AssetPath, MeshData::MeshData());
+
+ MeshData empty;
+ splitImport(splitOptions, animation.Name, prefabObject.AssetPath, empty);
}
}
else if (options.SplitObjects)
From 42b20b4e764008052c059e172601c81516ccb7de Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Tue, 2 Jan 2024 20:39:24 -0400
Subject: [PATCH 26/79] Expose vehicle relationship between speed and steer to
driver
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 43 +++++++++++-
Source/Engine/Physics/Actors/WheeledVehicle.h | 67 ++++++++++++++++---
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 41 +++++++-----
3 files changed, 126 insertions(+), 25 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 243d9cc48..29d1a9e63 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -55,6 +55,48 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
{
+ // Don't let have an invalid steer vs speed list.
+ if (&value.SteerVsSpeed == nullptr)
+ value.SteerVsSpeed = Array();
+
+ if (value.SteerVsSpeed.Count() < 1)
+ value.SteerVsSpeed.Add(WheeledVehicle::SteerControl());
+ else // physx backend requires the max of 4 values only
+ while (value.SteerVsSpeed.Count() > 4)
+ value.SteerVsSpeed.RemoveLast();
+
+ // Maintain all values clamped to have a ordened speed list
+ int steerVsSpeedCount = value.SteerVsSpeed.Count();
+ for (int i = 0; i < steerVsSpeedCount; i++)
+ {
+ // Apply only on changed value
+ if (_driveControl.SteerVsSpeed[i].Speed != value.SteerVsSpeed[i].Speed || _driveControl.SteerVsSpeed[i].Steer != value.SteerVsSpeed[i].Steer)
+ {
+ WheeledVehicle::SteerControl &steerVsSpeed = value.SteerVsSpeed[i];
+ steerVsSpeed.Steer = Math::Saturate(steerVsSpeed.Steer);
+ steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, 10.0f);
+
+ // Clamp speeds to have an ordened list.
+ if (i >= 1)
+ {
+ WheeledVehicle::SteerControl &lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
+ WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
+ float minSpeed = lastSteerVsSpeed.Speed;
+ float maxSpeed = nextSteerVsSpeed.Speed;
+
+ if (i + 1 < steerVsSpeedCount - 1)
+ steerVsSpeed.Speed = Math::Clamp(steerVsSpeed.Speed, minSpeed, maxSpeed);
+ else
+ steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, minSpeed);
+ }
+ else if (steerVsSpeedCount > 1)
+ {
+ WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
+ steerVsSpeed.Speed = Math::Min(steerVsSpeed.Speed, nextSteerVsSpeed.Speed);
+ }
+ }
+ }
+
_driveControl = value;
}
@@ -392,7 +434,6 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
SERIALIZE_MEMBER(Engine, _engine);
SERIALIZE_MEMBER(Differential, _differential);
SERIALIZE_MEMBER(Gearbox, _gearbox);
-
}
void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index bfa3dc294..7d7c782df 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -40,6 +40,45 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
Special
};
+ ///
+ /// Storage the relationship between speed and steer.
+ ///
+ API_STRUCT() struct SteerControl : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(SteerControl);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// The vehicle speed.
+ ///
+ API_FIELD(Attributes = "Limit(0)") float Speed;
+
+ ///
+ /// The target max steer of the speed.
+ ///
+ API_FIELD(Attributes = "Limit(0, 1)") float Steer;
+
+ ///
+ /// Create a Steer/Speed relationship structure.
+ ///
+ SteerControl()
+ {
+ Speed = 1000;
+ Steer = 1;
+ }
+
+ ///
+ /// Create a Steer/Speed relationship structure.
+ /// The vehicle speed.
+ /// The target max steer of the speed.
+ ///
+ SteerControl(float speed, float steer)
+ {
+ Speed = speed;
+ Steer = steer;
+ }
+ };
+
///
/// Vehicle engine settings.
///
@@ -94,42 +133,54 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// Acceleration input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
///
/// Deceleration input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(11)") float FallRateAcceleration = 10.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(11)") float FallRateAcceleration = 10.0f;
///
/// Brake input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(12)") float RiseRateBrake = 6.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(12)") float RiseRateBrake = 6.0f;
///
/// Release brake sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(13)") float FallRateBrake = 10.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(13)") float FallRateBrake = 10.0f;
///
/// Brake input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
///
/// Release handbrake sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(15)") float FallRateHandBrake = 12.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(15)") float FallRateHandBrake = 12.0f;
///
/// Steer input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(16)") float RiseRateSteer = 2.5f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(16)") float RiseRateSteer = 2.5f;
///
/// Release steer input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Inputs\"), EditorOrder(17)") float FallRateSteer = 5.0f;
+ API_FIELD(Attributes="Limit(0), EditorOrder(17)") float FallRateSteer = 5.0f;
+
+ ///
+ /// Vehicle control relationship between speed and steer. The higher is the speed,
+ /// decrease steer to make vehicle more maneuverable (limited only 4 relationships).
+ ///
+ API_FIELD() Array SteerVsSpeed = Array
+ {
+ SteerControl(800, 1.0f),
+ SteerControl(1500, 0.7f),
+ SteerControl(2500, 0.5f),
+ SteerControl(5000, 0.2f),
+ };
};
///
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 19743396c..98fbf7596 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1554,9 +1554,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
leftBrake = 1.0f;
}
- // @formatter:off
- // Reference: PhysX SDK docs
- // TODO: expose input control smoothing data
+ // Smooth input controls
PxVehiclePadSmoothingData padSmoothing =
{
{
@@ -1591,20 +1589,31 @@ void PhysicsBackend::EndSimulateScene(void* scene)
wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
}
};
- // Reference: PhysX SDK docs
- // TODO: expose steer vs forward curve into per-vehicle (up to 8 points, values clamped into 0/1 range)
- static constexpr PxF32 steerVsForwardSpeedData[] =
+
+ // Reduce steer by speed to make vehicle more easier to maneuver
+
+ constexpr int steerVsSpeedN = 8;
+ PxF32 steerVsForwardSpeedData[steerVsSpeedN];
+ const int lastSteerVsSpeedIndex = wheelVehicle->_driveControl.SteerVsSpeed.Count() - 1;
+ int steerVsSpeedIndex = 0;
+
+ // Steer vs speed data structure example:
+ // array:
+ // speed, steer
+ // 1000, 1.0,
+ // 2000, 0.7,
+ // 5000, 0.5,
+ // ..
+
+ // fill the steerVsForwardSpeedData with the speed and steer
+ for (int i = 0; i < 8; i += 2)
{
- 0.0f, 1.0f,
- 20.0f, 0.9f,
- 65.0f, 0.8f,
- 120.0f, 0.7f,
- PX_MAX_F32, PX_MAX_F32,
- PX_MAX_F32, PX_MAX_F32,
- PX_MAX_F32, PX_MAX_F32,
- PX_MAX_F32, PX_MAX_F32,
- };
- const PxFixedSizeLookupTable<8> steerVsForwardSpeed(steerVsForwardSpeedData, 4);
+ steerVsForwardSpeedData[i] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Speed;
+ steerVsForwardSpeedData[i + 1] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Steer;
+ steerVsSpeedIndex = Math::Min(steerVsSpeedIndex + 1, lastSteerVsSpeedIndex);
+ }
+ const PxFixedSizeLookupTable steerVsForwardSpeed(steerVsForwardSpeedData, 4);
+
// @formatter:on
if (wheelVehicle->UseAnalogSteering)
{
From a102bad87ed0461b3c80bd9252c045bbb7d9c8fd Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Tue, 2 Jan 2024 22:28:23 -0400
Subject: [PATCH 27/79] Change wheel steer angle limit
---
Source/Engine/Physics/Actors/WheeledVehicle.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 7d7c782df..f7288a240 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -282,9 +282,9 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
API_FIELD(Attributes="EditorOrder(3)") float Width = 20.0f;
///
- /// Max steer angle that can be achieved by the wheel (in degrees).
+ /// Max steer angle that can be achieved by the wheel (in degrees, -180 to 180).
///
- API_FIELD(Attributes="Limit(0), EditorDisplay(\"Steering\"), EditorOrder(10)") float MaxSteerAngle = 0.0f;
+ API_FIELD(Attributes="Limit(-180, 180), EditorDisplay(\"Steering\"), EditorOrder(10)") float MaxSteerAngle = 0.0f;
///
/// Damping rate applied to wheel. Specified in kilograms metres-squared per second (kg m^2 s^-1).
From 1b9984c728088320e7b63fd36d304080f4cc56d1 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Wed, 3 Jan 2024 20:16:57 -0500
Subject: [PATCH 28/79] Fix static import of GLTF (and presumably other assimp)
model types.
---
Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index e62d03b1c..c67a48705 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -790,6 +790,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
aiProcess_GenUVCoords |
aiProcess_FindDegenerates |
aiProcess_FindInvalidData |
+ aiProcess_GlobalScale |
//aiProcess_ValidateDataStructure |
aiProcess_ConvertToLeftHanded;
if (importMeshes)
@@ -807,6 +808,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
// Setup import options
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, options.SmoothingNormalsAngle);
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, options.SmoothingTangentsAngle);
+ context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm?
//context.AssimpImporter.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, MAX_uint16);
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, false);
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, false);
From 7d07ed20ea1b8a04d21956e112e15dea1aecfa84 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Wed, 3 Jan 2024 22:20:59 -0500
Subject: [PATCH 29/79] major improvements
---
.../Tools/ModelTool/ModelTool.Assimp.cpp | 74 ++++++-------------
Source/Engine/Tools/ModelTool/ModelTool.cpp | 23 ++++--
2 files changed, 39 insertions(+), 58 deletions(-)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index c67a48705..6041cbb4f 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -484,6 +484,26 @@ bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMes
}
}
+ AssimpNode* curNode = &data.Nodes[mesh.NodeIndex];
+ Vector3 translation = Vector3::Zero;
+ Vector3 scale = Vector3::One;
+ Quaternion rotation = Quaternion::Identity;
+
+ while(true)
+ {
+ translation += curNode->LocalTransform.Translation;
+ scale *= curNode->LocalTransform.Scale;
+ rotation *= curNode->LocalTransform.Orientation;
+
+ if (curNode->ParentIndex == -1)
+ break;
+ curNode = &data.Nodes[curNode->ParentIndex];
+ }
+
+ mesh.OriginTranslation = translation;
+ mesh.OriginOrientation = rotation;
+ mesh.Scaling = scale;
+
return false;
}
@@ -624,6 +644,7 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String
// Import mesh data
MeshData* meshData = New();
+ meshData->NodeIndex = data.MeshIndexToNodeIndex[index][0];
if (ProcessMesh(result, data, aMesh, *meshData, errorMsg))
{
Delete(meshData);
@@ -650,59 +671,6 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String
result.LODs[lodIndex].Meshes.Add(meshData);
}
- auto root = data.Scene->mRootNode;
- Array points;
- if (root->mNumChildren == 0)
- {
- aiQuaternion aiQuat;
- aiVector3D aiPos;
- aiVector3D aiScale;
- root->mTransformation.Decompose(aiScale, aiQuat, aiPos);
- auto quat = ToQuaternion(aiQuat);
- auto pos = ToFloat3(aiPos);
- auto scale = ToFloat3(aiScale);
- Transform trans = Transform(pos, quat, scale);
- points.Add(trans);
- }
- else
- {
- for (unsigned int j = 0; j < root->mNumChildren; j++)
- {
- aiQuaternion aiQuat;
- aiVector3D aiPos;
- aiVector3D aiScale;
- root->mChildren[j]->mTransformation.Decompose(aiScale, aiQuat, aiPos);
- auto quat = ToQuaternion(aiQuat);
- auto pos = ToFloat3(aiPos);
- auto scale = ToFloat3(aiScale);
- Transform trans = Transform(pos, quat, scale);
- points.Add(trans);
- }
- }
-
- Float3 translation = Float3::Zero;
- Float3 scale = Float3::Zero;
- Quaternion orientation = Quaternion::Identity;
- for (auto point : points)
- {
- translation += point.Translation;
- scale += point.Scale;
- orientation *= point.Orientation;
- }
-
- if (points.Count() > 0)
- {
- meshData->OriginTranslation = translation / (float)points.Count();
- meshData->OriginOrientation = Quaternion::Invert(orientation);
- meshData->Scaling = scale / (float)points.Count();
- }
- else
- {
- meshData->OriginTranslation = translation;
- meshData->OriginOrientation = Quaternion::Invert(orientation);
- meshData->Scaling = Float3(1);
- }
-
return false;
}
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index 899f67a1f..8d5db063f 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1333,13 +1333,26 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex];
auto& node = data.Nodes[mesh.NodeIndex];
+ auto currentNode = &data.Nodes[mesh.NodeIndex];
+
+ Vector3 scale = Vector3::One;
+ Quaternion rotation = Quaternion::Identity;
+ while (true)
+ {
+ scale *= currentNode->LocalTransform.Scale;
+ rotation *= currentNode->LocalTransform.Orientation;
+
+ if (currentNode->ParentIndex == -1)
+ {
+ break;
+ }
+ currentNode = &data.Nodes[currentNode->ParentIndex];
+ }
+
// Transform vertices
auto transformationMatrix = Matrix::Identity;
- transformationMatrix.SetScaleVector(node.LocalTransform.Scale);
-
- Matrix rotation;
- node.LocalTransform.GetRotation(rotation);
- transformationMatrix = transformationMatrix * rotation;
+ transformationMatrix.SetScaleVector(scale);
+ transformationMatrix = transformationMatrix * Matrix::RotationQuaternion(rotation);
if (!transformationMatrix.IsIdentity())
mesh.TransformBuffer(transformationMatrix);
From 35832e5b1c55e6075484645f245490a229af5629 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Thu, 4 Jan 2024 00:57:20 -0500
Subject: [PATCH 30/79] Proper fix now?
---
.../Engine/ContentImporters/ImportModel.cpp | 41 ++++++++++++++++++-
.../Tools/ModelTool/ModelTool.Assimp.cpp | 6 +--
2 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index 67479db24..cf66762ad 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -287,7 +287,23 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
splitOptions.UseLocalOrigin = false;
// This properly sets the transformation of the mesh during reimport.
- splitOptions.Translation = meshData.OriginTranslation * -1.0f;
+ auto* nodes = &splitOptions.Cached->Data->Nodes;
+ Vector3 scale = Vector3::One;
+
+ // TODO: Improve this hack.
+ // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there.
+ auto* currentNode = &(*nodes)[meshData.NodeIndex];
+ while (true)
+ {
+ if (currentNode->ParentIndex == -1)
+ {
+ scale *= currentNode->LocalTransform.Scale;
+ break;
+ }
+ currentNode = &(*nodes)[currentNode->ParentIndex];
+ }
+
+ splitOptions.Translation = meshData.OriginTranslation * scale * -1.0f;
}
return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions);
@@ -682,9 +698,30 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, ModelDa
// When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that.
if (!(nodeIndex == 0 && options.UseLocalOrigin))
{
+ // TODO: Improve this hack.
+ // Assimp importer has the meter -> centimeter conversion scale applied to the local transform of
+ // the root node, and only the root node. The OpenFBX importer has the same scale applied
+ // to each node, *except* the root node. This difference makes it hard to calculate the
+ // global scale properly. Position offsets are not calculated properly from Assimp without summing up
+ // the global scale because translations from Assimp don't get scaled with the global scaler option,
+ // but the OpenFBX importer does scale them. So this hack will end up only applying the global scale
+ // change if its using Assimp due to the difference in where the nodes' local transform scales are set.
+ auto* currentNode = &node;
+ Vector3 scale = Vector3::One;
+ while (true)
+ {
+ if (currentNode->ParentIndex == -1)
+ {
+ scale *= currentNode->LocalTransform.Scale;
+ break;
+ }
+ currentNode = &data.Nodes[currentNode->ParentIndex];
+ }
+
// Only set translation, since scale and rotation is applied earlier.
Transform positionOffset = Transform::Identity;
- positionOffset.Translation = node.LocalTransform.Translation;
+ positionOffset.Translation = node.LocalTransform.Translation * scale;
+
if (options.UseLocalOrigin)
{
positionOffset.Translation += data.Nodes[0].LocalTransform.Translation;
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index 6041cbb4f..8ce3cc0d0 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -797,14 +797,14 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
}
// Create root node
- AssimpNode& rootNode = context.Nodes.AddOne();
+ /*AssimpNode& rootNode = context.Nodes.AddOne();
rootNode.ParentIndex = -1;
rootNode.LodIndex = 0;
- rootNode.Name = TEXT("Root");
rootNode.LocalTransform = Transform::Identity;
+ rootNode.Name = TEXT("Root");*/
// Process imported scene nodes
- ProcessNodes(context, context.Scene->mRootNode, 0);
+ ProcessNodes(context, context.Scene->mRootNode, -1);
// Import materials
if (ImportMaterials(data, context, errorMsg))
From 7e948de2db4c65e08c20aa03a96bbfaf138ace52 Mon Sep 17 00:00:00 2001
From: Menotdan <32620310+Menotdan@users.noreply.github.com>
Date: Thu, 4 Jan 2024 15:29:23 -0500
Subject: [PATCH 31/79] Handle multiple nodes having the same mesh (probably?)
---
.../Tools/ModelTool/ModelTool.Assimp.cpp | 42 +++++++++----------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index 8ce3cc0d0..85e320ee6 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -483,27 +483,6 @@ bool ProcessMesh(ModelData& result, AssimpImporterData& data, const aiMesh* aMes
}
}
}
-
- AssimpNode* curNode = &data.Nodes[mesh.NodeIndex];
- Vector3 translation = Vector3::Zero;
- Vector3 scale = Vector3::One;
- Quaternion rotation = Quaternion::Identity;
-
- while(true)
- {
- translation += curNode->LocalTransform.Translation;
- scale *= curNode->LocalTransform.Scale;
- rotation *= curNode->LocalTransform.Orientation;
-
- if (curNode->ParentIndex == -1)
- break;
- curNode = &data.Nodes[curNode->ParentIndex];
- }
-
- mesh.OriginTranslation = translation;
- mesh.OriginOrientation = rotation;
- mesh.Scaling = scale;
-
return false;
}
@@ -644,7 +623,6 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String
// Import mesh data
MeshData* meshData = New();
- meshData->NodeIndex = data.MeshIndexToNodeIndex[index][0];
if (ProcessMesh(result, data, aMesh, *meshData, errorMsg))
{
Delete(meshData);
@@ -666,6 +644,26 @@ bool ImportMesh(int32 index, ModelData& result, AssimpImporterData& data, String
// Link mesh
meshData->NodeIndex = nodeIndex;
+ AssimpNode* curNode = &data.Nodes[meshData->NodeIndex];
+ Vector3 translation = Vector3::Zero;
+ Vector3 scale = Vector3::One;
+ Quaternion rotation = Quaternion::Identity;
+
+ while (true)
+ {
+ translation += curNode->LocalTransform.Translation;
+ scale *= curNode->LocalTransform.Scale;
+ rotation *= curNode->LocalTransform.Orientation;
+
+ if (curNode->ParentIndex == -1)
+ break;
+ curNode = &data.Nodes[curNode->ParentIndex];
+ }
+
+ meshData->OriginTranslation = translation;
+ meshData->OriginOrientation = rotation;
+ meshData->Scaling = scale;
+
if (result.LODs.Count() <= lodIndex)
result.LODs.Resize(lodIndex + 1);
result.LODs[lodIndex].Meshes.Add(meshData);
From 14a4c92aa846d4bdea766c7ec90270d72af39295 Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sat, 6 Jan 2024 14:49:38 -0400
Subject: [PATCH 32/79] Add Vehicle anti roll bar and suspension sprung force
multiplier
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 47 ++++++++----
Source/Engine/Physics/Actors/WheeledVehicle.h | 37 +++++++++-
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 73 ++++++++++++++++---
Source/Engine/Physics/PhysicsBackend.h | 1 +
4 files changed, 130 insertions(+), 28 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 29d1a9e63..66a13fd7f 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -56,9 +56,6 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
{
// Don't let have an invalid steer vs speed list.
- if (&value.SteerVsSpeed == nullptr)
- value.SteerVsSpeed = Array();
-
if (value.SteerVsSpeed.Count() < 1)
value.SteerVsSpeed.Add(WheeledVehicle::SteerControl());
else // physx backend requires the max of 4 values only
@@ -171,6 +168,20 @@ void WheeledVehicle::SetGearbox(const GearboxSettings &value)
_gearbox = value;
}
+void WheeledVehicle::SetAntiRollBars(const Array &value)
+{
+ _antiRollBars = value;
+#if WITH_VEHICLE
+ if (_vehicle)
+ PhysicsBackend::UpdateVehicleAntiRollBars(this);
+#endif
+}
+
+const Array &WheeledVehicle::GetAntiRollBars() const
+{
+ return _antiRollBars;
+}
+
void WheeledVehicle::SetThrottle(float value)
{
_throttle = Math::Clamp(value, -1.0f, 1.0f);
@@ -398,20 +409,24 @@ void WheeledVehicle::OnDebugDrawSelected()
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(data.State.TireContactPoint, 5.0f), Color::Green, 0, false);
}
}
-
- // Draw wheels axes
- if (wheelIndex % 2 == 0 && wheelIndex + 1 < _wheels.Count())
- {
- if (!_wheels[wheelIndex].Collider || !_wheels[wheelIndex + 1].Collider)
- continue;
-
- const Vector3 wheelPos = _wheels[wheelIndex].Collider->GetPosition();
- const Vector3 nextWheelPos = _wheels[wheelIndex + 1].Collider->GetPosition();
- DEBUG_DRAW_LINE(wheelPos, nextWheelPos, Color::Yellow, 0, false);
- }
}
- // Center of mass
+ // Draw anti roll bars axes
+ int wheelsCount = _wheels.Count();
+ for (int i = 0; i < GetAntiRollBars().Count(); i++)
+ {
+ int axleIndex = GetAntiRollBars()[i].Axle;
+ int leftWheelIndex = axleIndex * 2;
+ int rightWheelIndex = leftWheelIndex + 1;
+
+ if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
+ continue;
+ if (!_wheels[leftWheelIndex].Collider || !_wheels[rightWheelIndex].Collider)
+ continue;
+
+ DEBUG_DRAW_LINE(_wheels[leftWheelIndex].Collider->GetPosition(), _wheels[rightWheelIndex].Collider->GetPosition(), Color::Yellow, 0, false);
+ }
+ // Center of mass
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(_transform.LocalToWorld(_centerOfMassOffset), 10.0f), Color::Blue, 0, false);
RigidBody::OnDebugDrawSelected();
@@ -434,6 +449,7 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
SERIALIZE_MEMBER(Engine, _engine);
SERIALIZE_MEMBER(Differential, _differential);
SERIALIZE_MEMBER(Gearbox, _gearbox);
+ SERIALIZE_MEMBER(AntiRollBars, _antiRollBars);
}
void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
@@ -449,6 +465,7 @@ void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *
DESERIALIZE_MEMBER(Engine, _engine);
DESERIALIZE_MEMBER(Differential, _differential);
DESERIALIZE_MEMBER(Gearbox, _gearbox);
+ DESERIALIZE_MEMBER(AntiRollBars, _antiRollBars);
// [Deprecated on 13.06.2023, expires on 13.06.2025]
_fixInvalidForwardDir |= modifier->EngineBuild < 6341;
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index f7288a240..2048a2f46 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -306,6 +306,11 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
API_FIELD(Attributes="EditorOrder(4)") ScriptingObjectReference Collider;
+ ///
+ /// Spring sprung mass force multiplier.
+ ///
+ API_FIELD(Attributes="Limit(0.01f), EditorDisplay(\"Suspension\"), EditorOrder(19)") float SprungMassMultiplier = 1.0f;
+
///
/// Spring damper rate of suspension unit.
///
@@ -407,6 +412,25 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
#endif
};
+ ///
+ /// Vehicle axle anti roll bar.
+ ///
+ API_STRUCT() struct AntiRollBar : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(AntiRollBar);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// The specific axle with wheels to apply anti roll.
+ ///
+ API_FIELD() int Axle;
+
+ ///
+ /// The anti roll stiffness.
+ ///
+ API_FIELD() float Stiffness;
+ };
+
private:
struct WheelData
{
@@ -420,7 +444,8 @@ private:
DriveModes _driveMode = DriveModes::Standard;
Array> _wheelsData;
float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake;
- Array _wheels;
+ Array _wheels;
+ Array _antiRollBars;
DriveControlSettings _driveControl;
EngineSettings _engine;
DifferentialSettings _differential;
@@ -511,6 +536,16 @@ public:
///
API_PROPERTY() void SetGearbox(const GearboxSettings& value);
+ //
+ /// Sets axles anti roll bars to increase vehicle estability.
+ ///
+ API_PROPERTY() void SetAntiRollBars(const Array& value);
+
+ //
+ /// Gets axles anti roll bars.
+ ///
+ API_PROPERTY() const Array& GetAntiRollBars() const;
+
public:
///
/// Sets the input for vehicle throttle. It is the analog accelerator pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 98fbf7596..70ac6a2af 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include
#endif
#if WITH_CLOTH
@@ -3333,7 +3334,7 @@ PxVehicleSuspensionData CreatePxVehicleSuspensionData(const WheeledVehicle::Whee
const float suspensionFrequency = 7.0f;
suspensionData.mMaxCompression = settings.SuspensionMaxRaise;
suspensionData.mMaxDroop = settings.SuspensionMaxDrop;
- suspensionData.mSprungMass = wheelSprungMass;
+ suspensionData.mSprungMass = wheelSprungMass * settings.SprungMassMultiplier;
suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass;
suspensionData.mSpringDamperRate = settings.SuspensionDampingRate * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass);
return suspensionData;
@@ -3380,23 +3381,29 @@ PxVehicleAckermannGeometryData CreatePxVehicleAckermannGeometryData(PxVehicleWhe
return ackermann;
}
-bool SortWheelsFrontToBack(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
+PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle::AntiRollBar& settings, int leftWheelIndex, int rightWheelIndex)
+{
+ PxVehicleAntiRollBarData antiRollBar;
+ antiRollBar.mWheel0 = leftWheelIndex;
+ antiRollBar.mWheel1 = rightWheelIndex;
+ antiRollBar.mStiffness = settings.Stiffness;
+ return antiRollBar;
+}
+
+bool SortWheelsFrontToBack(WheeledVehicle::Wheel const &a, WheeledVehicle::Wheel const &b)
{
return a.Collider && b.Collider && a.Collider->GetLocalPosition().Z > b.Collider->GetLocalPosition().Z;
}
void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
{
-#if USE_EDITOR
- if (Editor::IsPlayMode)
-#endif
+ // Physx vehicles needs to have all wheels sorted to apply controls correctly.
+ // Its needs to know what wheels are on front to turn wheel to correctly side
+ // and needs to know wheel side to apply throttle to correctly direction for each track when using tanks.
+ // Anti roll bars needs to have all wheels sorted to get correctly wheel index too.
+ if (actor->_driveType != WheeledVehicle::DriveTypes::NoDrive)
{
- // Physx vehicles needs to have all wheels sorted to apply controls correctly.
- // Its needs to know what wheels are on front to turn wheel to correctly side
- // and needs to know wheel side to apply throttle to correctly direction for each track when using tanks.
-
- if (actor->_driveType == WheeledVehicle::DriveTypes::Drive4W)
- Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack);
+ Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack);
// sort wheels by side
if (actor->_driveType == WheeledVehicle::DriveTypes::Tank)
@@ -3468,7 +3475,8 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// TODO: get gravityDirection from scenePhysX->Scene->getGravity()
PxVehicleComputeSprungMasses(wheels.Count(), offsets, centerOfMassOffset.p, mass, 1, sprungMasses);
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(wheels.Count());
- for (int32 i = 0; i < wheels.Count(); i++)
+ int wheelsCount = wheels.Count();
+ for (int32 i = 0; i < wheelsCount; i++)
{
auto& wheel = *wheels[i];
@@ -3514,6 +3522,19 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
wheelsSimData->disableWheel(i);
}
}
+ // Add Anti roll bars for wheels axles
+ for (int i = 0; i < actor->GetAntiRollBars().Count(); i++)
+ {
+ int axleIndex = actor->GetAntiRollBars()[i].Axle;
+ int leftWheelIndex = axleIndex * 2;
+ int rightWheelIndex = leftWheelIndex + 1;
+
+ if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
+ continue;
+
+ const PxVehicleAntiRollBarData &antiRollBar = CreatePxPxVehicleAntiRollBarData(actor->GetAntiRollBars()[i], leftWheelIndex, rightWheelIndex);
+ wheelsSimData->addAntiRollBarData(antiRollBar);
+ }
for (auto child : actor->Children)
{
auto collider = ScriptingObject::Cast(child);
@@ -3676,6 +3697,34 @@ void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor)
}
}
+void PhysicsBackend::UpdateVehicleAntiRollBars(WheeledVehicle *actor)
+{
+ int wheelsCount = actor->_wheels.Count();
+ auto drive = (PxVehicleWheels *)actor->_vehicle;
+ PxVehicleWheelsSimData *wheelsSimData = &drive->mWheelsSimData;
+
+ // Update Anti roll bars for wheels axles
+ for (int i = 0; i < actor->GetAntiRollBars().Count(); i++)
+ {
+ int axleIndex = actor->GetAntiRollBars()[i].Axle;
+ int leftWheelIndex = axleIndex * 2;
+ int rightWheelIndex = leftWheelIndex + 1;
+
+ if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
+ continue;
+
+ const PxVehicleAntiRollBarData &antiRollBar = CreatePxPxVehicleAntiRollBarData(actor->GetAntiRollBars()[i], leftWheelIndex, rightWheelIndex);
+ if (wheelsSimData->getNbAntiRollBarData() - 1 < i)
+ {
+ wheelsSimData->addAntiRollBarData(antiRollBar);
+ }
+ else
+ {
+ wheelsSimData->setAntiRollBarData(axleIndex, antiRollBar);
+ }
+ }
+}
+
void PhysicsBackend::SetVehicleEngine(void* vehicle, const void* value)
{
auto drive = (PxVehicleDrive*)vehicle;
diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h
index f20683e31..63c14fdc3 100644
--- a/Source/Engine/Physics/PhysicsBackend.h
+++ b/Source/Engine/Physics/PhysicsBackend.h
@@ -262,6 +262,7 @@ public:
static void* CreateVehicle(class WheeledVehicle* actor);
static void DestroyVehicle(void* vehicle, int32 driveType);
static void UpdateVehicleWheels(WheeledVehicle* actor);
+ static void UpdateVehicleAntiRollBars(WheeledVehicle* actor);
static void SetVehicleEngine(void* vehicle, const void* value);
static void SetVehicleDifferential(void* vehicle, const void* value);
static void SetVehicleGearbox(void* vehicle, const void* value);
From eca17c77997b191d847108a243b434d4124ef093 Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sun, 7 Jan 2024 10:35:00 -0400
Subject: [PATCH 33/79] Change vehicle drive mode to vehiclde drive control
---
Source/Engine/Physics/Actors/WheeledVehicle.cpp | 12 ------------
Source/Engine/Physics/Actors/WheeledVehicle.h | 16 +++++-----------
.../Engine/Physics/PhysX/PhysicsBackendPhysX.cpp | 2 +-
3 files changed, 6 insertions(+), 24 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 66a13fd7f..2f92ef3a8 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -33,16 +33,6 @@ void WheeledVehicle::SetDriveType(DriveTypes value)
Setup();
}
-void WheeledVehicle::SetDriveMode(DriveModes value)
-{
- _driveMode = value;
-}
-
-WheeledVehicle::DriveModes WheeledVehicle::GetDriveMode() const
-{
- return _driveMode;
-}
-
const Array &WheeledVehicle::GetWheels() const
{
return _wheels;
@@ -441,7 +431,6 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
SERIALIZE_GET_OTHER_OBJ(WheeledVehicle);
SERIALIZE_MEMBER(DriveType, _driveType);
- SERIALIZE_MEMBER(DriveModes, _driveMode);
SERIALIZE_MEMBER(Wheels, _wheels);
SERIALIZE_MEMBER(DriveControl, _driveControl);
SERIALIZE(UseReverseAsBrake);
@@ -457,7 +446,6 @@ void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *
RigidBody::Deserialize(stream, modifier);
DESERIALIZE_MEMBER(DriveType, _driveType);
- DESERIALIZE_MEMBER(DriveModes, _driveMode);
DESERIALIZE_MEMBER(Wheels, _wheels);
DESERIALIZE_MEMBER(DriveControl, _driveControl);
DESERIALIZE(UseReverseAsBrake);
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 2048a2f46..396f74543 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -130,6 +130,11 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
DECLARE_SCRIPTING_TYPE_MINIMAL(DriveControlSettings);
API_AUTO_SERIALIZATION();
+ ///
+ /// Gets or sets the drive mode, used by vehicles specify the way of the tracks control.
+ ///
+ API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Tanks\")") WheeledVehicle::DriveModes DriveMode;
+
///
/// Acceleration input sensitive.
///
@@ -441,7 +446,6 @@ private:
void* _vehicle = nullptr;
DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
- DriveModes _driveMode = DriveModes::Standard;
Array> _wheelsData;
float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake;
Array _wheels;
@@ -476,16 +480,6 @@ public:
///
API_PROPERTY() void SetDriveType(DriveTypes value);
- ///
- /// Used only for tanks, set the drive mode.
- ///
- API_PROPERTY() void SetDriveMode(DriveModes value);
-
- ///
- /// Gets the vehicle driving mode. Used only on tanks
- ///
- API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") DriveModes GetDriveMode() const;
-
///
/// Gets the vehicle wheels settings.
///
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 70ac6a2af..7fbcfc1be 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1397,7 +1397,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
float leftBrake = Math::Max(wheelVehicle->_tankLeftBrake, wheelVehicle->_handBrake);
float rightBrake = Math::Max(wheelVehicle->_tankRightBrake, wheelVehicle->_handBrake);
- WheeledVehicle::DriveModes vehicleDriveMode = wheelVehicle->_driveMode;
+ WheeledVehicle::DriveModes vehicleDriveMode = wheelVehicle->_driveControl.DriveMode;
if (isTank)
{
From 7f420c0131e244902bc21a228f0d9a379bf0ba52 Mon Sep 17 00:00:00 2001
From: "Mr. Capybara"
Date: Sun, 7 Jan 2024 10:46:21 -0400
Subject: [PATCH 34/79] add validation to vehicle drive
---
Source/Engine/Physics/Actors/WheeledVehicle.cpp | 10 ++++++++++
Source/Engine/Physics/Actors/WheeledVehicle.h | 16 ++++++++--------
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 2f92ef3a8..9891de208 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -45,6 +45,16 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
{
+ value.RiseRateAcceleration = Math::Max(value.RiseRateAcceleration, 0.01f);
+ value.RiseRateBrake = Math::Max(value.RiseRateBrake, 0.01f);
+ value.RiseRateHandBrake = Math::Max(value.RiseRateHandBrake, 0.01f);
+ value.RiseRateSteer = Math::Max(value.RiseRateSteer, 0.01f);
+
+ value.FallRateAcceleration = Math::Max(value.FallRateAcceleration, 0.01f);
+ value.FallRateBrake = Math::Max(value.FallRateBrake, 0.01f);
+ value.FallRateHandBrake = Math::Max(value.FallRateHandBrake, 0.01f);
+ value.FallRateSteer = Math::Max(value.FallRateSteer, 0.01f);
+
// Don't let have an invalid steer vs speed list.
if (value.SteerVsSpeed.Count() < 1)
value.SteerVsSpeed.Add(WheeledVehicle::SteerControl());
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 396f74543..7cf8310d0 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -138,42 +138,42 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// Acceleration input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(10)") float RiseRateAcceleration = 6.0f;
+ API_FIELD(Attributes="EditorOrder(10)") float RiseRateAcceleration = 6.0f;
///
/// Deceleration input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(11)") float FallRateAcceleration = 10.0f;
+ API_FIELD(Attributes="EditorOrder(11)") float FallRateAcceleration = 10.0f;
///
/// Brake input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(12)") float RiseRateBrake = 6.0f;
+ API_FIELD(Attributes="EditorOrder(12)") float RiseRateBrake = 6.0f;
///
/// Release brake sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(13)") float FallRateBrake = 10.0f;
+ API_FIELD(Attributes="EditorOrder(13)") float FallRateBrake = 10.0f;
///
/// Brake input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(14)") float RiseRateHandBrake = 12.0f;
+ API_FIELD(Attributes="EditorOrder(14)") float RiseRateHandBrake = 12.0f;
///
/// Release handbrake sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(15)") float FallRateHandBrake = 12.0f;
+ API_FIELD(Attributes="EditorOrder(15)") float FallRateHandBrake = 12.0f;
///
/// Steer input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(16)") float RiseRateSteer = 2.5f;
+ API_FIELD(Attributes="EditorOrder(16)") float RiseRateSteer = 2.5f;
///
/// Release steer input sensitive.
///
- API_FIELD(Attributes="Limit(0), EditorOrder(17)") float FallRateSteer = 5.0f;
+ API_FIELD(Attributes="EditorOrder(17)") float FallRateSteer = 5.0f;
///
/// Vehicle control relationship between speed and steer. The higher is the speed,
From 361cb914f3712e3a7ec94705b952d7a51e8bf553 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Wed, 10 Jan 2024 11:42:49 -0600
Subject: [PATCH 35/79] Keep local orientation on collider spawn. Add option to
keep orientation when resizing collider.
---
Source/Editor/SceneGraph/Actors/BoxColliderNode.cs | 8 ++++++--
Source/Engine/Physics/Colliders/BoxCollider.cpp | 5 +++--
Source/Engine/Physics/Colliders/BoxCollider.h | 2 +-
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs b/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
index 0f6670feb..cc3bcbe42 100644
--- a/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
+++ b/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
@@ -19,12 +19,16 @@ namespace FlaxEditor.SceneGraph.Actors
[CustomEditor(typeof(BoxCollider)), DefaultEditor]
public class BoxColliderEditor : ActorEditor
{
+ private bool _keepLocalOrientation = false;
///
public override void Initialize(LayoutElementsContainer layout)
{
base.Initialize(layout);
layout.Space(20f);
+ var checkbox = layout.Checkbox("Keep Local Orientation", "Keeps the local orientation when resizing.").CheckBox;
+ checkbox.Checked = _keepLocalOrientation;
+ checkbox.StateChanged += box => _keepLocalOrientation = box.Checked;
layout.Button("Resize to Fit", Editor.Instance.CodeDocs.GetTooltip(new ScriptMemberInfo(typeof(BoxCollider).GetMethod("AutoResize")))).Button.Clicked += OnResizeClicked;
}
@@ -33,7 +37,7 @@ namespace FlaxEditor.SceneGraph.Actors
foreach (var value in Values)
{
if (value is BoxCollider collider)
- collider.AutoResize();
+ collider.AutoResize(!_keepLocalOrientation);
}
}
}
@@ -76,7 +80,7 @@ namespace FlaxEditor.SceneGraph.Actors
return;
}
- ((BoxCollider)Actor).AutoResize();
+ ((BoxCollider)Actor).AutoResize(false);
}
}
}
diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp
index d74b3efba..d82b94d28 100644
--- a/Source/Engine/Physics/Colliders/BoxCollider.cpp
+++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp
@@ -20,7 +20,7 @@ void BoxCollider::SetSize(const Float3& value)
UpdateBounds();
}
-void BoxCollider::AutoResize()
+void BoxCollider::AutoResize(bool globalOrientation = true)
{
Actor* parent = GetParent();
if (Cast(parent))
@@ -43,7 +43,8 @@ void BoxCollider::AutoResize()
SetLocalPosition(Vector3::Zero);
SetSize(parentSize / parentScale);
SetCenter(parentCenter / parentScale);
- SetOrientation(GetOrientation() * Quaternion::Invert(GetOrientation()));
+ if (globalOrientation)
+ SetOrientation(GetOrientation() * Quaternion::Invert(GetOrientation()));
}
#if USE_EDITOR
diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h
index 3c15ce640..3c6759ee9 100644
--- a/Source/Engine/Physics/Colliders/BoxCollider.h
+++ b/Source/Engine/Physics/Colliders/BoxCollider.h
@@ -46,7 +46,7 @@ public:
///
/// Resizes the collider based on the bounds of it's parent to contain it whole (including any siblings).
///
- API_FUNCTION() void AutoResize();
+ API_FUNCTION() void AutoResize(bool globalOrientation);
public:
// [Collider]
From f1d6d71f6c5d15c2ff6b3ebbdae5f05f42e972f2 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Wed, 10 Jan 2024 13:53:22 -0600
Subject: [PATCH 36/79] Get unrotated bounded box to rotate.
---
Source/Engine/Physics/Colliders/BoxCollider.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp
index d82b94d28..a174b2c11 100644
--- a/Source/Engine/Physics/Colliders/BoxCollider.cpp
+++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp
@@ -30,7 +30,13 @@ void BoxCollider::AutoResize(bool globalOrientation = true)
const Vector3 parentScale = parent->GetScale();
if (parentScale.IsAnyZero())
return; // Avoid division by zero
+
+ // Hacky way to get unrotated bounded box of parent.
+ const Quaternion parentOrientation = parent->GetOrientation();
+ parent->SetOrientation(Quaternion::Identity);
BoundingBox parentBox = parent->GetBox();
+ parent->SetOrientation(parentOrientation);
+
for (const Actor* sibling : parent->Children)
{
if (sibling != this)
@@ -45,6 +51,8 @@ void BoxCollider::AutoResize(bool globalOrientation = true)
SetCenter(parentCenter / parentScale);
if (globalOrientation)
SetOrientation(GetOrientation() * Quaternion::Invert(GetOrientation()));
+ else
+ SetOrientation(parentOrientation);
}
#if USE_EDITOR
From cae9ddfa36ee3af1e579ee0968ae80ffdade7cc6 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Wed, 10 Jan 2024 13:56:38 -0600
Subject: [PATCH 37/79] Default to keep local orientation.
---
Source/Editor/SceneGraph/Actors/BoxColliderNode.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs b/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
index cc3bcbe42..64ab104c5 100644
--- a/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
+++ b/Source/Editor/SceneGraph/Actors/BoxColliderNode.cs
@@ -19,7 +19,8 @@ namespace FlaxEditor.SceneGraph.Actors
[CustomEditor(typeof(BoxCollider)), DefaultEditor]
public class BoxColliderEditor : ActorEditor
{
- private bool _keepLocalOrientation = false;
+ private bool _keepLocalOrientation = true;
+
///
public override void Initialize(LayoutElementsContainer layout)
{
From 2935b8ba10e23820ce28ff26fc64543dbfefb969 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 12 Jan 2024 19:12:48 -0600
Subject: [PATCH 38/79] Fix prefab transform on drag drop with parent. #1749
---
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 9cfe5b7bd..4b91e8940 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -650,7 +650,10 @@ namespace FlaxEditor.SceneGraph.GUI
}
}
actor.Name = item.ShortName;
- actor.Transform = spawnParent.Transform;
+ if (_dragAssets.Objects[i] is PrefabItem p)
+ actor.Transform = spawnParent.Transform + actor.Transform;
+ else
+ actor.Transform = spawnParent.Transform;
ActorNode.Root.Spawn(actor, spawnParent);
actor.OrderInParent = newOrder;
}
From 0eb4e0205e23a71021eaad8bc2dfc652988f7947 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 12 Jan 2024 19:43:58 -0600
Subject: [PATCH 39/79] Better fix
---
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 4b91e8940..09859f398 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -650,11 +650,11 @@ namespace FlaxEditor.SceneGraph.GUI
}
}
actor.Name = item.ShortName;
- if (_dragAssets.Objects[i] is PrefabItem p)
- actor.Transform = spawnParent.Transform + actor.Transform;
- else
- actor.Transform = spawnParent.Transform;
+ if (_dragAssets.Objects[i] is not PrefabItem p)
+ actor.Transform = Transform.Identity;
+ var previousTrans = actor.Transform;
ActorNode.Root.Spawn(actor, spawnParent);
+ actor.LocalTransform = previousTrans;
actor.OrderInParent = newOrder;
}
result = DragDropEffect.Move;
From e6389511fffd63ae3e56c39f0e27b0868e3b6061 Mon Sep 17 00:00:00 2001
From: ruan
Date: Sat, 13 Jan 2024 09:47:00 -0400
Subject: [PATCH 40/79] Fix tank inputs without initialized values
---
Source/Engine/Physics/Actors/WheeledVehicle.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 7cf8310d0..a0b67cc75 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -26,6 +26,7 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
DriveNW,
// Non-drivable vehicle.
NoDrive,
+ // Tank Drive. Can have more than 4 wheel. Not use steer, control acceleration for each tank track.
Tank,
};
///
@@ -447,7 +448,7 @@ private:
void* _vehicle = nullptr;
DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
Array> _wheelsData;
- float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle, _tankRightThrottle, _tankLeftBrake, _tankRightBrake;
+ float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle = 0.0f, _tankRightThrottle = 0.0f, _tankLeftBrake = 0.0f, _tankRightBrake = 0.0f;
Array _wheels;
Array _antiRollBars;
DriveControlSettings _driveControl;
From 7f957483519b78189c1e4a73e7146e3b1c5ce10f Mon Sep 17 00:00:00 2001
From: ruan
Date: Sat, 20 Jan 2024 19:44:08 -0400
Subject: [PATCH 41/79] Fix brake not working on tanks
---
Source/Engine/Physics/Actors/WheeledVehicle.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 9891de208..b3e714e51 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -194,7 +194,10 @@ void WheeledVehicle::SetSteering(float value)
void WheeledVehicle::SetBrake(float value)
{
- _brake = Math::Saturate(value);
+ value = Math::Saturate(value);
+ _brake = value;
+ _tankLeftBrake = value;
+ _tankRightBrake = value;
}
void WheeledVehicle::SetHandbrake(float value)
@@ -227,11 +230,11 @@ void WheeledVehicle::ClearInput()
_throttle = 0;
_steering = 0;
_brake = 0;
+ _handBrake = 0;
_tankLeftThrottle = 0;
_tankRightThrottle = 0;
_tankLeftBrake = 0;
_tankRightBrake = 0;
- _handBrake = 0;
}
float WheeledVehicle::GetForwardSpeed() const
@@ -423,10 +426,10 @@ void WheeledVehicle::OnDebugDrawSelected()
continue;
if (!_wheels[leftWheelIndex].Collider || !_wheels[rightWheelIndex].Collider)
continue;
-
+
DEBUG_DRAW_LINE(_wheels[leftWheelIndex].Collider->GetPosition(), _wheels[rightWheelIndex].Collider->GetPosition(), Color::Yellow, 0, false);
}
- // Center of mass
+ // Center of mass
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(_transform.LocalToWorld(_centerOfMassOffset), 10.0f), Color::Blue, 0, false);
RigidBody::OnDebugDrawSelected();
From 34583d7a55775a0da9a4fc9861ec1246e5bc6772 Mon Sep 17 00:00:00 2001
From: ruan
Date: Sun, 21 Jan 2024 09:00:46 -0400
Subject: [PATCH 42/79] Fix crash when disable vehicle
---
Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp | 4 ----
1 file changed, 4 deletions(-)
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 7fbcfc1be..e55965034 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -3588,7 +3588,6 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// Create vehicle drive
auto drive4W = PxVehicleDrive4W::allocate(wheels.Count());
drive4W->setup(PhysX, actorPhysX, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
- drive4W->setToRestState();
drive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
drive4W->mDriveDynData.setUseAutoGears(gearbox.AutoGear);
vehicle = drive4W;
@@ -3613,7 +3612,6 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// Create vehicle drive
auto driveNW = PxVehicleDriveNW::allocate(wheels.Count());
driveNW->setup(PhysX, actorPhysX, *wheelsSimData, driveSimData, wheels.Count());
- driveNW->setToRestState();
driveNW->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
driveNW->mDriveDynData.setUseAutoGears(gearbox.AutoGear);
vehicle = driveNW;
@@ -3624,7 +3622,6 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// Create vehicle drive
auto driveNo = PxVehicleNoDrive::allocate(wheels.Count());
driveNo->setup(PhysX, actorPhysX, *wheelsSimData);
- driveNo->setToRestState();
vehicle = driveNo;
break;
}
@@ -3648,7 +3645,6 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// Create vehicle drive
auto driveTank = PxVehicleDriveTank::allocate(wheels.Count());
driveTank->setup(PhysX, actorPhysX, *wheelsSimData, driveSimData, wheels.Count());
- driveTank->setToRestState();
driveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
driveTank->mDriveDynData.setUseAutoGears(gearbox.AutoGear);
vehicle = driveTank;
From e5160f288551d0cf8c3d0d0016edf7a7f035dad5 Mon Sep 17 00:00:00 2001
From: ruan
Date: Sun, 21 Jan 2024 10:42:55 -0400
Subject: [PATCH 43/79] Small fix
---
Source/Engine/Physics/Actors/WheeledVehicle.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index a0b67cc75..2bc42d6d7 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -134,7 +134,7 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// Gets or sets the drive mode, used by vehicles specify the way of the tracks control.
///
- API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Tanks\")") WheeledVehicle::DriveModes DriveMode;
+ API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Tanks\")") WheeledVehicle::DriveModes DriveMode = WheeledVehicle::DriveModes::Standard;
///
/// Acceleration input sensitive.
From 19ddcad16f20ba484d96d04a6cde54e0ff013cfb Mon Sep 17 00:00:00 2001
From: ruan
Date: Sun, 21 Jan 2024 11:03:29 -0400
Subject: [PATCH 44/79] Small clean code
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 52 +++++++++----------
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 3 --
2 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index b3e714e51..803b080c4 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -14,7 +14,7 @@
#include "Engine/Core/Log.h"
#endif
-WheeledVehicle::WheeledVehicle(const SpawnParams ¶ms)
+WheeledVehicle::WheeledVehicle(const SpawnParams& params)
: RigidBody(params)
{
_useCCD = 1;
@@ -33,7 +33,7 @@ void WheeledVehicle::SetDriveType(DriveTypes value)
Setup();
}
-const Array &WheeledVehicle::GetWheels() const
+const Array& WheeledVehicle::GetWheels() const
{
return _wheels;
}
@@ -43,7 +43,7 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
return _driveControl;
}
-void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
+void WheeledVehicle::SetDriveControl(DriveControlSettings& value)
{
value.RiseRateAcceleration = Math::Max(value.RiseRateAcceleration, 0.01f);
value.RiseRateBrake = Math::Max(value.RiseRateBrake, 0.01f);
@@ -69,15 +69,15 @@ void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
// Apply only on changed value
if (_driveControl.SteerVsSpeed[i].Speed != value.SteerVsSpeed[i].Speed || _driveControl.SteerVsSpeed[i].Steer != value.SteerVsSpeed[i].Steer)
{
- WheeledVehicle::SteerControl &steerVsSpeed = value.SteerVsSpeed[i];
+ WheeledVehicle::SteerControl& steerVsSpeed = value.SteerVsSpeed[i];
steerVsSpeed.Steer = Math::Saturate(steerVsSpeed.Steer);
steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, 10.0f);
// Clamp speeds to have an ordened list.
if (i >= 1)
{
- WheeledVehicle::SteerControl &lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
- WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
+ WheeledVehicle::SteerControl& lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
+ WheeledVehicle::SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
float minSpeed = lastSteerVsSpeed.Speed;
float maxSpeed = nextSteerVsSpeed.Speed;
@@ -88,7 +88,7 @@ void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
}
else if (steerVsSpeedCount > 1)
{
- WheeledVehicle::SteerControl &nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
+ WheeledVehicle::SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
steerVsSpeed.Speed = Math::Min(steerVsSpeed.Speed, nextSteerVsSpeed.Speed);
}
}
@@ -97,7 +97,7 @@ void WheeledVehicle::SetDriveControl(DriveControlSettings &value)
_driveControl = value;
}
-void WheeledVehicle::SetWheels(const Array &value)
+void WheeledVehicle::SetWheels(const Array& value)
{
#if WITH_VEHICLE
// Don't recreate whole vehicle when some wheel properties are only changed (eg. suspension)
@@ -106,8 +106,8 @@ void WheeledVehicle::SetWheels(const Array &value)
bool softUpdate = true;
for (int32 wheelIndex = 0; wheelIndex < value.Count(); wheelIndex++)
{
- auto &oldWheel = _wheels.Get()[wheelIndex];
- auto &newWheel = value.Get()[wheelIndex];
+ auto& oldWheel = _wheels.Get()[wheelIndex];
+ auto& newWheel = value.Get()[wheelIndex];
if (Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) || oldWheel.Collider != newWheel.Collider)
{
softUpdate = false;
@@ -131,7 +131,7 @@ WheeledVehicle::EngineSettings WheeledVehicle::GetEngine() const
return _engine;
}
-void WheeledVehicle::SetEngine(const EngineSettings &value)
+void WheeledVehicle::SetEngine(const EngineSettings& value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -145,7 +145,7 @@ WheeledVehicle::DifferentialSettings WheeledVehicle::GetDifferential() const
return _differential;
}
-void WheeledVehicle::SetDifferential(const DifferentialSettings &value)
+void WheeledVehicle::SetDifferential(const DifferentialSettings& value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -159,7 +159,7 @@ WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const
return _gearbox;
}
-void WheeledVehicle::SetGearbox(const GearboxSettings &value)
+void WheeledVehicle::SetGearbox(const GearboxSettings& value)
{
#if WITH_VEHICLE
if (_vehicle)
@@ -168,7 +168,7 @@ void WheeledVehicle::SetGearbox(const GearboxSettings &value)
_gearbox = value;
}
-void WheeledVehicle::SetAntiRollBars(const Array &value)
+void WheeledVehicle::SetAntiRollBars(const Array& value)
{
_antiRollBars = value;
#if WITH_VEHICLE
@@ -177,7 +177,7 @@ void WheeledVehicle::SetAntiRollBars(const Array &value)
#endif
}
-const Array &WheeledVehicle::GetAntiRollBars() const
+const Array& WheeledVehicle::GetAntiRollBars() const
{
return _antiRollBars;
}
@@ -298,12 +298,12 @@ void WheeledVehicle::SetTargetGear(int32 value)
#endif
}
-void WheeledVehicle::GetWheelState(int32 index, WheelState &result)
+void WheeledVehicle::GetWheelState(int32 index, WheelState& result)
{
if (index >= 0 && index < _wheels.Count())
{
const auto collider = _wheels[index].Collider.Get();
- for (auto &wheelData : _wheelsData)
+ for (auto& wheelData : _wheelsData)
{
if (wheelData.Collider == collider)
{
@@ -344,10 +344,10 @@ void WheeledVehicle::Setup()
#if USE_EDITOR
-void WheeledVehicle::DrawPhysicsDebug(RenderView &view)
+void WheeledVehicle::DrawPhysicsDebug(RenderView& view)
{
// Wheels shapes
- for (const auto &data : _wheelsData)
+ for (const auto& data : _wheelsData)
{
int32 wheelIndex = 0;
for (; wheelIndex < _wheels.Count(); wheelIndex++)
@@ -357,7 +357,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView &view)
}
if (wheelIndex == _wheels.Count())
break;
- const auto &wheel = _wheels[wheelIndex];
+ const auto& wheel = _wheels[wheelIndex];
if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
{
const Vector3 currentPos = wheel.Collider->GetPosition();
@@ -378,7 +378,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView &view)
void WheeledVehicle::OnDebugDrawSelected()
{
// Wheels shapes
- for (const auto &data : _wheelsData)
+ for (const auto& data : _wheelsData)
{
int32 wheelIndex = 0;
for (; wheelIndex < _wheels.Count(); wheelIndex++)
@@ -388,7 +388,7 @@ void WheeledVehicle::OnDebugDrawSelected()
}
if (wheelIndex == _wheels.Count())
break;
- const auto &wheel = _wheels[wheelIndex];
+ const auto& wheel = _wheels[wheelIndex];
if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
{
const Vector3 currentPos = wheel.Collider->GetPosition();
@@ -437,7 +437,7 @@ void WheeledVehicle::OnDebugDrawSelected()
#endif
-void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
+void WheeledVehicle::Serialize(SerializeStream& stream, const void *otherObj)
{
RigidBody::Serialize(stream, otherObj);
@@ -454,7 +454,7 @@ void WheeledVehicle::Serialize(SerializeStream &stream, const void *otherObj)
SERIALIZE_MEMBER(AntiRollBars, _antiRollBars);
}
-void WheeledVehicle::Deserialize(DeserializeStream &stream, ISerializeModifier *modifier)
+void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier *modifier)
{
RigidBody::Deserialize(stream, modifier);
@@ -550,14 +550,14 @@ void WheeledVehicle::BeginPlay(SceneBeginData *data)
#endif
#if USE_EDITOR
- GetSceneRendering()->AddPhysicsDebug(this);
+ GetSceneRendering()->AddPhysicsDebug(this);
#endif
}
void WheeledVehicle::EndPlay()
{
#if USE_EDITOR
- GetSceneRendering()->RemovePhysicsDebug(this);
+ GetSceneRendering()->RemovePhysicsDebug(this);
#endif
#if WITH_VEHICLE
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index b9d0387d8..c5ebd0620 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -59,9 +59,6 @@
#if WITH_PVD
#include
#endif
-#if USE_EDITOR
-#include "Editor/Editor.h"
-#endif
// Temporary memory size used by the PhysX during the simulation. Must be multiply of 4kB and 16bit aligned.
#define PHYSX_SCRATCH_BLOCK_SIZE (1024 * 128)
From 04da732da9088353571492a71cc45dec7619f5e7 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 19 Feb 2024 23:04:59 +0100
Subject: [PATCH 45/79] Cleanup code #1795 and unify new api in vector types
---
Source/Engine/Core/Math/Double2.cs | 13 ++++++++++++
Source/Engine/Core/Math/Double3.cs | 14 +++++++++++++
Source/Engine/Core/Math/Float2.cs | 30 ++++++++-------------------
Source/Engine/Core/Math/Float3.cs | 14 +++++++++++++
Source/Engine/Core/Math/Vector2.cs | 13 ++++++++++++
Source/Engine/Core/Math/Vector3.cs | 33 ++++++++----------------------
6 files changed, 71 insertions(+), 46 deletions(-)
diff --git a/Source/Engine/Core/Math/Double2.cs b/Source/Engine/Core/Math/Double2.cs
index 02669a869..9211d2a7b 100644
--- a/Source/Engine/Core/Math/Double2.cs
+++ b/Source/Engine/Core/Math/Double2.cs
@@ -1255,6 +1255,19 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// Snaps the input position into the grid.
+ ///
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Double2 SnapToGrid(Double2 pos, Double2 gridSize)
+ {
+ pos.X = Mathd.Ceil((pos.X - (gridSize.X * 0.5)) / gridSize.Y) * gridSize.X;
+ pos.Y = Mathd.Ceil((pos.Y - (gridSize.Y * 0.5)) / gridSize.X) * gridSize.Y;
+ return pos;
+ }
+
///
/// Adds two vectors.
///
diff --git a/Source/Engine/Core/Math/Double3.cs b/Source/Engine/Core/Math/Double3.cs
index ca5eb9cbd..ccb30d699 100644
--- a/Source/Engine/Core/Math/Double3.cs
+++ b/Source/Engine/Core/Math/Double3.cs
@@ -1536,6 +1536,20 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// Snaps the input position into the grid.
+ ///
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Double3 SnapToGrid(Double3 pos, Double3 gridSize)
+ {
+ pos.X = Mathd.Ceil((pos.X - (gridSize.X * 0.5)) / gridSize.X) * gridSize.X;
+ pos.Y = Mathd.Ceil((pos.Y - (gridSize.Y * 0.5)) / gridSize.Y) * gridSize.Y;
+ pos.Z = Mathd.Ceil((pos.Z - (gridSize.Z * 0.5)) / gridSize.Z) * gridSize.Z;
+ return pos;
+ }
+
///
/// Adds two vectors.
///
diff --git a/Source/Engine/Core/Math/Float2.cs b/Source/Engine/Core/Math/Float2.cs
index 38fb7534a..ccf8384c8 100644
--- a/Source/Engine/Core/Math/Float2.cs
+++ b/Source/Engine/Core/Math/Float2.cs
@@ -1274,30 +1274,16 @@ namespace FlaxEngine
}
///
- /// funcion for grid snaping snap to absolute world grid
- ///
desined for snaping using a ray / draging object
+ /// Snaps the input position into the grid.
///
- ///
- ///
- /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Float2 SnapToGrid(Float2 translation, Float2 gridSize)
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Float2 SnapToGrid(Float2 pos, Float2 gridSize)
{
- translation.X = Mathf.Ceil((translation.X - (gridSize.X * 0.5f)) / gridSize.Y) * gridSize.X;
- translation.Y = Mathf.Ceil((translation.Y - (gridSize.Y * 0.5f)) / gridSize.X) * gridSize.Y;
- return translation;
- }
- ///
- /// funcion for grid snaping snap to absolute world grid
- ///
desined for snaping using a ray / draging object
- ///
- ///
- ///
- /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Float2 SnapToGrid(Float2 translation, float gridSize)
- {
- translation.X = Mathf.Ceil((translation.X - (gridSize * 0.5f)) / gridSize) * gridSize;
- translation.Y = Mathf.Ceil((translation.Y - (gridSize * 0.5f)) / gridSize) * gridSize;
- return translation;
+ pos.X = Mathf.Ceil((pos.X - (gridSize.X * 0.5f)) / gridSize.Y) * gridSize.X;
+ pos.Y = Mathf.Ceil((pos.Y - (gridSize.Y * 0.5f)) / gridSize.X) * gridSize.Y;
+ return pos;
}
///
diff --git a/Source/Engine/Core/Math/Float3.cs b/Source/Engine/Core/Math/Float3.cs
index 3ea95f0d7..9ee2bbea9 100644
--- a/Source/Engine/Core/Math/Float3.cs
+++ b/Source/Engine/Core/Math/Float3.cs
@@ -1520,6 +1520,20 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// Snaps the input position into the grid.
+ ///
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Float3 SnapToGrid(Float3 pos, Float3 gridSize)
+ {
+ pos.X = Mathf.Ceil((pos.X - (gridSize.X * 0.5f)) / gridSize.X) * gridSize.X;
+ pos.Y = Mathf.Ceil((pos.Y - (gridSize.Y * 0.5f)) / gridSize.Y) * gridSize.Y;
+ pos.Z = Mathf.Ceil((pos.Z - (gridSize.Z * 0.5f)) / gridSize.Z) * gridSize.Z;
+ return pos;
+ }
+
///
/// Adds two vectors.
///
diff --git a/Source/Engine/Core/Math/Vector2.cs b/Source/Engine/Core/Math/Vector2.cs
index 568c51764..f8e0b6c32 100644
--- a/Source/Engine/Core/Math/Vector2.cs
+++ b/Source/Engine/Core/Math/Vector2.cs
@@ -1381,6 +1381,19 @@ namespace FlaxEngine
return result;
}
+ ///
+ /// Snaps the input position into the grid.
+ ///
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Vector2 SnapToGrid(Vector2 pos, Vector2 gridSize)
+ {
+ pos.X = Mathr.Ceil((pos.X - (gridSize.X * 0.5f)) / gridSize.Y) * gridSize.X;
+ pos.Y = Mathr.Ceil((pos.Y - (gridSize.Y * 0.5f)) / gridSize.X) * gridSize.Y;
+ return pos;
+ }
+
///
/// Adds two vectors.
///
diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs
index ad1797644..554631849 100644
--- a/Source/Engine/Core/Math/Vector3.cs
+++ b/Source/Engine/Core/Math/Vector3.cs
@@ -1672,32 +1672,17 @@ namespace FlaxEngine
}
///
- /// funcion for grid snaping snap to absolute world grid
- ///
desined for snaping using a ray / draging object
+ /// Snaps the input position into the grid.
///
- ///
- ///
- /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Vector3 SnapToGrid(Vector3 translation, float gridSize)
+ /// The position to snap.
+ /// The size of the grid.
+ /// The position snapped to the grid.
+ public static Vector3 SnapToGrid(Vector3 pos, Vector3 gridSize)
{
- translation.X = Mathr.Ceil((translation.X - (gridSize * 0.5f)) / gridSize) * gridSize;
- translation.Y = Mathr.Ceil((translation.Y - (gridSize * 0.5f)) / gridSize) * gridSize;
- translation.Z = Mathr.Ceil((translation.Z - (gridSize * 0.5f)) / gridSize) * gridSize;
- return translation;
- }
- ///
- /// funcion for grid snaping snap to absolute world grid
- ///
desined for snaping using a ray / draging object
- ///
- ///
- ///
- /// out = Ceil(((A - (GridSize * 0.5f)) / GridSize) * GridSize
- public static Vector3 SnapToGrid(Vector3 translation, Float3 gridSize)
- {
- translation.X = Mathr.Ceil((translation.X - (gridSize.X * 0.5f)) / gridSize.X) * gridSize.X;
- translation.Y = Mathr.Ceil((translation.Y - (gridSize.Y * 0.5f)) / gridSize.Y) * gridSize.Y;
- translation.Z = Mathr.Ceil((translation.Z - (gridSize.Z * 0.5f)) / gridSize.Z) * gridSize.Z;
- return translation;
+ pos.X = Mathr.Ceil((pos.X - (gridSize.X * 0.5f)) / gridSize.X) * gridSize.X;
+ pos.Y = Mathr.Ceil((pos.Y - (gridSize.Y * 0.5f)) / gridSize.Y) * gridSize.Y;
+ pos.Z = Mathr.Ceil((pos.Z - (gridSize.Z * 0.5f)) / gridSize.Z) * gridSize.Z;
+ return pos;
}
///
From 9c9aabcae332af99ff4dac61b877562ffd338571 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 10:49:45 +0100
Subject: [PATCH 46/79] Minor tweaks to #2147
---
.../Engine/ContentImporters/ImportModel.cpp | 22 +++++++++----------
.../Tools/ModelTool/ModelTool.Assimp.cpp | 2 +-
Source/Engine/Tools/ModelTool/ModelTool.cpp | 8 ++-----
3 files changed, 13 insertions(+), 19 deletions(-)
diff --git a/Source/Engine/ContentImporters/ImportModel.cpp b/Source/Engine/ContentImporters/ImportModel.cpp
index cf66762ad..190b4ba41 100644
--- a/Source/Engine/ContentImporters/ImportModel.cpp
+++ b/Source/Engine/ContentImporters/ImportModel.cpp
@@ -269,7 +269,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
// Import all of the objects recursive but use current model data to skip loading file again
options.Cached = &cached;
- Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData& meshData)
+ Function splitImport = [&context, &autoImportOutput](Options& splitOptions, const StringView& objectName, String& outputPath, MeshData* meshData)
{
// Recursive importing of the split object
String postFix = objectName;
@@ -280,19 +280,19 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
outputPath = autoImportOutput / String(StringUtils::GetFileNameWithoutExtension(context.TargetAssetPath)) + TEXT(" ") + postFix + TEXT(".flax");
splitOptions.SubAssetFolder = TEXT(" "); // Use the same folder as asset as they all are imported to the subdir for the prefab (see SubAssetFolder usage above)
- if (splitOptions.Type == ModelTool::ModelType::Model)
+ if (splitOptions.Type == ModelTool::ModelType::Model && meshData)
{
- // These settings interfere with submesh reimporting.
+ // These settings interfere with submesh reimporting
splitOptions.CenterGeometry = false;
splitOptions.UseLocalOrigin = false;
- // This properly sets the transformation of the mesh during reimport.
+ // This properly sets the transformation of the mesh during reimport
auto* nodes = &splitOptions.Cached->Data->Nodes;
Vector3 scale = Vector3::One;
// TODO: Improve this hack.
- // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there.
- auto* currentNode = &(*nodes)[meshData.NodeIndex];
+ // This is the same hack as in ImportModel::CreatePrefab(), and it is documented further there
+ auto* currentNode = &(*nodes)[meshData->NodeIndex];
while (true)
{
if (currentNode->ParentIndex == -1)
@@ -303,7 +303,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
currentNode = &(*nodes)[currentNode->ParentIndex];
}
- splitOptions.Translation = meshData.OriginTranslation * scale * -1.0f;
+ splitOptions.Translation = meshData->OriginTranslation * scale * -1.0f;
}
return AssetsImportingManager::Import(context.InputPath, outputPath, &splitOptions);
@@ -321,7 +321,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
splitOptions.Type = ModelTool::ModelType::Model;
splitOptions.ObjectIndex = groupIndex;
- if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, *group.First()))
+ if (!splitImport(splitOptions, group.GetKey(), prefabObject.AssetPath, group.First()))
{
prefabObjects.Add(prefabObject);
}
@@ -332,9 +332,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
auto& animation = data->Animations[i];
splitOptions.Type = ModelTool::ModelType::Animation;
splitOptions.ObjectIndex = i;
-
- MeshData empty;
- splitImport(splitOptions, animation.Name, prefabObject.AssetPath, empty);
+ splitImport(splitOptions, animation.Name, prefabObject.AssetPath, nullptr);
}
}
else if (options.SplitObjects)
@@ -390,7 +388,7 @@ CreateAssetResult ImportModel::Import(CreateAssetContext& context)
auto& group = meshesByName[options.ObjectIndex];
if (&dataThis == data)
{
- // Use meshes only from the the grouping (others will be removed manually)
+ // Use meshes only from the grouping (others will be removed manually)
{
auto& lod = dataThis.LODs[0];
meshesToDelete.Add(lod.Meshes);
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
index 85e320ee6..8b47b21dd 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp
@@ -774,7 +774,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ModelData& data, Options& opt
// Setup import options
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, options.SmoothingNormalsAngle);
context.AssimpImporter.SetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE, options.SmoothingTangentsAngle);
- context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm?
+ context.AssimpImporter.SetPropertyFloat(AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 100.0f); // Convert to cm
//context.AssimpImporter.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, MAX_uint16);
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, false);
context.AssimpImporter.SetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, false);
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index a8cb0ecd8..74cbfbb52 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1320,7 +1320,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
!
#endif
}
- if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && !(options.Type == ModelType::Prefab))
+ if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry) && options.Type != ModelType::Prefab)
{
// Perform simple nodes mapping to single node (will transform meshes to model local space)
SkeletonMapping skeletonMapping(data.Nodes, nullptr);
@@ -1340,7 +1340,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
if (skeletonMapping.SourceToSource[mesh.NodeIndex] != mesh.NodeIndex)
{
// Transform vertices
- auto transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
+ const Matrix transformationMatrix = hierarchyUpdater.CombineMatricesFromNodeIndices(skeletonMapping.SourceToSource[mesh.NodeIndex], mesh.NodeIndex);
if (!transformationMatrix.IsIdentity())
mesh.TransformBuffer(transformationMatrix);
@@ -1360,7 +1360,6 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
{
auto& mesh = *data.LODs[lodIndex].Meshes[meshIndex];
auto& node = data.Nodes[mesh.NodeIndex];
-
auto currentNode = &data.Nodes[mesh.NodeIndex];
Vector3 scale = Vector3::One;
@@ -1369,11 +1368,8 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
{
scale *= currentNode->LocalTransform.Scale;
rotation *= currentNode->LocalTransform.Orientation;
-
if (currentNode->ParentIndex == -1)
- {
break;
- }
currentNode = &data.Nodes[currentNode->ParentIndex];
}
From 1cb88bdc63ae9447e1c72305f60cf3cf864b9a46 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 11:44:49 +0100
Subject: [PATCH 47/79] Fix crash when using invalid `GPUTextureDescription`
#2261
---
.../Engine/Graphics/Textures/GPUTexture.cpp | 20 ++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/Source/Engine/Graphics/Textures/GPUTexture.cpp b/Source/Engine/Graphics/Textures/GPUTexture.cpp
index 93642f00a..d400e034d 100644
--- a/Source/Engine/Graphics/Textures/GPUTexture.cpp
+++ b/Source/Engine/Graphics/Textures/GPUTexture.cpp
@@ -339,12 +339,6 @@ int32 GPUTexture::ComputeRowPitch(int32 mipLevel, int32 rowAlign) const
bool GPUTexture::Init(const GPUTextureDescription& desc)
{
- ASSERT(Math::IsInRange(desc.Width, 1, GPU_MAX_TEXTURE_SIZE)
- && Math::IsInRange(desc.Height, 1, GPU_MAX_TEXTURE_SIZE)
- && Math::IsInRange(desc.Depth, 1, GPU_MAX_TEXTURE_SIZE)
- && Math::IsInRange(desc.ArraySize, 1, GPU_MAX_TEXTURE_ARRAY_SIZE)
- && Math::IsInRange(desc.MipLevels, 1, GPU_MAX_TEXTURE_MIP_LEVELS));
-
// Validate description
const auto device = GPUDevice::Instance;
if (desc.Usage == GPUResourceUsage::Dynamic)
@@ -352,6 +346,11 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot create texture. Dynamic textures are not supported. Description: {0}", desc.ToString());
return true;
}
+ if (desc.MipLevels < 0 || desc.MipLevels > GPU_MAX_TEXTURE_MIP_LEVELS)
+ {
+ LOG(Warning, "Cannot create texture. Invalid amount of mip levels. Description: {0}", desc.ToString());
+ return true;
+ }
if (desc.IsDepthStencil())
{
if (desc.MipLevels > 1)
@@ -392,7 +391,8 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot create texture. Texture cannot have per slice views. Description: {0}", desc.ToString());
return true;
}
- if (desc.Width > device->Limits.MaximumTexture2DSize
+ if (desc.Width <= 0 || desc.Height <= 0 || desc.ArraySize <= 0
+ || desc.Width > device->Limits.MaximumTexture2DSize
|| desc.Height > device->Limits.MaximumTexture2DSize
|| desc.ArraySize > device->Limits.MaximumTexture2DArraySize)
{
@@ -429,7 +429,8 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot create texture. Volume texture cannot have per slice map views if is not a render target. Description: {0}", desc.ToString());
return true;
}
- if (desc.Width > device->Limits.MaximumTexture3DSize
+ if (desc.Width <= 0 || desc.Height <= 0 || desc.Depth <= 0
+ || desc.Width > device->Limits.MaximumTexture3DSize
|| desc.Height > device->Limits.MaximumTexture3DSize
|| desc.Depth > device->Limits.MaximumTexture3DSize)
{
@@ -446,7 +447,8 @@ bool GPUTexture::Init(const GPUTextureDescription& desc)
LOG(Warning, "Cannot create texture. Cube texture cannot have per slice views. Description: {0}", desc.ToString());
return true;
}
- if (desc.Width > device->Limits.MaximumTextureCubeSize
+ if (desc.Width <= 0 || desc.ArraySize <= 0
+ || desc.Width > device->Limits.MaximumTextureCubeSize
|| desc.Height > device->Limits.MaximumTextureCubeSize
|| desc.ArraySize * 6 > device->Limits.MaximumTexture2DArraySize
|| desc.Width != desc.Height)
From e255778c07649bf6f235fc736680c62cf77f15b0 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 12:59:00 +0100
Subject: [PATCH 48/79] Add profiler event to task wait method
---
Source/Engine/Threading/Task.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Source/Engine/Threading/Task.cpp b/Source/Engine/Threading/Task.cpp
index 84737a71b..77af6ffb6 100644
--- a/Source/Engine/Threading/Task.cpp
+++ b/Source/Engine/Threading/Task.cpp
@@ -7,6 +7,7 @@
#include "Engine/Core/Types/DateTime.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Core/Math/Math.h"
+#include "Engine/Profiler/ProfilerCPU.h"
void Task::Start()
{
@@ -37,6 +38,7 @@ void Task::Cancel()
bool Task::Wait(double timeoutMilliseconds) const
{
+ PROFILE_CPU();
double startTime = Platform::GetTimeSeconds() * 0.001;
// TODO: no active waiting! use a semaphore!
@@ -73,12 +75,9 @@ bool Task::Wait(double timeoutMilliseconds) const
Task* Task::ContinueWith(Task* task)
{
ASSERT(task != nullptr && task != this);
-
if (_continueWith)
return _continueWith->ContinueWith(task);
-
_continueWith = task;
-
return task;
}
From 8e6bd07322ec1d283c21b2e8969bbc0e10a26c33 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 13:12:23 +0100
Subject: [PATCH 49/79] Fix `Transform` diff serialization to properly handle
prefab changes to a single component of transform
#2085
---
Source/Engine/Serialization/JsonWriter.cpp | 26 ++++++++++++++-----
Source/Engine/Serialization/Serialization.cpp | 18 ++++++++++---
Source/Engine/Serialization/Serialization.h | 2 +-
3 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/Source/Engine/Serialization/JsonWriter.cpp b/Source/Engine/Serialization/JsonWriter.cpp
index 27ecb672b..af7bb63a0 100644
--- a/Source/Engine/Serialization/JsonWriter.cpp
+++ b/Source/Engine/Serialization/JsonWriter.cpp
@@ -343,18 +343,30 @@ void JsonWriter::Transform(const ::Transform& value)
void JsonWriter::Transform(const ::Transform& value, const ::Transform* other)
{
StartObject();
- if (!other || !Vector3::NearEqual(value.Translation, other->Translation))
+ if (other)
+ {
+ if (!Vector3::NearEqual(value.Translation, other->Translation))
+ {
+ JKEY("Translation");
+ Vector3(value.Translation);
+ }
+ if (!Quaternion::NearEqual(value.Orientation, other->Orientation))
+ {
+ JKEY("Orientation");
+ Quaternion(value.Orientation);
+ }
+ if (!Float3::NearEqual(value.Scale, other->Scale))
+ {
+ JKEY("Scale");
+ Float3(value.Scale);
+ }
+ }
+ else
{
JKEY("Translation");
Vector3(value.Translation);
- }
- if (!other || !Quaternion::NearEqual(value.Orientation, other->Orientation))
- {
JKEY("Orientation");
Quaternion(value.Orientation);
- }
- if (!other || !Float3::NearEqual(value.Scale, other->Scale))
- {
JKEY("Scale");
Float3(value.Scale);
}
diff --git a/Source/Engine/Serialization/Serialization.cpp b/Source/Engine/Serialization/Serialization.cpp
index ac8eb41a9..1f8020288 100644
--- a/Source/Engine/Serialization/Serialization.cpp
+++ b/Source/Engine/Serialization/Serialization.cpp
@@ -747,9 +747,21 @@ bool Serialization::ShouldSerialize(const Transform& v, const void* otherObj)
void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Transform& v, ISerializeModifier* modifier)
{
- DESERIALIZE_HELPER(stream, "Translation", v.Translation, Vector3::Zero);
- DESERIALIZE_HELPER(stream, "Scale", v.Scale, Vector3::One);
- DESERIALIZE_HELPER(stream, "Orientation", v.Orientation, Quaternion::Identity);
+ {
+ const auto m = SERIALIZE_FIND_MEMBER(stream, "Translation");
+ if (m != stream.MemberEnd())
+ Deserialize(m->value, v.Translation, modifier);
+ }
+ {
+ const auto m = SERIALIZE_FIND_MEMBER(stream, "Scale");
+ if (m != stream.MemberEnd())
+ Deserialize(m->value, v.Scale, modifier);
+ }
+ {
+ const auto m = SERIALIZE_FIND_MEMBER(stream, "Orientation");
+ if (m != stream.MemberEnd())
+ Deserialize(m->value, v.Orientation, modifier);
+ }
}
bool Serialization::ShouldSerialize(const Matrix& v, const void* otherObj)
diff --git a/Source/Engine/Serialization/Serialization.h b/Source/Engine/Serialization/Serialization.h
index ed1008922..f7e8a0fcb 100644
--- a/Source/Engine/Serialization/Serialization.h
+++ b/Source/Engine/Serialization/Serialization.h
@@ -393,7 +393,7 @@ namespace Serialization
FLAXENGINE_API bool ShouldSerialize(const Transform& v, const void* otherObj);
inline void Serialize(ISerializable::SerializeStream& stream, const Transform& v, const void* otherObj)
{
- stream.Transform(v);
+ stream.Transform(v, (const Transform*)otherObj);
}
FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, Transform& v, ISerializeModifier* modifier);
From 9e747eb98a65678311db4cf3e1097ddd200c5e7a Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 13:24:59 +0100
Subject: [PATCH 50/79] Fix version deserialization of `Revision` component
---
Source/Engine/Serialization/JsonWriter.cpp | 2 +-
Source/Engine/Serialization/Serialization.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Source/Engine/Serialization/JsonWriter.cpp b/Source/Engine/Serialization/JsonWriter.cpp
index af7bb63a0..507e40372 100644
--- a/Source/Engine/Serialization/JsonWriter.cpp
+++ b/Source/Engine/Serialization/JsonWriter.cpp
@@ -15,7 +15,7 @@ void JsonWriter::Blob(const void* data, int32 length)
{
::Array base64;
base64.Resize(Encryption::Base64EncodeLength(length));
- Encryption::Base64Encode((byte*)data, length, base64.Get());
+ Encryption::Base64Encode((const byte*)data, length, base64.Get());
String(base64.Get(), base64.Count());
}
diff --git a/Source/Engine/Serialization/Serialization.cpp b/Source/Engine/Serialization/Serialization.cpp
index 1f8020288..3627078be 100644
--- a/Source/Engine/Serialization/Serialization.cpp
+++ b/Source/Engine/Serialization/Serialization.cpp
@@ -479,7 +479,7 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Versio
const auto mBuild = SERIALIZE_FIND_MEMBER(stream, "Build");
if (mBuild != stream.MemberEnd())
{
- const auto mRevision = SERIALIZE_FIND_MEMBER(stream, "mRevision");
+ const auto mRevision = SERIALIZE_FIND_MEMBER(stream, "Revision");
if (mRevision != stream.MemberEnd())
v = Version(mMajor->value.GetInt(), mMinor->value.GetInt(), mBuild->value.GetInt(), mRevision->value.GetInt());
else
From 8fa8eeb09468f1ae577a30fa74c58d2dea81e865 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 17:51:48 +0100
Subject: [PATCH 51/79] Optimize `Matrix` decomposition to use `Matrix3x3` for
rotation
---
.../Viewport/Previews/AnimatedModelPreview.cs | 2 +-
Source/Engine/Core/Math/BoundingBox.cs | 2 +-
Source/Engine/Core/Math/Matrix.cpp | 16 ++++--
Source/Engine/Core/Math/Matrix.cs | 50 ++++++++++++++++---
Source/Engine/Core/Math/Matrix.h | 3 +-
Source/Engine/Core/Math/Matrix3x3.cs | 17 +++++++
Source/Engine/Core/Math/Transform.h | 9 ++--
7 files changed, 83 insertions(+), 16 deletions(-)
diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs
index d96d7a8f9..c8f37df15 100644
--- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs
+++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs
@@ -342,7 +342,7 @@ namespace FlaxEditor.Viewport.Previews
if (nodesMask != null && !nodesMask[nodeIndex])
continue;
var transform = pose[nodeIndex];
- transform.Decompose(out var scale, out Matrix _, out _);
+ transform.Decompose(out var scale, out Matrix3x3 _, out _);
transform = Matrix.Invert(Matrix.Scaling(scale)) * transform;
var box = localBox * transform;
DebugDraw.DrawWireBox(box, Color.Green, 0, false);
diff --git a/Source/Engine/Core/Math/BoundingBox.cs b/Source/Engine/Core/Math/BoundingBox.cs
index 51225d775..f2ae8d64b 100644
--- a/Source/Engine/Core/Math/BoundingBox.cs
+++ b/Source/Engine/Core/Math/BoundingBox.cs
@@ -171,7 +171,7 @@ namespace FlaxEngine
/// The ray to test.
/// When the method completes, contains the distance of the intersection, or 0 if there was no intersection.
/// Whether the two objects intersected.
- [Obsolete("Deprecated in 1.4")]
+ [Obsolete("Deprecated in v1.4")]
public bool Intersects(ref Ray ray, out float distance)
{
var result = CollisionsHelper.RayIntersectsBox(ref ray, ref this, out Real dst);
diff --git a/Source/Engine/Core/Math/Matrix.cpp b/Source/Engine/Core/Math/Matrix.cpp
index 058936d61..7269d4e68 100644
--- a/Source/Engine/Core/Math/Matrix.cpp
+++ b/Source/Engine/Core/Math/Matrix.cpp
@@ -101,7 +101,7 @@ void Matrix::Decompose(Float3& scale, Float3& translation) const
void Matrix::Decompose(Transform& transform) const
{
- Matrix rotationMatrix;
+ Matrix3x3 rotationMatrix;
Float3 translation;
Decompose(transform.Scale, rotationMatrix, translation);
transform.Translation = translation;
@@ -110,12 +110,12 @@ void Matrix::Decompose(Transform& transform) const
void Matrix::Decompose(Float3& scale, Quaternion& rotation, Float3& translation) const
{
- Matrix rotationMatrix;
+ Matrix3x3 rotationMatrix;
Decompose(scale, rotationMatrix, translation);
Quaternion::RotationMatrix(rotationMatrix, rotation);
}
-void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) const
+void Matrix::Decompose(Float3& scale, Matrix3x3& rotation, Float3& translation) const
{
// Get the translation
translation = Float3(M41, M42, M43);
@@ -127,7 +127,7 @@ void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) con
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;
+ rotation = Matrix3x3::Identity;
if (scale.IsAnyZero())
return;
@@ -145,6 +145,14 @@ void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) con
scale.Z = Float3::Dot(at, GetBackward()) > 0.0f ? scale.Z : -scale.Z;
}
+void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) const
+{
+ // [Deprecated on 20.02.2024, expires on 20.02.2026]
+ Matrix3x3 r;
+ Decompose(scale, r, translation);
+ rotation = Matrix(r);
+}
+
Matrix Matrix::Transpose(const Matrix& value)
{
Matrix result;
diff --git a/Source/Engine/Core/Math/Matrix.cs b/Source/Engine/Core/Math/Matrix.cs
index 6344b008a..4bee98574 100644
--- a/Source/Engine/Core/Math/Matrix.cs
+++ b/Source/Engine/Core/Math/Matrix.cs
@@ -330,6 +330,30 @@ namespace FlaxEngine
M44 = values[15];
}
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The rotation/scale matrix.
+ public Matrix(Matrix3x3 m)
+ {
+ M11 = m.M11;
+ M12 = m.M12;
+ M13 = m.M13;
+ M14 = 0;
+ M21 = m.M21;
+ M22 = m.M22;
+ M23 = m.M23;
+ M24 = 0;
+ M31 = m.M31;
+ M32 = m.M32;
+ M33 = m.M33;
+ M34 = 0;
+ M41 = 0;
+ M42 = 0;
+ M43 = 0;
+ M44 = 1;
+ }
+
///
/// Gets or sets the first row in the matrix; that is M11, M12, M13, and M14.
///
@@ -747,7 +771,7 @@ namespace FlaxEngine
/// This method is designed to decompose an SRT transformation matrix only.
public void Decompose(out Transform transform)
{
- Decompose(out transform.Scale, out Matrix rotationMatrix, out Float3 translation);
+ Decompose(out transform.Scale, out Matrix3x3 rotationMatrix, out Float3 translation);
Quaternion.RotationMatrix(ref rotationMatrix, out transform.Orientation);
transform.Translation = translation;
}
@@ -759,7 +783,7 @@ namespace FlaxEngine
/// When the method completes, contains the rotation component of the decomposed matrix.
/// When the method completes, contains the translation component of the decomposed matrix.
/// This method is designed to decompose an SRT transformation matrix only.
- public void Decompose(out Float3 scale, out Matrix rotation, out Float3 translation)
+ public void Decompose(out Float3 scale, out Matrix3x3 rotation, out Float3 translation)
{
// Get the translation
translation.X = M41;
@@ -774,12 +798,12 @@ namespace FlaxEngine
// If any of the scaling factors are zero, than the rotation matrix can not exist
if (Mathf.IsZero(scale.X) || Mathf.IsZero(scale.Y) || Mathf.IsZero(scale.Z))
{
- rotation = Identity;
+ rotation = Matrix3x3.Identity;
return;
}
// The rotation is the left over matrix after dividing out the scaling
- rotation = new Matrix
+ rotation = new Matrix3x3
{
M11 = M11 / scale.X,
M12 = M12 / scale.X,
@@ -790,10 +814,24 @@ namespace FlaxEngine
M31 = M31 / scale.Z,
M32 = M32 / scale.Z,
M33 = M33 / scale.Z,
- M44 = 1f
};
}
+ ///
+ /// Decomposes a matrix into a scale, rotation, and translation.
+ /// [Deprecated on 20.02.2024, expires on 20.02.2026]
+ ///
+ /// When the method completes, contains the scaling component of the decomposed matrix.
+ /// When the method completes, contains the rotation component of the decomposed matrix.
+ /// When the method completes, contains the translation component of the decomposed matrix.
+ /// This method is designed to decompose an SRT transformation matrix only.
+ [Obsolete("Deprecated in v1.8")]
+ public void Decompose(out Float3 scale, out Matrix rotation, out Float3 translation)
+ {
+ Decompose(out scale, out Matrix3x3 r, out translation);
+ rotation = new Matrix(r);
+ }
+
///
/// Decomposes a matrix into a scale, rotation, and translation.
///
@@ -803,7 +841,7 @@ namespace FlaxEngine
/// This method is designed to decompose an SRT transformation matrix only.
public void Decompose(out Float3 scale, out Quaternion rotation, out Float3 translation)
{
- Decompose(out scale, out Matrix rotationMatrix, out translation);
+ Decompose(out scale, out Matrix3x3 rotationMatrix, out translation);
Quaternion.RotationMatrix(ref rotationMatrix, out rotation);
}
diff --git a/Source/Engine/Core/Math/Matrix.h b/Source/Engine/Core/Math/Matrix.h
index aed2ead8d..11fbe1e78 100644
--- a/Source/Engine/Core/Math/Matrix.h
+++ b/Source/Engine/Core/Math/Matrix.h
@@ -480,7 +480,8 @@ public:
/// When the method completes, contains the rotation component of the decomposed matrix.
/// When the method completes, contains the translation component of the decomposed matrix.
/// This method is designed to decompose an SRT transformation matrix only.
- void Decompose(Float3& scale, Matrix& rotation, Float3& translation) const;
+ void Decompose(Float3& scale, Matrix3x3& rotation, Float3& translation) const;
+ DEPRECATED void Decompose(Float3& scale, Matrix& rotation, Float3& translation) const;
public:
Matrix operator*(const float scale) const
diff --git a/Source/Engine/Core/Math/Matrix3x3.cs b/Source/Engine/Core/Math/Matrix3x3.cs
index 44af4542b..33e69d6e1 100644
--- a/Source/Engine/Core/Math/Matrix3x3.cs
+++ b/Source/Engine/Core/Math/Matrix3x3.cs
@@ -185,6 +185,23 @@ namespace FlaxEngine
M33 = values[8];
}
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The rotation/scale matrix.
+ public Matrix3x3(Matrix m)
+ {
+ M11 = m.M11;
+ M12 = m.M12;
+ M13 = m.M13;
+ M21 = m.M21;
+ M22 = m.M22;
+ M23 = m.M23;
+ M31 = m.M31;
+ M32 = m.M32;
+ M33 = m.M33;
+ }
+
///
/// Gets or sets the first row in the Matrix3x3; that is M11, M12, M13
///
diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h
index 1079b4c23..f61ce8b9c 100644
--- a/Source/Engine/Core/Math/Transform.h
+++ b/Source/Engine/Core/Math/Transform.h
@@ -18,17 +18,20 @@ API_STRUCT() struct FLAXENGINE_API Transform
///
/// The translation vector of the transform.
///
- API_FIELD(Attributes="EditorOrder(10), EditorDisplay(null, \"Position\")") Vector3 Translation;
+ API_FIELD(Attributes="EditorOrder(10), EditorDisplay(null, \"Position\")")
+ Vector3 Translation;
///
/// The rotation of the transform.
///
- API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Rotation\")") Quaternion Orientation;
+ API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Rotation\")")
+ Quaternion Orientation;
///
/// The scale vector of the transform.
///
- API_FIELD(Attributes="EditorOrder(30), Limit(float.MinValue, float.MaxValue, 0.01f)") Float3 Scale;
+ API_FIELD(Attributes="EditorOrder(30), Limit(float.MinValue, float.MaxValue, 0.01f)")
+ Float3 Scale;
public:
///
From e5cfd872b2fc5c9a3935ac9a7ef46cd9f0550452 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 17:52:51 +0100
Subject: [PATCH 52/79] Simplify math codebase
---
Source/Engine/Core/Math/Matrix.cpp | 186 +++++++++++++++++++++++++-
Source/Engine/Core/Math/Matrix.h | 182 ++-----------------------
Source/Engine/Core/Math/Matrix3x3.cpp | 5 +
Source/Engine/Core/Math/Matrix3x3.h | 7 +-
Source/Engine/Core/Math/Transform.cpp | 19 +++
Source/Engine/Core/Math/Transform.h | 29 ++--
Source/Engine/Level/Actor.cpp | 19 +--
7 files changed, 245 insertions(+), 202 deletions(-)
diff --git a/Source/Engine/Core/Math/Matrix.cpp b/Source/Engine/Core/Math/Matrix.cpp
index 7269d4e68..db255e627 100644
--- a/Source/Engine/Core/Math/Matrix.cpp
+++ b/Source/Engine/Core/Math/Matrix.cpp
@@ -40,9 +40,7 @@ float Matrix::GetDeterminant() const
const float temp4 = M31 * M44 - M34 * M41;
const float temp5 = M31 * M43 - M33 * M41;
const float temp6 = M31 * M42 - M32 * M41;
- return M11 * (M22 * temp1 - M23 * temp2 + M24 * temp3) - M12 * (M21 * temp1 -
- M23 * temp4 + M24 * temp5) + M13 * (M21 * temp2 - M22 * temp4 + M24 * temp6) -
- M14 * (M21 * temp3 - M22 * temp5 + M23 * temp6);
+ return M11 * (M22 * temp1 - M23 * temp2 + M24 * temp3) - M12 * (M21 * temp1 -M23 * temp4 + M24 * temp5) + M13 * (M21 * temp2 - M22 * temp4 + M24 * temp6) - M14 * (M21 * temp3 - M22 * temp5 + M23 * temp6);
}
float Matrix::RotDeterminant() const
@@ -153,6 +151,179 @@ void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) con
rotation = Matrix(r);
}
+bool Matrix::operator==(const Matrix& other) const
+{
+ for (int32 i = 0; i < 16; i++)
+ {
+ if (Math::NotNearEqual(other.Raw[i], Raw[i]))
+ return false;
+ }
+ return true;
+}
+
+void Matrix::Add(const Matrix& left, const Matrix& right, Matrix& result)
+{
+ result.M11 = left.M11 + right.M11;
+ result.M12 = left.M12 + right.M12;
+ result.M13 = left.M13 + right.M13;
+ result.M14 = left.M14 + right.M14;
+ result.M21 = left.M21 + right.M21;
+ result.M22 = left.M22 + right.M22;
+ result.M23 = left.M23 + right.M23;
+ result.M24 = left.M24 + right.M24;
+ result.M31 = left.M31 + right.M31;
+ result.M32 = left.M32 + right.M32;
+ result.M33 = left.M33 + right.M33;
+ result.M34 = left.M34 + right.M34;
+ result.M41 = left.M41 + right.M41;
+ result.M42 = left.M42 + right.M42;
+ result.M43 = left.M43 + right.M43;
+ result.M44 = left.M44 + right.M44;
+}
+
+void Matrix::Subtract(const Matrix& left, const Matrix& right, Matrix& result)
+{
+ result.M11 = left.M11 - right.M11;
+ result.M12 = left.M12 - right.M12;
+ result.M13 = left.M13 - right.M13;
+ result.M14 = left.M14 - right.M14;
+ result.M21 = left.M21 - right.M21;
+ result.M22 = left.M22 - right.M22;
+ result.M23 = left.M23 - right.M23;
+ result.M24 = left.M24 - right.M24;
+ result.M31 = left.M31 - right.M31;
+ result.M32 = left.M32 - right.M32;
+ result.M33 = left.M33 - right.M33;
+ result.M34 = left.M34 - right.M34;
+ result.M41 = left.M41 - right.M41;
+ result.M42 = left.M42 - right.M42;
+ result.M43 = left.M43 - right.M43;
+ result.M44 = left.M44 - right.M44;
+}
+
+void Matrix::Multiply(const Matrix& left, float right, Matrix& result)
+{
+ result.M11 = left.M11 * right;
+ result.M12 = left.M12 * right;
+ result.M13 = left.M13 * right;
+ result.M14 = left.M14 * right;
+ result.M21 = left.M21 * right;
+ result.M22 = left.M22 * right;
+ result.M23 = left.M23 * right;
+ result.M24 = left.M24 * right;
+ result.M31 = left.M31 * right;
+ result.M32 = left.M32 * right;
+ result.M33 = left.M33 * right;
+ result.M34 = left.M34 * right;
+ result.M41 = left.M41 * right;
+ result.M42 = left.M42 * right;
+ result.M43 = left.M43 * right;
+ result.M44 = left.M44 * right;
+}
+
+void Matrix::Multiply(const Matrix& left, const Matrix& right, Matrix& 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 Matrix::Divide(const Matrix& left, float right, Matrix& result)
+{
+ ASSERT(!Math::IsZero(right));
+ const float inv = 1.0f / right;
+
+ result.M11 = left.M11 * inv;
+ result.M12 = left.M12 * inv;
+ result.M13 = left.M13 * inv;
+ result.M14 = left.M14 * inv;
+ result.M21 = left.M21 * inv;
+ result.M22 = left.M22 * inv;
+ result.M23 = left.M23 * inv;
+ result.M24 = left.M24 * inv;
+ result.M31 = left.M31 * inv;
+ result.M32 = left.M32 * inv;
+ result.M33 = left.M33 * inv;
+ result.M34 = left.M34 * inv;
+ result.M41 = left.M41 * inv;
+ result.M42 = left.M42 * inv;
+ result.M43 = left.M43 * inv;
+ result.M44 = left.M44 * inv;
+}
+
+void Matrix::Divide(const Matrix& left, const Matrix& right, Matrix& result)
+{
+ result.M11 = left.M11 / right.M11;
+ result.M12 = left.M12 / right.M12;
+ result.M13 = left.M13 / right.M13;
+ result.M14 = left.M14 / right.M14;
+ result.M21 = left.M21 / right.M21;
+ result.M22 = left.M22 / right.M22;
+ result.M23 = left.M23 / right.M23;
+ result.M24 = left.M24 / right.M24;
+ result.M31 = left.M31 / right.M31;
+ result.M32 = left.M32 / right.M32;
+ result.M33 = left.M33 / right.M33;
+ result.M34 = left.M34 / right.M34;
+ result.M41 = left.M41 / right.M41;
+ result.M42 = left.M42 / right.M42;
+ result.M43 = left.M43 / right.M43;
+ result.M44 = left.M44 / right.M44;
+}
+
+void Matrix::Negate(const Matrix& value, Matrix& result)
+{
+ result.M11 = -value.M11;
+ result.M12 = -value.M12;
+ result.M13 = -value.M13;
+ result.M14 = -value.M14;
+ result.M21 = -value.M21;
+ result.M22 = -value.M22;
+ result.M23 = -value.M23;
+ result.M24 = -value.M24;
+ result.M31 = -value.M31;
+ result.M32 = -value.M32;
+ result.M33 = -value.M33;
+ result.M34 = -value.M34;
+ result.M41 = -value.M41;
+ result.M42 = -value.M42;
+ result.M43 = -value.M43;
+ result.M44 = -value.M44;
+}
+
+void Matrix::Lerp(const Matrix& start, const Matrix& end, float amount, Matrix& result)
+{
+ result.M11 = Math::Lerp(start.M11, end.M11, amount);
+ result.M12 = Math::Lerp(start.M12, end.M12, amount);
+ result.M13 = Math::Lerp(start.M13, end.M13, amount);
+ result.M14 = Math::Lerp(start.M14, end.M14, amount);
+ result.M21 = Math::Lerp(start.M21, end.M21, amount);
+ result.M22 = Math::Lerp(start.M22, end.M22, amount);
+ result.M23 = Math::Lerp(start.M23, end.M23, amount);
+ result.M24 = Math::Lerp(start.M24, end.M24, amount);
+ result.M31 = Math::Lerp(start.M31, end.M31, amount);
+ result.M32 = Math::Lerp(start.M32, end.M32, amount);
+ result.M33 = Math::Lerp(start.M33, end.M33, amount);
+ result.M34 = Math::Lerp(start.M34, end.M34, amount);
+ result.M41 = Math::Lerp(start.M41, end.M41, amount);
+ result.M42 = Math::Lerp(start.M42, end.M42, amount);
+ result.M43 = Math::Lerp(start.M43, end.M43, amount);
+ result.M44 = Math::Lerp(start.M44, end.M44, amount);
+}
+
Matrix Matrix::Transpose(const Matrix& value)
{
Matrix result;
@@ -688,6 +859,15 @@ void Matrix::CreateFromAxisAngle(const Float3& axis, float angle, Matrix& result
result.M44 = 1.0f;
}
+Vector3 Matrix::TransformVector(const Matrix& m, const Vector3& v)
+{
+ return Vector3(
+ m.Values[0][0] * v.Raw[0] + m.Values[1][0] * v.Raw[1] + m.Values[2][0] * v.Raw[2],
+ m.Values[0][1] * v.Raw[0] + m.Values[1][1] * v.Raw[1] + m.Values[2][1] * v.Raw[2],
+ m.Values[0][2] * v.Raw[0] + m.Values[1][2] * v.Raw[1] + m.Values[2][2] * v.Raw[2]
+ );
+}
+
Float4 Matrix::TransformPosition(const Matrix& m, const Float3& v)
{
return Float4(
diff --git a/Source/Engine/Core/Math/Matrix.h b/Source/Engine/Core/Math/Matrix.h
index 11fbe1e78..906000592 100644
--- a/Source/Engine/Core/Math/Matrix.h
+++ b/Source/Engine/Core/Math/Matrix.h
@@ -523,24 +523,10 @@ public:
return *this;
}
- bool operator==(const Matrix& other) const
- {
- for (int32 i = 0; i < 16; i++)
- {
- if (Math::NotNearEqual(other.Raw[i], Raw[i]))
- return false;
- }
- return true;
- }
-
+ bool operator==(const Matrix& other) const;
bool operator!=(const Matrix& other) const
{
- for (int32 i = 0; i < 16; i++)
- {
- if (Math::NotNearEqual(other.Raw[i], Raw[i]))
- return true;
- }
- return false;
+ return !operator==(other);
}
public:
@@ -548,73 +534,19 @@ public:
// @param left The first matrix to add.
// @param right The second matrix to add.
// @param result When the method completes, contains the sum of the two matrices.
- static void Add(const Matrix& left, const Matrix& right, Matrix& result)
- {
- result.M11 = left.M11 + right.M11;
- result.M12 = left.M12 + right.M12;
- result.M13 = left.M13 + right.M13;
- result.M14 = left.M14 + right.M14;
- result.M21 = left.M21 + right.M21;
- result.M22 = left.M22 + right.M22;
- result.M23 = left.M23 + right.M23;
- result.M24 = left.M24 + right.M24;
- result.M31 = left.M31 + right.M31;
- result.M32 = left.M32 + right.M32;
- result.M33 = left.M33 + right.M33;
- result.M34 = left.M34 + right.M34;
- result.M41 = left.M41 + right.M41;
- result.M42 = left.M42 + right.M42;
- result.M43 = left.M43 + right.M43;
- result.M44 = left.M44 + right.M44;
- }
+ static void Add(const Matrix& left, const Matrix& right, Matrix& result);
// Calculates the difference between two matrices.
// @param left The first matrix to subtract.
// @param right The second matrix to subtract.
// @param result When the method completes, contains the difference between the two matrices.
- static void Subtract(const Matrix& left, const Matrix& right, Matrix& result)
- {
- result.M11 = left.M11 - right.M11;
- result.M12 = left.M12 - right.M12;
- result.M13 = left.M13 - right.M13;
- result.M14 = left.M14 - right.M14;
- result.M21 = left.M21 - right.M21;
- result.M22 = left.M22 - right.M22;
- result.M23 = left.M23 - right.M23;
- result.M24 = left.M24 - right.M24;
- result.M31 = left.M31 - right.M31;
- result.M32 = left.M32 - right.M32;
- result.M33 = left.M33 - right.M33;
- result.M34 = left.M34 - right.M34;
- result.M41 = left.M41 - right.M41;
- result.M42 = left.M42 - right.M42;
- result.M43 = left.M43 - right.M43;
- result.M44 = left.M44 - right.M44;
- }
+ static void Subtract(const Matrix& left, const Matrix& right, Matrix& result);
// Scales a matrix by the given value.
// @param left The matrix to scale.
// @param right The amount by which to scale.
// @param result When the method completes, contains the scaled matrix.
- static void Multiply(const Matrix& left, float right, Matrix& result)
- {
- result.M11 = left.M11 * right;
- result.M12 = left.M12 * right;
- result.M13 = left.M13 * right;
- result.M14 = left.M14 * right;
- result.M21 = left.M21 * right;
- result.M22 = left.M22 * right;
- result.M23 = left.M23 * right;
- result.M24 = left.M24 * right;
- result.M31 = left.M31 * right;
- result.M32 = left.M32 * right;
- result.M33 = left.M33 * right;
- result.M34 = left.M34 * right;
- result.M41 = left.M41 * right;
- result.M42 = left.M42 * right;
- result.M43 = left.M43 * right;
- result.M44 = left.M44 * right;
- }
+ static void Multiply(const Matrix& left, float right, Matrix& result);
// Calculates the product of two matrices.
// @param left The first matrix to multiply.
@@ -631,124 +563,31 @@ public:
// @param left The first matrix to multiply.
// @param right The second matrix to multiply.
// @param result The product of the two matrices.
- static void Multiply(const Matrix& left, const Matrix& right, Matrix& 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;
- }
+ static void Multiply(const Matrix& left, const Matrix& right, Matrix& result);
// Scales a matrix by the given value.
// @param left The matrix to scale.
// @param right The amount by which to scale.
// @param result When the method completes, contains the scaled matrix.
- static void Divide(const Matrix& left, float right, Matrix& result)
- {
- ASSERT(!Math::IsZero(right));
- const float inv = 1.0f / right;
-
- result.M11 = left.M11 * inv;
- result.M12 = left.M12 * inv;
- result.M13 = left.M13 * inv;
- result.M14 = left.M14 * inv;
- result.M21 = left.M21 * inv;
- result.M22 = left.M22 * inv;
- result.M23 = left.M23 * inv;
- result.M24 = left.M24 * inv;
- result.M31 = left.M31 * inv;
- result.M32 = left.M32 * inv;
- result.M33 = left.M33 * inv;
- result.M34 = left.M34 * inv;
- result.M41 = left.M41 * inv;
- result.M42 = left.M42 * inv;
- result.M43 = left.M43 * inv;
- result.M44 = left.M44 * inv;
- }
+ static void Divide(const Matrix& left, float right, Matrix& result);
// Calculates the quotient of two matrices.
// @param left The first matrix to divide.
// @param right The second matrix to divide.
// @param result When the method completes, contains the quotient of the two matrices.
- static void Divide(const Matrix& left, const Matrix& right, Matrix& result)
- {
- result.M11 = left.M11 / right.M11;
- result.M12 = left.M12 / right.M12;
- result.M13 = left.M13 / right.M13;
- result.M14 = left.M14 / right.M14;
- result.M21 = left.M21 / right.M21;
- result.M22 = left.M22 / right.M22;
- result.M23 = left.M23 / right.M23;
- result.M24 = left.M24 / right.M24;
- result.M31 = left.M31 / right.M31;
- result.M32 = left.M32 / right.M32;
- result.M33 = left.M33 / right.M33;
- result.M34 = left.M34 / right.M34;
- result.M41 = left.M41 / right.M41;
- result.M42 = left.M42 / right.M42;
- result.M43 = left.M43 / right.M43;
- result.M44 = left.M44 / right.M44;
- }
+ static void Divide(const Matrix& left, const Matrix& right, Matrix& result);
// Negates a matrix.
// @param value The matrix to be negated.
// @param result When the method completes, contains the negated matrix.
- static void Negate(const Matrix& value, Matrix& result)
- {
- result.M11 = -value.M11;
- result.M12 = -value.M12;
- result.M13 = -value.M13;
- result.M14 = -value.M14;
- result.M21 = -value.M21;
- result.M22 = -value.M22;
- result.M23 = -value.M23;
- result.M24 = -value.M24;
- result.M31 = -value.M31;
- result.M32 = -value.M32;
- result.M33 = -value.M33;
- result.M34 = -value.M34;
- result.M41 = -value.M41;
- result.M42 = -value.M42;
- result.M43 = -value.M43;
- result.M44 = -value.M44;
- }
+ static void Negate(const Matrix& value, Matrix& result);
// Performs a linear interpolation between two matrices.
// @param start Start matrix.
// @param end End matrix.
// @param amount Value between 0 and 1 indicating the weight of end.
// @param result When the method completes, contains the linear interpolation of the two matrices.
- static void Lerp(const Matrix& start, const Matrix& end, float amount, Matrix& result)
- {
- result.M11 = Math::Lerp(start.M11, end.M11, amount);
- result.M12 = Math::Lerp(start.M12, end.M12, amount);
- result.M13 = Math::Lerp(start.M13, end.M13, amount);
- result.M14 = Math::Lerp(start.M14, end.M14, amount);
- result.M21 = Math::Lerp(start.M21, end.M21, amount);
- result.M22 = Math::Lerp(start.M22, end.M22, amount);
- result.M23 = Math::Lerp(start.M23, end.M23, amount);
- result.M24 = Math::Lerp(start.M24, end.M24, amount);
- result.M31 = Math::Lerp(start.M31, end.M31, amount);
- result.M32 = Math::Lerp(start.M32, end.M32, amount);
- result.M33 = Math::Lerp(start.M33, end.M33, amount);
- result.M34 = Math::Lerp(start.M34, end.M34, amount);
- result.M41 = Math::Lerp(start.M41, end.M41, amount);
- result.M42 = Math::Lerp(start.M42, end.M42, amount);
- result.M43 = Math::Lerp(start.M43, end.M43, amount);
- result.M44 = Math::Lerp(start.M44, end.M44, amount);
- }
+ static void Lerp(const Matrix& start, const Matrix& end, float amount, Matrix& result);
// Performs a cubic interpolation between two matrices.
// @param start Start matrix.
@@ -1131,6 +970,7 @@ public:
static void CreateFromAxisAngle(const Float3& axis, float angle, Matrix& result);
public:
+ static Vector3 TransformVector(const Matrix& m, const Vector3& v);
static Float4 TransformPosition(const Matrix& m, const Float3& v);
static Float4 TransformPosition(const Matrix& m, const Float4& v);
};
diff --git a/Source/Engine/Core/Math/Matrix3x3.cpp b/Source/Engine/Core/Math/Matrix3x3.cpp
index 65a1b6b7e..f7a6298af 100644
--- a/Source/Engine/Core/Math/Matrix3x3.cpp
+++ b/Source/Engine/Core/Math/Matrix3x3.cpp
@@ -23,6 +23,11 @@ String Matrix3x3::ToString() const
return String::Format(TEXT("{}"), *this);
}
+float Matrix3x3::GetDeterminant() const
+{
+ return M11 * M22 * M33 + M12 * M23 * M31 + M13 * M21 * M32 - M13 * M22 * M31 - M12 * M21 * M33 - M11 * M23 * M32;
+}
+
void Matrix3x3::NormalizeScale()
{
const float scaleX = 1.0f / Float3(M11, M21, M31).Length();
diff --git a/Source/Engine/Core/Math/Matrix3x3.h b/Source/Engine/Core/Math/Matrix3x3.h
index 0680e7735..177c33d19 100644
--- a/Source/Engine/Core/Math/Matrix3x3.h
+++ b/Source/Engine/Core/Math/Matrix3x3.h
@@ -312,10 +312,7 @@ public:
///
/// Calculates the determinant of the Matrix3x3.
///
- float GetDeterminant() const
- {
- return M11 * M22 * M33 + M12 * M23 * M31 + M13 * M21 * M32 - M13 * M22 * M31 - M12 * M21 * M33 - M11 * M23 * M32;
- }
+ float GetDeterminant() const;
public:
///
@@ -352,7 +349,7 @@ public:
///
/// The Matrix3x3 whose inverse is to be calculated.
/// The inverse of the specified Matrix3x3.
- static Matrix3x3 Invert(Matrix3x3 value)
+ static Matrix3x3 Invert(const Matrix3x3& value)
{
Matrix3x3 result;
Invert(value, result);
diff --git a/Source/Engine/Core/Math/Transform.cpp b/Source/Engine/Core/Math/Transform.cpp
index f08de8279..463182415 100644
--- a/Source/Engine/Core/Math/Transform.cpp
+++ b/Source/Engine/Core/Math/Transform.cpp
@@ -18,6 +18,16 @@ String Transform::ToString() const
return String::Format(TEXT("{}"), *this);
}
+bool Transform::IsIdentity() const
+{
+ return Translation.IsZero() && Orientation.IsIdentity() && Scale.IsOne();
+}
+
+bool Transform::IsNanOrInfinity() const
+{
+ return Translation.IsNanOrInfinity() || Orientation.IsNanOrInfinity() || Scale.IsNanOrInfinity();
+}
+
Matrix Transform::GetRotation() const
{
Matrix result;
@@ -188,6 +198,15 @@ void Transform::WorldToLocalVector(const Vector3& vector, Vector3& result) const
result *= invScale;
}
+void Transform::WorldToLocal(const Quaternion& rotation, Quaternion& result) const
+{
+ Quaternion orientation = Orientation;
+ orientation.Conjugate();
+ Quaternion::Multiply(orientation, rotation, orientation);
+ orientation.Normalize();
+ result = orientation;
+}
+
Float3 Transform::GetRight() const
{
return Float3::Transform(Float3::Right, Orientation);
diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h
index f61ce8b9c..3811ce0be 100644
--- a/Source/Engine/Core/Math/Transform.h
+++ b/Source/Engine/Core/Math/Transform.h
@@ -90,18 +90,12 @@ public:
///
/// Checks if transform is an identity transformation.
///
- bool IsIdentity() const
- {
- return Translation.IsZero() && Orientation.IsIdentity() && Scale.IsOne();
- }
+ bool IsIdentity() const;
///
/// Returns true if transform has one or more components equal to +/- infinity or NaN.
///
- bool IsNanOrInfinity() const
- {
- return Translation.IsNanOrInfinity() || Orientation.IsNanOrInfinity() || Scale.IsNanOrInfinity();
- }
+ bool IsNanOrInfinity() const;
///
/// Calculates the determinant of this transformation.
@@ -278,6 +272,25 @@ public:
return result;
}
+ ///
+ /// Performs transformation of the given rotation in world space to the local space of this transform.
+ ///
+ /// The world space rotation.
+ /// The local space rotation.
+ void WorldToLocal(const Quaternion& rotation, Quaternion& result) const;
+
+ ///
+ /// Performs transformation of the given rotation in world space to the local space of this transform.
+ ///
+ /// The world space rotation.
+ /// The local space rotation.
+ Quaternion WorldToLocal(const Quaternion& rotation) const
+ {
+ Quaternion result;
+ WorldToLocal(rotation, result);
+ return result;
+ }
+
public:
FORCE_INLINE Transform operator*(const Transform& other) const
{
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index 64ad37b8e..60646cdbf 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -319,13 +319,9 @@ void Actor::SetParent(Actor* value, bool worldPositionsStays, bool canBreakPrefa
if (worldPositionsStays)
{
if (_parent)
- {
- _parent->GetTransform().WorldToLocal(prevTransform, _localTransform);
- }
+ _parent->_transform.WorldToLocal(prevTransform, _localTransform);
else
- {
_localTransform = prevTransform;
- }
}
// Fire events
@@ -622,7 +618,7 @@ void Actor::SetTransform(const Transform& value)
if (!(Vector3::NearEqual(_transform.Translation, value.Translation) && Quaternion::NearEqual(_transform.Orientation, value.Orientation, ACTOR_ORIENTATION_EPSILON) && Float3::NearEqual(_transform.Scale, value.Scale)))
{
if (_parent)
- _parent->GetTransform().WorldToLocal(value, _localTransform);
+ _parent->_transform.WorldToLocal(value, _localTransform);
else
_localTransform = value;
OnTransformChanged();
@@ -635,7 +631,7 @@ void Actor::SetPosition(const Vector3& value)
if (!Vector3::NearEqual(_transform.Translation, value))
{
if (_parent)
- _localTransform.Translation = _parent->GetTransform().WorldToLocal(value);
+ _localTransform.Translation = _parent->_transform.WorldToLocal(value);
else
_localTransform.Translation = value;
OnTransformChanged();
@@ -648,16 +644,9 @@ void Actor::SetOrientation(const Quaternion& value)
if (!Quaternion::NearEqual(_transform.Orientation, value, ACTOR_ORIENTATION_EPSILON))
{
if (_parent)
- {
- _localTransform.Orientation = _parent->GetOrientation();
- _localTransform.Orientation.Invert();
- Quaternion::Multiply(_localTransform.Orientation, value, _localTransform.Orientation);
- _localTransform.Orientation.Normalize();
- }
+ _parent->_transform.WorldToLocal(value, _localTransform.Orientation);
else
- {
_localTransform.Orientation = value;
- }
OnTransformChanged();
}
}
From 9a21cfd092621fdb5bc8bfe31e6d968c8095094a Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Tue, 20 Feb 2024 23:55:06 +0100
Subject: [PATCH 53/79] Fix transform scaling applying to nested objects when
drawing
#1796 #1350
---
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 2 +-
Source/Engine/Graphics/RenderView.h | 8 ++++++++
Source/Engine/Level/Actor.cpp | 19 +++++++++++++++++--
Source/Engine/Level/Actor.h | 5 +----
Source/Engine/Level/Actors/AnimatedModel.cpp | 16 +++++++++-------
Source/Engine/Level/Actors/Camera.cpp | 2 +-
Source/Engine/Level/Actors/Spline.cpp | 6 +++---
Source/Engine/Level/Actors/StaticModel.cpp | 8 ++++----
.../Particles/Graph/GPU/GPUParticles.cpp | 6 ++----
Source/Engine/Physics/Actors/Cloth.cpp | 3 ++-
.../ShadowsOfMordor/Builder.Entries.cpp | 2 +-
.../Engine/ShadowsOfMordor/Builder.Jobs.cpp | 2 +-
Source/Engine/UI/SpriteRender.cpp | 2 +-
13 files changed, 51 insertions(+), 30 deletions(-)
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 95f767d80..29032010e 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -658,7 +658,7 @@ namespace FlaxEditor.SceneGraph.GUI
}
}
actor.Name = item.ShortName;
- if (_dragAssets.Objects[i] is not PrefabItem p)
+ if (_dragAssets.Objects[i] is not PrefabItem)
actor.Transform = Transform.Identity;
var previousTrans = actor.Transform;
ActorNode.Root.Spawn(actor, spawnParent);
diff --git a/Source/Engine/Graphics/RenderView.h b/Source/Engine/Graphics/RenderView.h
index e72ebaa45..778c8f2e5 100644
--- a/Source/Engine/Graphics/RenderView.h
+++ b/Source/Engine/Graphics/RenderView.h
@@ -335,4 +335,12 @@ public:
// Calculates the world matrix for the given transformation instance rendering.
void GetWorldMatrix(const Transform& transform, Matrix& world) const;
+
+ // Applies the render origin to the transformation instance matrix.
+ FORCE_INLINE void GetWorldMatrix(Matrix& world) const
+ {
+ world.M41 -= Origin.X;
+ world.M42 -= Origin.Y;
+ world.M43 -= Origin.Z;
+ }
};
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index 60646cdbf..6ae69d471 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -657,7 +657,7 @@ void Actor::SetScale(const Float3& value)
if (!Float3::NearEqual(_transform.Scale, value))
{
if (_parent)
- Float3::Divide(value, _parent->GetScale(), _localTransform.Scale);
+ Float3::Divide(value, _parent->_transform.Scale, _localTransform.Scale);
else
_localTransform.Scale = value;
OnTransformChanged();
@@ -753,10 +753,25 @@ void Actor::AddMovement(const Vector3& translation, const Quaternion& rotation)
void Actor::GetWorldToLocalMatrix(Matrix& worldToLocal) const
{
- _transform.GetWorld(worldToLocal);
+ GetLocalToWorldMatrix(worldToLocal);
worldToLocal.Invert();
}
+void Actor::GetLocalToWorldMatrix(Matrix& localToWorld) const
+{
+#if 0
+ _transform.GetWorld(localToWorld);
+#else
+ _localTransform.GetWorld(localToWorld);
+ if (_parent)
+ {
+ Matrix parentToWorld;
+ _parent->GetLocalToWorldMatrix(parentToWorld);
+ localToWorld = localToWorld * parentToWorld;
+ }
+#endif
+}
+
void Actor::LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId)
{
ASSERT(prefabId.IsValid());
diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h
index ddf6f0587..bb3570eee 100644
--- a/Source/Engine/Level/Actor.h
+++ b/Source/Engine/Level/Actor.h
@@ -638,10 +638,7 @@ public:
/// Gets the matrix that transforms a point from the local space of the actor to world space.
///
/// The world to local matrix.
- API_FUNCTION() FORCE_INLINE void GetLocalToWorldMatrix(API_PARAM(Out) Matrix& localToWorld) const
- {
- _transform.GetWorld(localToWorld);
- }
+ API_FUNCTION() void GetLocalToWorldMatrix(API_PARAM(Out) Matrix& localToWorld) const;
public:
///
diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp
index 319def475..027995e19 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.cpp
+++ b/Source/Engine/Level/Actors/AnimatedModel.cpp
@@ -127,7 +127,7 @@ void AnimatedModel::GetCurrentPose(Array& nodesTransformation, bool worl
if (worldSpace)
{
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
for (auto& m : nodesTransformation)
m = m * world;
}
@@ -142,7 +142,7 @@ void AnimatedModel::SetCurrentPose(const Array& nodesTransformation, boo
if (worldSpace)
{
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
Matrix invWorld;
Matrix::Invert(world, invWorld);
for (auto& m : GraphInstance.NodesPose)
@@ -162,7 +162,7 @@ void AnimatedModel::GetNodeTransformation(int32 nodeIndex, Matrix& nodeTransform
if (worldSpace)
{
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
nodeTransformation = nodeTransformation * world;
}
}
@@ -181,7 +181,7 @@ void AnimatedModel::SetNodeTransformation(int32 nodeIndex, const Matrix& nodeTra
if (worldSpace)
{
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
Matrix invWorld;
Matrix::Invert(world, invWorld);
GraphInstance.NodesPose[nodeIndex] = GraphInstance.NodesPose[nodeIndex] * invWorld;
@@ -731,7 +731,9 @@ void AnimatedModel::UpdateBounds()
}
else if (model && model->IsLoaded() && model->LODs.Count() != 0)
{
- const BoundingBox modelBox = model->GetBox(_transform.GetWorld());
+ Matrix world;
+ GetLocalToWorldMatrix(world);
+ const BoundingBox modelBox = model->GetBox(world);
BoundingBox box = modelBox;
if (GraphInstance.NodesPose.Count() != 0)
{
@@ -911,8 +913,8 @@ void AnimatedModel::Draw(RenderContext& renderContext)
if (renderContext.View.Pass == DrawPass::GlobalSurfaceAtlas)
return; // No supported
Matrix world;
- const Float3 translation = _transform.Translation - renderContext.View.Origin;
- Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world);
+ GetLocalToWorldMatrix(world);
+ renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
_lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.WorldPosition));
diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp
index c3559c87f..6f3052598 100644
--- a/Source/Engine/Level/Actors/Camera.cpp
+++ b/Source/Engine/Level/Actors/Camera.cpp
@@ -378,7 +378,7 @@ void Camera::UpdateCache()
// Update editor preview model cache
Matrix rot, tmp, world;
- _transform.GetWorld(tmp);
+ GetLocalToWorldMatrix(tmp);
Matrix::RotationY(PI * -0.5f, rot);
Matrix::Multiply(rot, tmp, world);
diff --git a/Source/Engine/Level/Actors/Spline.cpp b/Source/Engine/Level/Actors/Spline.cpp
index dfe7c2be8..a54384dd9 100644
--- a/Source/Engine/Level/Actors/Spline.cpp
+++ b/Source/Engine/Level/Actors/Spline.cpp
@@ -467,7 +467,7 @@ void Spline::UpdateSpline()
for (int32 i = 1; i < count; i++)
_localBounds.Merge(keyframes[i].Value.Translation);
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box);
SplineUpdated();
@@ -542,7 +542,7 @@ void Spline::OnTransformChanged()
Actor::OnTransformChanged();
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box);
BoundingSphere::FromBox(_box, _sphere);
}
@@ -560,7 +560,7 @@ void Spline::Initialize()
for (int32 i = 1; i < count; i++)
_localBounds.Merge(keyframes[i].Value.Translation);
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
BoundingBox::Transform(_localBounds, world, _box);
}
diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp
index d5c7e0e3e..58a471e04 100644
--- a/Source/Engine/Level/Actors/StaticModel.cpp
+++ b/Source/Engine/Level/Actors/StaticModel.cpp
@@ -335,8 +335,8 @@ void StaticModel::Draw(RenderContext& renderContext)
return;
}
Matrix world;
- const Float3 translation = _transform.Translation - renderContext.View.Origin;
- Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world);
+ GetLocalToWorldMatrix(world);
+ renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
if (_vertexColorsDirty)
FlushVertexColors();
@@ -369,8 +369,8 @@ void StaticModel::Draw(RenderContextBatch& renderContextBatch)
return;
const RenderContext& renderContext = renderContextBatch.GetMainContext();
Matrix world;
- const Float3 translation = _transform.Translation - renderContext.View.Origin;
- Matrix::Transformation(_transform.Scale, _transform.Orientation, translation, world);
+ GetLocalToWorldMatrix(world);
+ renderContext.View.GetWorldMatrix(world);
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, world);
if (_vertexColorsDirty)
FlushVertexColors();
diff --git a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp
index 57ffa251a..94cc5ef08 100644
--- a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp
+++ b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp
@@ -233,11 +233,9 @@ void GPUParticles::Execute(GPUContext* context, ParticleEmitter* emitter, Partic
else
{
Matrix worldMatrix;
- const Transform transform = effect->GetTransform();
+ effect->GetLocalToWorldMatrix(worldMatrix);
if (viewTask)
- viewTask->View.GetWorldMatrix(transform, worldMatrix);
- else
- transform.GetWorld(worldMatrix);
+ viewTask->View.GetWorldMatrix(worldMatrix);
Matrix::Transpose(worldMatrix, cbData->WorldMatrix);
worldMatrix.Invert();
Matrix::Transpose(worldMatrix, cbData->InvWorldMatrix);
diff --git a/Source/Engine/Physics/Actors/Cloth.cpp b/Source/Engine/Physics/Actors/Cloth.cpp
index a35acb066..2c6199490 100644
--- a/Source/Engine/Physics/Actors/Cloth.cpp
+++ b/Source/Engine/Physics/Actors/Cloth.cpp
@@ -847,7 +847,8 @@ void Cloth::OnPostUpdate()
if (_meshDeformation)
{
// Mark mesh as dirty
- const Matrix invWorld = Matrix::Invert(_transform.GetWorld());
+ Matrix invWorld;
+ GetWorldToLocalMatrix(invWorld);
BoundingBox localBounds;
BoundingBox::Transform(_box, invWorld, localBounds);
_meshDeformation->Dirty(_mesh.LODIndex, _mesh.MeshIndex, MeshBufferType::Vertex0, localBounds);
diff --git a/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp b/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
index 67af59585..7ab93cfc8 100644
--- a/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
+++ b/Source/Engine/ShadowsOfMordor/Builder.Entries.cpp
@@ -64,7 +64,7 @@ bool cacheStaticGeometryTree(Actor* actor, ShadowsOfMordor::Builder::SceneBuildC
if (useLightmap && anyValid && entry.Scale > ZeroTolerance)
{
Matrix worldMatrix;
- staticModel->GetTransform().GetWorld(worldMatrix);
+ staticModel->GetLocalToWorldMatrix(worldMatrix);
entry.Box = model->GetBox(worldMatrix);
results.Add(entry);
}
diff --git a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp
index 8aed89eb3..02cedf1ad 100644
--- a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp
+++ b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp
@@ -125,7 +125,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
auto& lod = staticModel->Model->LODs[0];
Matrix worldMatrix;
- staticModel->GetTransform().GetWorld(worldMatrix);
+ staticModel->GetLocalToWorldMatrix(worldMatrix);
Matrix::Transpose(worldMatrix, shaderData.WorldMatrix);
shaderData.LightmapArea = staticModel->Lightmap.UVsArea;
diff --git a/Source/Engine/UI/SpriteRender.cpp b/Source/Engine/UI/SpriteRender.cpp
index 25446c9c5..a2ad0021c 100644
--- a/Source/Engine/UI/SpriteRender.cpp
+++ b/Source/Engine/UI/SpriteRender.cpp
@@ -213,7 +213,7 @@ void SpriteRender::OnTransformChanged()
const BoundingSphere localSphere(Vector3::Zero, _size.Length());
Matrix world;
- _transform.GetWorld(world);
+ GetLocalToWorldMatrix(world);
BoundingSphere::Transform(localSphere, world, _sphere);
BoundingBox::FromSphere(_sphere, _box);
if (_sceneRenderingKey != -1)
From 149a6a29f883e83a3763eb92328cc66dc254f534 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 00:00:58 +0100
Subject: [PATCH 54/79] Fix crash when using very small render resolution
#2261
---
Source/Engine/Renderer/PostProcessingPass.cpp | 22 +++++++++----------
.../Renderer/ScreenSpaceReflectionsPass.cpp | 2 ++
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/Source/Engine/Renderer/PostProcessingPass.cpp b/Source/Engine/Renderer/PostProcessingPass.cpp
index 7c93177e0..6222153b6 100644
--- a/Source/Engine/Renderer/PostProcessingPass.cpp
+++ b/Source/Engine/Renderer/PostProcessingPass.cpp
@@ -194,8 +194,18 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
bool useCameraArtifacts = EnumHasAnyFlags(view.Flags, ViewFlags::CameraArtifacts) && (settings.CameraArtifacts.VignetteIntensity > 0.0f || settings.CameraArtifacts.GrainAmount > 0.0f || settings.CameraArtifacts.ChromaticDistortion > 0.0f || settings.CameraArtifacts.ScreenFadeColor.A > 0.0f);
bool useLensFlares = EnumHasAnyFlags(view.Flags, ViewFlags::LensFlares) && settings.LensFlares.Intensity > 0.0f && useBloom;
+ // Cache viewport sizes
+ int32 w1 = input->Width();
+ int32 w2 = w1 >> 1;
+ int32 w4 = w2 >> 1;
+ int32 w8 = w4 >> 1;
+ int32 h1 = input->Height();
+ int32 h2 = h1 >> 1;
+ int32 h4 = h2 >> 1;
+ int32 h8 = h4 >> 1;
+
// Ensure to have valid data and if at least one effect should be applied
- if (!(useBloom || useToneMapping || useCameraArtifacts) || checkIfSkipPass())
+ if (!(useBloom || useToneMapping || useCameraArtifacts) || checkIfSkipPass() || w8 == 0 || h8 ==0)
{
// Resources are missing. Do not perform rendering. Just copy raw frame
context->SetViewportAndScissors((float)output->Width(), (float)output->Height());
@@ -209,16 +219,6 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
auto cb0 = shader->GetCB(0);
auto cb1 = shader->GetCB(1);
- // Cache viewport sizes
- int32 w1 = input->Width();
- int32 w2 = w1 >> 1;
- int32 w4 = w2 >> 1;
- int32 w8 = w4 >> 1;
- int32 h1 = input->Height();
- int32 h2 = h1 >> 1;
- int32 h4 = h2 >> 1;
- int32 h8 = h4 >> 1;
-
////////////////////////////////////////////////////////////////////////////////////
// Setup shader
diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
index 80bacf650..7ba9fbb50 100644
--- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
+++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp
@@ -176,6 +176,8 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
// Prepare resolutions for passes
const int32 width = buffers->GetWidth();
const int32 height = buffers->GetHeight();
+ if (width < 4 || height < 4)
+ return;
const int32 traceWidth = width / static_cast(settings.RayTracePassResolution);
const int32 traceHeight = height / static_cast(settings.RayTracePassResolution);
const int32 resolveWidth = width / static_cast(settings.RayTracePassResolution);
From 97cb8d1b619e691ab4fe3fd9a20f49cfd1f5ee04 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 00:07:38 +0100
Subject: [PATCH 55/79] Clarify doc comment
---
Source/Engine/Core/Math/Math.h | 2 +-
Source/Shaders/Math.hlsl | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Source/Engine/Core/Math/Math.h b/Source/Engine/Core/Math/Math.h
index a3c05fce4..a7d806dfe 100644
--- a/Source/Engine/Core/Math/Math.h
+++ b/Source/Engine/Core/Math/Math.h
@@ -901,7 +901,7 @@ namespace Math
return length - Abs(Repeat(t, length * 2.0f) - length);
}
- // Rotates position about the given axis by the given angle, in radians, and returns the offset to position
+ // Rotates position about the input axis by the given angle (in radians), and returns the delta to position
Vector3 FLAXENGINE_API RotateAboutAxis(const Vector3& normalizedRotationAxis, float angle, const Vector3& positionOnAxis, const Vector3& position);
Vector3 FLAXENGINE_API ExtractLargestComponent(const Vector3& v);
diff --git a/Source/Shaders/Math.hlsl b/Source/Shaders/Math.hlsl
index 67ddc1887..9ddef6c02 100644
--- a/Source/Shaders/Math.hlsl
+++ b/Source/Shaders/Math.hlsl
@@ -241,7 +241,7 @@ float4 FindQuatBetween(float3 from, float3 to)
return normalize(result);
}
-// Rotates Position about the given axis by the given angle, in radians, and returns the offset to position
+// Rotates position about the input axis by the given angle (in radians), and returns the delta to position
float3 RotateAboutAxis(float4 normalizedRotationAxisAndAngle, float3 positionOnAxis, float3 position)
{
float3 pointOnAxis = positionOnAxis + normalizedRotationAxisAndAngle.xyz * dot(normalizedRotationAxisAndAngle.xyz, position - positionOnAxis);
From f3e6b74043d7bfdd636a2ea5f9e540e278975d60 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 09:12:31 +0100
Subject: [PATCH 56/79] Add breaking node connection under mouse with middle
button click
#1010
---
Source/Editor/Surface/VisjectSurface.Input.cs | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs
index 419c2d468..356e798fa 100644
--- a/Source/Editor/Surface/VisjectSurface.Input.cs
+++ b/Source/Editor/Surface/VisjectSurface.Input.cs
@@ -557,7 +557,21 @@ namespace FlaxEditor.Surface
_middleMouseDown = false;
EndMouseCapture();
Cursor = CursorType.Default;
- _mouseMoveAmount = 0;
+ if (_mouseMoveAmount > 0)
+ _mouseMoveAmount = 0;
+ else if (CanEdit)
+ {
+ // Surface was not moved with MMB so try to remove connection underneath
+ var mousePos = _rootControl.PointFromParent(ref location);
+ if (IntersectsConnection(mousePos, out InputBox inputBox, out OutputBox outputBox))
+ {
+ var action = new EditNodeConnections(inputBox.ParentNode.Context, inputBox.ParentNode);
+ inputBox.BreakConnection(outputBox);
+ action.End();
+ AddBatchedUndoAction(action);
+ MarkAsEdited();
+ }
+ }
}
// Base
From d7dbc0fbdc70b49cbc9775699b340f22005732b5 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 20:21:45 +0100
Subject: [PATCH 57/79] Fix opening projects with PostFx material assigned in
Graphics Settings
#1993
---
Source/Engine/Content/SoftAssetReference.h | 13 ++++++++++
.../Engine/Graphics/PostProcessSettings.cpp | 7 +++---
Source/Engine/Graphics/PostProcessSettings.h | 4 +--
Source/Engine/Scripting/ManagedCLR/MUtils.h | 25 +++++++++++++++++++
4 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/Source/Engine/Content/SoftAssetReference.h b/Source/Engine/Content/SoftAssetReference.h
index d237b5fd7..0f1be471d 100644
--- a/Source/Engine/Content/SoftAssetReference.h
+++ b/Source/Engine/Content/SoftAssetReference.h
@@ -89,6 +89,11 @@ public:
OnSet(other.GetID());
}
+ SoftAssetReference(const Guid& id)
+ {
+ OnSet(id);
+ }
+
SoftAssetReference(SoftAssetReference&& other)
{
OnSet(other.GetID());
@@ -111,6 +116,10 @@ public:
{
return GetID() == other.GetID();
}
+ FORCE_INLINE bool operator==(const Guid& other) const
+ {
+ return GetID() == other;
+ }
FORCE_INLINE bool operator!=(T* other) const
{
return Get() != other;
@@ -119,6 +128,10 @@ public:
{
return GetID() != other.GetID();
}
+ FORCE_INLINE bool operator!=(const Guid& other) const
+ {
+ return GetID() != other;
+ }
SoftAssetReference& operator=(const SoftAssetReference& other)
{
if (this != &other)
diff --git a/Source/Engine/Graphics/PostProcessSettings.cpp b/Source/Engine/Graphics/PostProcessSettings.cpp
index 6e2b21045..4de7bdb2e 100644
--- a/Source/Engine/Graphics/PostProcessSettings.cpp
+++ b/Source/Engine/Graphics/PostProcessSettings.cpp
@@ -207,12 +207,11 @@ void PostFxMaterialsSettings::BlendWith(PostFxMaterialsSettings& other, float we
if (isHalf)
{
int32 indexSrc = 0;
- const AssetReference* materialsSrc = other.Materials.Get();
+ const SoftAssetReference* materialsSrc = other.Materials.Get();
while (Materials.Count() != POST_PROCESS_SETTINGS_MAX_MATERIALS && indexSrc < other.Materials.Count())
{
- MaterialBase* mat = materialsSrc[indexSrc].Get();
- if (mat && !Materials.Contains(mat))
- Materials.Add(mat);
+ if (!Materials.Contains(materialsSrc[indexSrc].GetID()))
+ Materials.Add(materialsSrc[indexSrc]);
indexSrc++;
}
}
diff --git a/Source/Engine/Graphics/PostProcessSettings.h b/Source/Engine/Graphics/PostProcessSettings.h
index 1d695f353..5d95f7c74 100644
--- a/Source/Engine/Graphics/PostProcessSettings.h
+++ b/Source/Engine/Graphics/PostProcessSettings.h
@@ -1929,8 +1929,8 @@ API_STRUCT() struct FLAXENGINE_API PostFxMaterialsSettings : ISerializable
///
/// The post-process materials collection for rendering (fixed capacity).
///
- API_FIELD(Attributes="EditorDisplay(null, EditorDisplayAttribute.InlineStyle)")
- Array, FixedAllocation> Materials;
+ API_FIELD(Attributes="EditorDisplay(null, EditorDisplayAttribute.InlineStyle), Collection(MaxCount=8)")
+ Array, FixedAllocation> Materials;
public:
///
diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.h b/Source/Engine/Scripting/ManagedCLR/MUtils.h
index ed1b690c2..46601ede7 100644
--- a/Source/Engine/Scripting/ManagedCLR/MUtils.h
+++ b/Source/Engine/Scripting/ManagedCLR/MUtils.h
@@ -347,6 +347,31 @@ struct MConverter>
}
};
+// TODO: use MarshalAs=Guid on SoftAssetReference to pass guid over bindings and not load asset in glue code
+template
+class SoftAssetReference;
+template
+struct MConverter>
+{
+ void ToManagedArray(MArray* result, const Span>& data)
+ {
+ if (data.Length() == 0)
+ return;
+ MObject** objects = (MObject**)Allocator::Allocate(data.Length() * sizeof(MObject*));
+ for (int32 i = 0; i < data.Length(); i++)
+ objects[i] = data[i].GetManagedInstance();
+ MCore::GC::WriteArrayRef(result, Span(objects, data.Length()));
+ Allocator::Free(objects);
+ }
+
+ void ToNativeArray(Span>& result, const MArray* data)
+ {
+ MObject** dataPtr = MCore::Array::GetAddress(data);
+ for (int32 i = 0; i < result.Length(); i++)
+ result.Get()[i] = (T*)ScriptingObject::ToNative(dataPtr[i]);
+ }
+};
+
// Converter for Array.
template
struct MConverter>
From fa606ce5f6a5260d2629bdf5435bd7e91d5a2914 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 22:05:08 +0100
Subject: [PATCH 58/79] Fix render view panning when bug when no camera is
active
#1997
---
Source/Engine/Graphics/RenderTask.cpp | 3 +++
Source/Engine/Graphics/RenderView.cs | 1 +
2 files changed, 4 insertions(+)
diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp
index 8a10a0444..3527c8627 100644
--- a/Source/Engine/Graphics/RenderTask.cpp
+++ b/Source/Engine/Graphics/RenderTask.cpp
@@ -403,6 +403,9 @@ void SceneRenderTask::OnEnd(GPUContext* context)
View.PrevView = View.View;
View.PrevProjection = View.Projection;
View.PrevViewProjection = View.ViewProjection();
+
+ // Remove jitter from the projection (in case it's unmodified by gameplay eg. due to missing camera)
+ View.Projection = View.NonJitteredProjection;
}
bool SceneRenderTask::Resize(int32 width, int32 height)
diff --git a/Source/Engine/Graphics/RenderView.cs b/Source/Engine/Graphics/RenderView.cs
index 72cfe3577..f83779a43 100644
--- a/Source/Engine/Graphics/RenderView.cs
+++ b/Source/Engine/Graphics/RenderView.cs
@@ -30,6 +30,7 @@ namespace FlaxEngine
Frustum = new BoundingFrustum(ref viewProjection);
Matrix.Invert(ref viewProjection, out IVP);
CullingFrustum = Frustum;
+ NonJitteredProjection = Projection;
}
///
From f20805e56701ab4ec118188891e348efe124694c Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 22:39:32 +0100
Subject: [PATCH 59/79] Fix Json serializer for CSharp data to use UTF-8 text
encoding
#1994
---
Source/Editor/Managed/ManagedEditor.Internal.cpp | 2 +-
Source/Engine/Serialization/JsonSerializer.cs | 13 ++++++++++++-
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp
index 53c0fbab2..8ee058552 100644
--- a/Source/Editor/Managed/ManagedEditor.Internal.cpp
+++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp
@@ -204,7 +204,7 @@ DEFINE_INTERNAL_CALL(bool) EditorInternal_SaveJsonAsset(MString* outputPathObj,
FileSystem::NormalizePath(outputPath);
const StringView dataObjChars = MCore::String::GetChars(dataObj);
- const StringAsANSI<> data(dataObjChars.Get(), dataObjChars.Length());
+ const StringAsUTF8<> data(dataObjChars.Get(), dataObjChars.Length());
const StringAnsiView dataAnsi(data.Get(), data.Length());
const StringView dataTypeNameObjChars = MCore::String::GetChars(dataTypeNameObj);
diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs
index 076e8abe7..076beef7d 100644
--- a/Source/Engine/Serialization/JsonSerializer.cs
+++ b/Source/Engine/Serialization/JsonSerializer.cs
@@ -15,6 +15,17 @@ using Newtonsoft.Json.Serialization;
namespace FlaxEngine.Json
{
+ sealed class StringWriterWithEncoding : StringWriter
+ {
+ public override Encoding Encoding { get; }
+
+ public StringWriterWithEncoding(System.Text.StringBuilder sb, IFormatProvider formatProvider, Encoding encoding)
+ : base(sb, formatProvider)
+ {
+ Encoding = encoding;
+ }
+ }
+
partial class JsonSerializer
{
internal class SerializerCache
@@ -37,7 +48,7 @@ namespace FlaxEngine.Json
{
IsManagedOnly = isManagedOnly;
StringBuilder = new StringBuilder(256);
- StringWriter = new StringWriter(StringBuilder, CultureInfo.InvariantCulture);
+ StringWriter = new StringWriterWithEncoding(StringBuilder, CultureInfo.InvariantCulture, Encoding.UTF8);
MemoryStream = new UnmanagedMemoryStream((byte*)0, 0);
#if FLAX_EDITOR
From 318b00c617140b487c8cb60ee46fb44bd7545338 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Wed, 21 Feb 2024 23:18:09 +0100
Subject: [PATCH 60/79] Fix editor exit with error code when game cooking CL
fails
#2248
---
Source/Editor/Cooker/GameCooker.cpp | 12 +++++++-----
Source/Editor/Cooker/GameCooker.h | 3 ++-
Source/Editor/Editor.cs | 2 +-
Source/Editor/Windows/GameCookerWindow.cs | 7 ++++++-
Source/Engine/Engine/Engine.cpp | 2 ++
5 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp
index 52550128e..894f4ed2d 100644
--- a/Source/Editor/Cooker/GameCooker.cpp
+++ b/Source/Editor/Cooker/GameCooker.cpp
@@ -456,18 +456,18 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
return result;
}
-void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array& customDefines, const StringView& preset, const StringView& presetTarget)
+bool GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array& customDefines, const StringView& preset, const StringView& presetTarget)
{
if (IsRunning())
{
LOG(Warning, "Cannot start a build. Already running.");
- return;
+ return true;
}
PlatformTools* tools = GetTools(platform);
if (tools == nullptr)
{
LOG(Error, "Build platform {0} is not supported.", ::ToString(platform));
- return;
+ return true;
}
// Setup
@@ -493,7 +493,7 @@ void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
if (FileSystem::CreateDirectory(data.CacheDirectory))
{
LOG(Error, "Cannot setup game building cache directory.");
- return;
+ return true;
}
}
@@ -510,13 +510,15 @@ void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
{
GameCookerImpl::IsRunning = false;
LOG(Error, "Failed to start a build thread.");
- return;
+ return true;
}
}
else
{
ThreadCond.NotifyOne();
}
+
+ return false;
}
void GameCooker::Cancel(bool waitForEnd)
diff --git a/Source/Editor/Cooker/GameCooker.h b/Source/Editor/Cooker/GameCooker.h
index 5c2b89787..f328c8719 100644
--- a/Source/Editor/Cooker/GameCooker.h
+++ b/Source/Editor/Cooker/GameCooker.h
@@ -82,7 +82,8 @@ public:
/// The list of custom defines passed to the build tool when compiling project scripts. Can be used in build scripts for configuration (Configuration.CustomDefines).
/// The name of build preset used for cooking (can be used by editor and game plugins).
/// The name of build preset target used for cooking (can be used by editor and game plugins).
- API_FUNCTION() static void Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array& customDefines, const StringView& preset = StringView::Empty, const StringView& presetTarget = StringView::Empty);
+ /// True if failed to start the build, otherwise false.
+ API_FUNCTION() static bool Build(BuildPlatform platform, BuildConfiguration configuration, const StringView& outputPath, BuildOptions options, const Array& customDefines, const StringView& preset = StringView::Empty, const StringView& presetTarget = StringView::Empty);
///
/// Sends a cancel event to the game building service.
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index 266d8235f..2f332e1d7 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -1395,7 +1395,7 @@ namespace FlaxEditor
internal void BuildCommand(string arg)
{
if (TryBuildCommand(arg))
- Engine.RequestExit();
+ Engine.RequestExit(1);
}
private bool TryBuildCommand(string arg)
diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs
index 2ef9c05cf..2c2fafbdf 100644
--- a/Source/Editor/Windows/GameCookerWindow.cs
+++ b/Source/Editor/Windows/GameCookerWindow.cs
@@ -1006,7 +1006,12 @@ namespace FlaxEditor.Windows
_preBuildAction = target.PreBuildAction;
_postBuildAction = target.PostBuildAction;
- GameCooker.Build(target.Platform, target.Mode, target.Output, item.Options, target.CustomDefines, item.PresetName, target.Name);
+ bool failed = GameCooker.Build(target.Platform, target.Mode, target.Output, item.Options, target.CustomDefines, item.PresetName, target.Name);
+ if (failed && _exitOnBuildEnd)
+ {
+ _exitOnBuildEnd = false;
+ Engine.RequestExit(1);
+ }
}
else if (_exitOnBuildEnd)
{
diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp
index fe7541adb..0754c8456 100644
--- a/Source/Engine/Engine/Engine.cpp
+++ b/Source/Engine/Engine/Engine.cpp
@@ -241,6 +241,8 @@ void Engine::Exit(int32 exitCode)
void Engine::RequestExit(int32 exitCode)
{
+ if (Globals::IsRequestingExit)
+ return;
#if USE_EDITOR
// Send to editor (will leave play mode if need to)
if (Editor::Managed->OnAppExit())
From 8351a75676e2634bba8d4b0c6f72a354ade4482b Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Fri, 23 Feb 2024 14:43:14 +0100
Subject: [PATCH 61/79] Codestyle fixes #2192
---
.../Engine/Physics/Actors/WheeledVehicle.cpp | 64 +++---
Source/Engine/Physics/Actors/WheeledVehicle.h | 36 ++--
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 189 +++++++++---------
3 files changed, 140 insertions(+), 149 deletions(-)
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
index 803b080c4..e0ae1f3c4 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -43,7 +43,7 @@ WheeledVehicle::DriveControlSettings WheeledVehicle::GetDriveControl() const
return _driveControl;
}
-void WheeledVehicle::SetDriveControl(DriveControlSettings& value)
+void WheeledVehicle::SetDriveControl(DriveControlSettings value)
{
value.RiseRateAcceleration = Math::Max(value.RiseRateAcceleration, 0.01f);
value.RiseRateBrake = Math::Max(value.RiseRateBrake, 0.01f);
@@ -58,28 +58,29 @@ void WheeledVehicle::SetDriveControl(DriveControlSettings& value)
// Don't let have an invalid steer vs speed list.
if (value.SteerVsSpeed.Count() < 1)
value.SteerVsSpeed.Add(WheeledVehicle::SteerControl());
- else // physx backend requires the max of 4 values only
+ else // PhysX backend requires the max of 4 values only
while (value.SteerVsSpeed.Count() > 4)
value.SteerVsSpeed.RemoveLast();
- // Maintain all values clamped to have a ordened speed list
- int steerVsSpeedCount = value.SteerVsSpeed.Count();
- for (int i = 0; i < steerVsSpeedCount; i++)
+ // Maintain all values clamped to have an ordered speed list
+ const int32 steerVsSpeedCount = value.SteerVsSpeed.Count();
+ for (int32 i = 0; i < steerVsSpeedCount; i++)
{
// Apply only on changed value
- if (_driveControl.SteerVsSpeed[i].Speed != value.SteerVsSpeed[i].Speed || _driveControl.SteerVsSpeed[i].Steer != value.SteerVsSpeed[i].Steer)
+ if (Math::NotNearEqual(_driveControl.SteerVsSpeed[i].Speed, value.SteerVsSpeed[i].Speed) ||
+ Math::NotNearEqual(_driveControl.SteerVsSpeed[i].Steer, value.SteerVsSpeed[i].Steer))
{
- WheeledVehicle::SteerControl& steerVsSpeed = value.SteerVsSpeed[i];
+ SteerControl& steerVsSpeed = value.SteerVsSpeed[i];
steerVsSpeed.Steer = Math::Saturate(steerVsSpeed.Steer);
steerVsSpeed.Speed = Math::Max(steerVsSpeed.Speed, 10.0f);
- // Clamp speeds to have an ordened list.
+ // Clamp speeds to have an ordered list
if (i >= 1)
{
- WheeledVehicle::SteerControl& lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
- WheeledVehicle::SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
- float minSpeed = lastSteerVsSpeed.Speed;
- float maxSpeed = nextSteerVsSpeed.Speed;
+ const SteerControl& lastSteerVsSpeed = value.SteerVsSpeed[i - 1];
+ const SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[Math::Clamp(i + 1, 0, steerVsSpeedCount - 1)];
+ const float minSpeed = lastSteerVsSpeed.Speed;
+ const float maxSpeed = nextSteerVsSpeed.Speed;
if (i + 1 < steerVsSpeedCount - 1)
steerVsSpeed.Speed = Math::Clamp(steerVsSpeed.Speed, minSpeed, maxSpeed);
@@ -88,7 +89,7 @@ void WheeledVehicle::SetDriveControl(DriveControlSettings& value)
}
else if (steerVsSpeedCount > 1)
{
- WheeledVehicle::SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
+ const SteerControl& nextSteerVsSpeed = value.SteerVsSpeed[i + 1];
steerVsSpeed.Speed = Math::Min(steerVsSpeed.Speed, nextSteerVsSpeed.Speed);
}
}
@@ -108,7 +109,8 @@ void WheeledVehicle::SetWheels(const Array& value)
{
auto& oldWheel = _wheels.Get()[wheelIndex];
auto& newWheel = value.Get()[wheelIndex];
- if (Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) || oldWheel.Collider != newWheel.Collider)
+ if (Math::NotNearEqual(oldWheel.SuspensionForceOffset, newWheel.SuspensionForceOffset) ||
+ oldWheel.Collider != newWheel.Collider)
{
softUpdate = false;
break;
@@ -321,7 +323,7 @@ void WheeledVehicle::Setup()
return;
// Release previous
- void *scene = GetPhysicsScene()->GetPhysicsScene();
+ void* scene = GetPhysicsScene()->GetPhysicsScene();
if (_vehicle)
{
PhysicsBackend::RemoveVehicle(scene, this);
@@ -414,21 +416,20 @@ void WheeledVehicle::OnDebugDrawSelected()
}
}
- // Draw anti roll bars axes
- int wheelsCount = _wheels.Count();
- for (int i = 0; i < GetAntiRollBars().Count(); i++)
+ // Anti roll bars axes
+ const int32 wheelsCount = _wheels.Count();
+ for (int32 i = 0; i < GetAntiRollBars().Count(); i++)
{
- int axleIndex = GetAntiRollBars()[i].Axle;
- int leftWheelIndex = axleIndex * 2;
- int rightWheelIndex = leftWheelIndex + 1;
-
+ const int32 axleIndex = GetAntiRollBars()[i].Axle;
+ const int32 leftWheelIndex = axleIndex * 2;
+ const int32 rightWheelIndex = leftWheelIndex + 1;
if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
continue;
if (!_wheels[leftWheelIndex].Collider || !_wheels[rightWheelIndex].Collider)
continue;
-
DEBUG_DRAW_LINE(_wheels[leftWheelIndex].Collider->GetPosition(), _wheels[rightWheelIndex].Collider->GetPosition(), Color::Yellow, 0, false);
}
+
// Center of mass
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(_transform.LocalToWorld(_centerOfMassOffset), 10.0f), Color::Blue, 0, false);
@@ -437,7 +438,7 @@ void WheeledVehicle::OnDebugDrawSelected()
#endif
-void WheeledVehicle::Serialize(SerializeStream& stream, const void *otherObj)
+void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj)
{
RigidBody::Serialize(stream, otherObj);
@@ -454,7 +455,7 @@ void WheeledVehicle::Serialize(SerializeStream& stream, const void *otherObj)
SERIALIZE_MEMBER(AntiRollBars, _antiRollBars);
}
-void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier *modifier)
+void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
RigidBody::Deserialize(stream, modifier);
@@ -472,7 +473,7 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier *
_fixInvalidForwardDir |= modifier->EngineBuild < 6341;
}
-void WheeledVehicle::OnColliderChanged(Collider *c)
+void WheeledVehicle::OnColliderChanged(Collider* c)
{
RigidBody::OnColliderChanged(c);
@@ -495,7 +496,7 @@ void WheeledVehicle::OnActiveInTreeChanged()
Setup();
}
-void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene *previous)
+void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene* previous)
{
RigidBody::OnPhysicsSceneChanged(previous);
@@ -518,10 +519,9 @@ void WheeledVehicle::OnTransformChanged()
// Transform all vehicle children around the vehicle origin to fix the vehicle facing direction
const Quaternion rotationDelta(0.0f, -0.7071068f, 0.0f, 0.7071068f);
const Vector3 origin = GetPosition();
- for (Actor *child : Children)
+ for (Actor* child : Children)
{
Transform trans = child->GetTransform();
- ;
const Vector3 pivotOffset = trans.Translation - origin;
if (pivotOffset.IsZero())
{
@@ -541,7 +541,7 @@ void WheeledVehicle::OnTransformChanged()
}
}
-void WheeledVehicle::BeginPlay(SceneBeginData *data)
+void WheeledVehicle::BeginPlay(SceneBeginData* data)
{
RigidBody::BeginPlay(data);
@@ -550,14 +550,14 @@ void WheeledVehicle::BeginPlay(SceneBeginData *data)
#endif
#if USE_EDITOR
- GetSceneRendering()->AddPhysicsDebug(this);
+ GetSceneRendering()->AddPhysicsDebug(this);
#endif
}
void WheeledVehicle::EndPlay()
{
#if USE_EDITOR
- GetSceneRendering()->RemovePhysicsDebug(this);
+ GetSceneRendering()->RemovePhysicsDebug(this);
#endif
#if WITH_VEHICLE
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
index 2bc42d6d7..b2522bce3 100644
--- a/Source/Engine/Physics/Actors/WheeledVehicle.h
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -29,16 +29,16 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
// Tank Drive. Can have more than 4 wheel. Not use steer, control acceleration for each tank track.
Tank,
};
+
///
- /// Vehicle driving types.
- /// Used only on tanks to specify the drive mode.
+ /// Vehicle driving types. Used only on tanks to specify the drive mode.
///
API_ENUM() enum class DriveModes
{
- // Drive turning the vehicle using only one track
+ // Drive turning the vehicle using only one track.
Standard,
// Drive turning the vehicle using all tracks inverse direction.
- Special
+ Special,
};
///
@@ -52,21 +52,14 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// The vehicle speed.
///
- API_FIELD(Attributes = "Limit(0)") float Speed;
+ API_FIELD(Attributes = "Limit(0)") float Speed = 1000;
///
/// The target max steer of the speed.
///
- API_FIELD(Attributes = "Limit(0, 1)") float Steer;
+ API_FIELD(Attributes = "Limit(0, 1)") float Steer = 1;
- ///
- /// Create a Steer/Speed relationship structure.
- ///
- SteerControl()
- {
- Speed = 1000;
- Steer = 1;
- }
+ SteerControl() = default;
///
/// Create a Steer/Speed relationship structure.
@@ -177,8 +170,7 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
API_FIELD(Attributes="EditorOrder(17)") float FallRateSteer = 5.0f;
///
- /// Vehicle control relationship between speed and steer. The higher is the speed,
- /// decrease steer to make vehicle more maneuverable (limited only 4 relationships).
+ /// Vehicle control relationship between speed and steer. The higher is the speed, decrease steer to make vehicle more maneuverable (limited only 4 relationships).
///
API_FIELD() Array SteerVsSpeed = Array
{
@@ -249,7 +241,7 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// Number of gears to move to forward
///
- API_FIELD(Attributes = "Limit(1, 30)") int ForwardGearsRatios = 5;
+ API_FIELD(Attributes = "Limit(1, 30)") int32 ForwardGearsRatios = 5;
///
/// Time it takes to switch gear. Specified in seconds (s).
@@ -429,7 +421,7 @@ API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Wheeled Vehicle\"), ActorTo
///
/// The specific axle with wheels to apply anti roll.
///
- API_FIELD() int Axle;
+ API_FIELD() int32 Axle;
///
/// The anti roll stiffness.
@@ -449,8 +441,8 @@ private:
DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
Array> _wheelsData;
float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f, _tankLeftThrottle = 0.0f, _tankRightThrottle = 0.0f, _tankLeftBrake = 0.0f, _tankRightBrake = 0.0f;
- Array _wheels;
- Array _antiRollBars;
+ Array _wheels;
+ Array _antiRollBars;
DriveControlSettings _driveControl;
EngineSettings _engine;
DifferentialSettings _differential;
@@ -494,7 +486,7 @@ public:
///
/// Sets the vehicle drive control settings.
///
- API_PROPERTY() void SetDriveControl(DriveControlSettings& value);
+ API_PROPERTY() void SetDriveControl(DriveControlSettings value);
///
/// Sets the vehicle wheels settings.
@@ -532,7 +524,7 @@ public:
API_PROPERTY() void SetGearbox(const GearboxSettings& value);
//
- /// Sets axles anti roll bars to increase vehicle estability.
+ /// Sets axles anti roll bars to increase vehicle stability.
///
API_PROPERTY() void SetAntiRollBars(const Array& value);
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index f0b6914ae..8339b0f23 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -59,6 +59,7 @@
#if WITH_PVD
#include
#endif
+
// Temporary memory size used by the PhysX during the simulation. Must be multiply of 4kB and 16bit aligned.
#define PHYSX_SCRATCH_BLOCK_SIZE (1024 * 128)
@@ -975,6 +976,7 @@ void PhysicalMaterial::UpdatePhysicsMaterial()
bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& output)
{
+ PROFILE_CPU();
ENSURE_CAN_COOK;
if (input.VertexCount == 0)
LOG(Warning, "Empty mesh data for collision cooking.");
@@ -1018,6 +1020,7 @@ bool CollisionCooking::CookConvexMesh(CookingInput& input, BytesContainer& outpu
bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& output)
{
+ PROFILE_CPU();
ENSURE_CAN_COOK;
if (input.VertexCount == 0 || input.IndexCount == 0)
LOG(Warning, "Empty mesh data for collision cooking.");
@@ -1052,6 +1055,7 @@ bool CollisionCooking::CookTriangleMesh(CookingInput& input, BytesContainer& out
bool CollisionCooking::CookHeightField(int32 cols, int32 rows, const PhysicsBackend::HeightFieldSample* data, WriteStream& stream)
{
+ PROFILE_CPU();
ENSURE_CAN_COOK;
PxHeightFieldDesc heightFieldDesc;
@@ -1444,45 +1448,45 @@ void PhysicsBackend::EndSimulateScene(void* scene)
const float breakThreshold = 8.0f;
const float forwardSpeed = wheelVehicle->GetForwardSpeed();
int currentGear = wheelVehicle->GetCurrentGear();
- // Tank tracks direction: 1 forward -1 backward 0 neutral
+ // Tank tracks direction: 1 forward -1 backward 0 neutral
bool toForward = false;
toForward |= throttle > deadZone;
- toForward |= (leftThrottle > deadZone) && (rightThrottle > deadZone); // 1 1
+ toForward |= (leftThrottle > deadZone) && (rightThrottle > deadZone); // 1 1
bool toBackward = false;
toBackward |= throttle < -deadZone;
- toBackward |= (leftThrottle < -deadZone) && (rightThrottle < -deadZone); // -1 -1
- toBackward |= (leftThrottle < -deadZone) && (rightThrottle < deadZone); // -1 0
- toBackward |= (leftThrottle < deadZone) && (rightThrottle < -deadZone); // 0 -1
+ toBackward |= (leftThrottle < -deadZone) && (rightThrottle < -deadZone); // -1 -1
+ toBackward |= (leftThrottle < -deadZone) && (rightThrottle < deadZone); // -1 0
+ toBackward |= (leftThrottle < deadZone) && (rightThrottle < -deadZone); // 0 -1
bool isTankTurning = false;
if (isTank)
- {
- isTankTurning |= leftThrottle > deadZone && rightThrottle < -deadZone; // 1 -1
- isTankTurning |= leftThrottle < -deadZone && rightThrottle > deadZone; // -1 1
- isTankTurning |= leftThrottle < deadZone && rightThrottle > deadZone; // 0 1
- isTankTurning |= leftThrottle > deadZone && rightThrottle < deadZone; // 1 0
- isTankTurning |= leftThrottle < -deadZone && rightThrottle < deadZone; // -1 0
- isTankTurning |= leftThrottle < deadZone && rightThrottle < -deadZone; // 0 -1
+ {
+ isTankTurning |= leftThrottle > deadZone && rightThrottle < -deadZone; // 1 -1
+ isTankTurning |= leftThrottle < -deadZone && rightThrottle > deadZone; // -1 1
+ isTankTurning |= leftThrottle < deadZone && rightThrottle > deadZone; // 0 1
+ isTankTurning |= leftThrottle > deadZone && rightThrottle < deadZone; // 1 0
+ isTankTurning |= leftThrottle < -deadZone && rightThrottle < deadZone; // -1 0
+ isTankTurning |= leftThrottle < deadZone && rightThrottle < -deadZone; // 0 -1
if (toForward || toBackward)
{
isTankTurning = false;
}
}
-
+
// Automatic gear change when changing driving direction
if (Math::Abs(forwardSpeed) < invalidDirectionThreshold)
{
- int targetGear = wheelVehicle->GetTargetGear();
+ int targetGear = wheelVehicle->GetTargetGear();
if (toBackward && currentGear > 0 && targetGear >= 0)
{
currentGear = -1;
}
else if (!toBackward && currentGear <= 0 && targetGear <= 0)
{
- currentGear = 1;
+ currentGear = 1;
}
else if (isTankTurning && currentGear <= 0)
{
@@ -1565,24 +1569,25 @@ void PhysicsBackend::EndSimulateScene(void* scene)
leftBrake = 1.0f;
}
- // Smooth input controls
+ // Smooth input controls
+ // @formatter:off
PxVehiclePadSmoothingData padSmoothing =
+ {
{
- {
- wheelVehicle->_driveControl.RiseRateAcceleration, // rise rate eANALOG_INPUT_ACCEL
- wheelVehicle->_driveControl.RiseRateBrake, // rise rate eANALOG_INPUT_BRAKE
- wheelVehicle->_driveControl.RiseRateHandBrake, // rise rate eANALOG_INPUT_HANDBRAKE
- wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_LEFT
- wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_RIGHT
- },
- {
- wheelVehicle->_driveControl.FallRateAcceleration, // fall rate eANALOG_INPUT_ACCEL
- wheelVehicle->_driveControl.FallRateBrake, // fall rate eANALOG_INPUT_BRAKE
- wheelVehicle->_driveControl.FallRateHandBrake, // fall rate eANALOG_INPUT_HANDBRAKE
- wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_LEFT
- wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
- }
- };
+ wheelVehicle->_driveControl.RiseRateAcceleration, // rise rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.RiseRateBrake, // rise rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.RiseRateHandBrake, // rise rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.RiseRateSteer, // rise rate eANALOG_INPUT_STEER_RIGHT
+ },
+ {
+ wheelVehicle->_driveControl.FallRateAcceleration, // fall rate eANALOG_INPUT_ACCEL
+ wheelVehicle->_driveControl.FallRateBrake, // fall rate eANALOG_INPUT_BRAKE
+ wheelVehicle->_driveControl.FallRateHandBrake, // fall rate eANALOG_INPUT_HANDBRAKE
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_LEFT
+ wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
+ }
+ };
PxVehicleKeySmoothingData keySmoothing =
{
{
@@ -1600,6 +1605,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
wheelVehicle->_driveControl.FallRateSteer, // fall rate eANALOG_INPUT_STEER_RIGHT
}
};
+ // @formatter:on
// Reduce steer by speed to make vehicle more easier to maneuver
@@ -1659,14 +1665,13 @@ void PhysicsBackend::EndSimulateScene(void* scene)
rawInputData.setAnalogRightBrake(rightBrake);
rawInputData.setAnalogLeftThrust(leftThrottle);
rawInputData.setAnalogRightThrust(rightThrottle);
-
PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank*)drive);
break;
}
}
}
else
- {
+ {
switch (wheelVehicle->_driveTypeCurrent)
{
case WheeledVehicle::DriveTypes::Drive4W:
@@ -1693,7 +1698,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
}
case WheeledVehicle::DriveTypes::Tank:
{
- // Convert analogic inputs to digital inputs.
+ // Convert analog inputs to digital inputs
leftThrottle = Math::Round(leftThrottle);
rightThrottle = Math::Round(rightThrottle);
leftBrake = Math::Round(leftBrake);
@@ -1707,8 +1712,8 @@ void PhysicsBackend::EndSimulateScene(void* scene)
rawInputData.setAnalogLeftThrust(leftThrottle);
rawInputData.setAnalogRightThrust(rightThrottle);
- // Needs to pass analogic values to vehicle to maintein current moviment direction because digital inputs accept only true/false values to tracks thrust instead of -1 to 1
- PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank *)drive);
+ // Needs to pass analog values to vehicle to maintain current movement direction because digital inputs accept only true/false values to tracks thrust instead of -1 to 1
+ PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, rawInputData, scenePhysX->LastDeltaTime, *(PxVehicleDriveTank*)drive);
break;
}
}
@@ -2428,7 +2433,7 @@ void PhysicsBackend::SetRigidActorPose(void* actor, const Vector3& position, con
actorPhysX->setGlobalPose(trans, wakeUp);
}
else
- actorPhysX->setKinematicTarget(trans);
+ actorPhysX->setKinematicTarget(trans);
}
else
{
@@ -2964,7 +2969,7 @@ void PhysicsBackend::SetHingeJointLimit(void* joint, const LimitAngularRange& va
void PhysicsBackend::SetHingeJointDrive(void* joint, const HingeJointDrive& value)
{
auto jointPhysX = (PxRevoluteJoint*)joint;
- jointPhysX->setDriveVelocity(Math::Max(value.Velocity, 0.0f));
+ jointPhysX->setDriveVelocity(value.Velocity);
jointPhysX->setDriveForceLimit(Math::Max(value.ForceLimit, 0.0f));
jointPhysX->setDriveGearRatio(Math::Max(value.GearRatio, 0.0f));
jointPhysX->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, value.FreeSpin);
@@ -3265,7 +3270,6 @@ PxVehicleDifferentialNWData CreatePxVehicleDifferentialNWData(const WheeledVehic
PxVehicleDifferentialNWData differentialNwData;
for (int32 i = 0; i < wheels.Count(); i++)
differentialNwData.setDrivenWheel(i, true);
-
return differentialNwData;
}
@@ -3286,7 +3290,7 @@ PxVehicleGearsData CreatePxVehicleGearsData(const WheeledVehicle::GearboxSetting
PxVehicleGearsData gears;
// Total gears is forward gears + neutral/rear gears
- int gearsAmount = settings.ForwardGearsRatios + 2;
+ const int32 gearsCount = Math::Clamp(settings.ForwardGearsRatios + 2, 2, PxVehicleGearsData::eGEARSRATIO_COUNT);
// Setup gears torque/top speed relations
// Higher torque = less speed
@@ -3302,24 +3306,23 @@ PxVehicleGearsData CreatePxVehicleGearsData(const WheeledVehicle::GearboxSetting
// Gear4 = 1.8
// Gear5 = 1
- gears.mRatios[0] = -(gearsAmount - 2); // reverse
- gears.mRatios[1] = 0; // neutral
+ gears.mRatios[0] = (float)-(gearsCount - 2); // Reverse
+ gears.mRatios[1] = 0; // Neutral
// Setup all gears except neutral and reverse
- for (int i = gearsAmount; i > 2; i--) {
-
- float gearsRatios = settings.ForwardGearsRatios;
- float currentGear = i - 2;
-
- gears.mRatios[i] = Math::Lerp(gearsRatios, 1.0f, (currentGear / gearsRatios));
+ for (int32 i = gearsCount; i > 2; i--)
+ {
+ float gearsRatios = (float)settings.ForwardGearsRatios;
+ float currentGear = i - 2.0f;
+ gears.mRatios[i] = Math::Lerp(gearsRatios, 1.0f, currentGear / gearsRatios);
}
- // reset unused gears
- for (int i = gearsAmount; i < PxVehicleGearsData::eGEARSRATIO_COUNT; i++)
+ // Reset unused gears
+ for (int32 i = gearsCount; i < PxVehicleGearsData::eGEARSRATIO_COUNT; i++)
gears.mRatios[i] = 0;
gears.mSwitchTime = Math::Max(settings.SwitchTime, 0.0f);
- gears.mNbRatios = Math::Clamp(gearsAmount, 2, (int)PxVehicleGearsData::eGEARSRATIO_COUNT);
+ gears.mNbRatios = gearsCount;
return gears;
}
@@ -3388,7 +3391,7 @@ PxVehicleAckermannGeometryData CreatePxVehicleAckermannGeometryData(PxVehicleWhe
return ackermann;
}
-PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle::AntiRollBar& settings, int leftWheelIndex, int rightWheelIndex)
+PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle::AntiRollBar& settings, int32 leftWheelIndex, int32 rightWheelIndex)
{
PxVehicleAntiRollBarData antiRollBar;
antiRollBar.mWheel0 = leftWheelIndex;
@@ -3397,7 +3400,7 @@ PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle::
return antiRollBar;
}
-bool SortWheelsFrontToBack(WheeledVehicle::Wheel const &a, WheeledVehicle::Wheel const &b)
+bool SortWheelsFrontToBack(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
{
return a.Collider && b.Collider && a.Collider->GetLocalPosition().Z > b.Collider->GetLocalPosition().Z;
}
@@ -3412,17 +3415,15 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
{
Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack);
- // sort wheels by side
+ // Sort wheels by side
if (actor->_driveType == WheeledVehicle::DriveTypes::Tank)
{
- for (int i = 0; i < actor->_wheels.Count() - 1; i += 2)
+ for (int32 i = 0; i < actor->_wheels.Count() - 1; i += 2)
{
auto a = actor->_wheels[i];
auto b = actor->_wheels[i + 1];
-
if (!a.Collider || !b.Collider)
continue;
-
if (a.Collider->GetLocalPosition().X > b.Collider->GetLocalPosition().X)
{
actor->_wheels[i] = b;
@@ -3482,7 +3483,7 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
// TODO: get gravityDirection from scenePhysX->Scene->getGravity()
PxVehicleComputeSprungMasses(wheels.Count(), offsets, centerOfMassOffset.p, mass, 1, sprungMasses);
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(wheels.Count());
- int wheelsCount = wheels.Count();
+ int32 wheelsCount = wheels.Count();
for (int32 i = 0; i < wheelsCount; i++)
{
auto& wheel = *wheels[i];
@@ -3498,7 +3499,7 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
const PxVehicleWheelData& wheelData = CreatePxVehicleWheelData(wheel);
const PxVehicleSuspensionData& suspensionData = CreatePxVehicleSuspensionData(wheel, sprungMasses[i]);
- wheelsSimData->setTireData(i,tireData);
+ wheelsSimData->setTireData(i, tireData);
wheelsSimData->setWheelData(i, wheelData);
wheelsSimData->setSuspensionData(i, suspensionData);
wheelsSimData->setSuspTravelDirection(i, centerOfMassOffset.rotate(PxVec3(0.0f, -1.0f, 0.0f)));
@@ -3530,16 +3531,15 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
}
}
// Add Anti roll bars for wheels axles
- for (int i = 0; i < actor->GetAntiRollBars().Count(); i++)
+ for (int32 i = 0; i < actor->GetAntiRollBars().Count(); i++)
{
- int axleIndex = actor->GetAntiRollBars()[i].Axle;
- int leftWheelIndex = axleIndex * 2;
- int rightWheelIndex = leftWheelIndex + 1;
-
+ int32 axleIndex = actor->GetAntiRollBars()[i].Axle;
+ int32 leftWheelIndex = axleIndex * 2;
+ int32 rightWheelIndex = leftWheelIndex + 1;
if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
continue;
- const PxVehicleAntiRollBarData &antiRollBar = CreatePxPxVehicleAntiRollBarData(actor->GetAntiRollBars()[i], leftWheelIndex, rightWheelIndex);
+ const PxVehicleAntiRollBarData& antiRollBar = CreatePxPxVehicleAntiRollBarData(actor->GetAntiRollBars()[i], leftWheelIndex, rightWheelIndex);
wheelsSimData->addAntiRollBarData(antiRollBar);
}
for (auto child : actor->Children)
@@ -3582,14 +3582,14 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox);
const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
- const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
driveSimData.setDiffData(differentialData);
driveSimData.setEngineData(engineData);
driveSimData.setGearsData(gearsData);
driveSimData.setAutoBoxData(autoBoxData);
- driveSimData.setClutchData(cluchData);
+ driveSimData.setClutchData(clutchData);
driveSimData.setAckermannGeometryData(geometryData);
// Create vehicle drive
@@ -3607,14 +3607,13 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox);
const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
- const PxVehicleClutchData& cluchData = CreatePxVehicleClutchData(gearbox);
- const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
driveSimData.setDiffData(differentialData);
driveSimData.setEngineData(engineData);
driveSimData.setGearsData(gearsData);
driveSimData.setAutoBoxData(autoBoxData);
- driveSimData.setClutchData(cluchData);
+ driveSimData.setClutchData(clutchData);
// Create vehicle drive
auto driveNW = PxVehicleDriveNW::allocate(wheels.Count());
@@ -3635,18 +3634,18 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
case WheeledVehicle::DriveTypes::Tank:
{
PxVehicleDriveSimData4W driveSimData;
- const PxVehicleDifferential4WData &differentialData = CreatePxVehicleDifferential4WData(differential);
- const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine);
- const PxVehicleGearsData &gearsData = CreatePxVehicleGearsData(gearbox);
- const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData();
- const PxVehicleClutchData &cluchData = CreatePxVehicleClutchData(gearbox);
- const PxVehicleAckermannGeometryData &geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
+ const PxVehicleDifferential4WData& differentialData = CreatePxVehicleDifferential4WData(differential);
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
+ const PxVehicleGearsData& gearsData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAckermannGeometryData& geometryData = CreatePxVehicleAckermannGeometryData(wheelsSimData);
driveSimData.setDiffData(differentialData);
driveSimData.setEngineData(engineData);
driveSimData.setGearsData(gearsData);
driveSimData.setAutoBoxData(autoBoxData);
- driveSimData.setClutchData(cluchData);
+ driveSimData.setClutchData(clutchData);
driveSimData.setAckermannGeometryData(geometryData);
// Create vehicle drive
@@ -3700,24 +3699,24 @@ void PhysicsBackend::UpdateVehicleWheels(WheeledVehicle* actor)
}
}
-void PhysicsBackend::UpdateVehicleAntiRollBars(WheeledVehicle *actor)
+void PhysicsBackend::UpdateVehicleAntiRollBars(WheeledVehicle* actor)
{
int wheelsCount = actor->_wheels.Count();
- auto drive = (PxVehicleWheels *)actor->_vehicle;
- PxVehicleWheelsSimData *wheelsSimData = &drive->mWheelsSimData;
+ auto drive = (PxVehicleWheels*)actor->_vehicle;
+ PxVehicleWheelsSimData* wheelsSimData = &drive->mWheelsSimData;
- // Update Anti roll bars for wheels axles
- for (int i = 0; i < actor->GetAntiRollBars().Count(); i++)
+ // Update anti roll bars for wheels axles
+ const auto& antiRollBars = actor->GetAntiRollBars();
+ for (int32 i = 0; i < antiRollBars.Count(); i++)
{
- int axleIndex = actor->GetAntiRollBars()[i].Axle;
- int leftWheelIndex = axleIndex * 2;
- int rightWheelIndex = leftWheelIndex + 1;
-
+ const int32 axleIndex = antiRollBars.Get()[i].Axle;
+ const int32 leftWheelIndex = axleIndex * 2;
+ const int32 rightWheelIndex = leftWheelIndex + 1;
if (leftWheelIndex >= wheelsCount || rightWheelIndex >= wheelsCount)
continue;
- const PxVehicleAntiRollBarData &antiRollBar = CreatePxPxVehicleAntiRollBarData(actor->GetAntiRollBars()[i], leftWheelIndex, rightWheelIndex);
- if (wheelsSimData->getNbAntiRollBarData() - 1 < i)
+ const PxVehicleAntiRollBarData& antiRollBar = CreatePxPxVehicleAntiRollBarData(antiRollBars.Get()[i], leftWheelIndex, rightWheelIndex);
+ if ((int32)wheelsSimData->getNbAntiRollBarData() - 1 < i)
{
wheelsSimData->addAntiRollBarData(antiRollBar);
}
@@ -3753,8 +3752,8 @@ void PhysicsBackend::SetVehicleEngine(void* vehicle, const void* value)
case PxVehicleTypes::eDRIVETANK:
{
auto driveTank = (PxVehicleDriveTank*)drive;
- const PxVehicleEngineData &engineData = CreatePxVehicleEngineData(engine);
- PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData;
+ const PxVehicleEngineData& engineData = CreatePxVehicleEngineData(engine);
+ PxVehicleDriveSimData& driveSimData = driveTank->mDriveSimData;
driveSimData.setEngineData(engineData);
break;
}
@@ -3812,11 +3811,11 @@ void PhysicsBackend::SetVehicleGearbox(void* vehicle, const void* value)
}
case PxVehicleTypes::eDRIVETANK:
{
- auto driveTank = (PxVehicleDriveTank *)drive;
- const PxVehicleGearsData &gearData = CreatePxVehicleGearsData(gearbox);
- const PxVehicleClutchData &clutchData = CreatePxVehicleClutchData(gearbox);
- const PxVehicleAutoBoxData &autoBoxData = CreatePxVehicleAutoBoxData();
- PxVehicleDriveSimData &driveSimData = driveTank->mDriveSimData;
+ auto driveTank = (PxVehicleDriveTank*)drive;
+ const PxVehicleGearsData& gearData = CreatePxVehicleGearsData(gearbox);
+ const PxVehicleClutchData& clutchData = CreatePxVehicleClutchData(gearbox);
+ const PxVehicleAutoBoxData& autoBoxData = CreatePxVehicleAutoBoxData();
+ PxVehicleDriveSimData& driveSimData = driveTank->mDriveSimData;
driveSimData.setGearsData(gearData);
driveSimData.setAutoBoxData(autoBoxData);
driveSimData.setClutchData(clutchData);
From 01d123b09988edc6332a6f7f3dc93ddc03977184 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Fri, 23 Feb 2024 17:46:27 +0100
Subject: [PATCH 62/79] Add support for importing material emissive and
roughness from `fbx` file
#2153
---
.../ContentImporters/CreateMaterial.cpp | 130 ++++++++----------
.../Engine/ContentImporters/CreateMaterial.h | 6 +
Source/Engine/Core/Math/Color.h | 7 +-
Source/Engine/Graphics/Models/ModelData.cpp | 12 ++
Source/Engine/Graphics/Models/ModelData.h | 7 +
.../Tools/ModelTool/ModelTool.OpenFBX.cpp | 2 +
Source/Engine/Tools/ModelTool/ModelTool.cpp | 3 +
7 files changed, 91 insertions(+), 76 deletions(-)
diff --git a/Source/Engine/ContentImporters/CreateMaterial.cpp b/Source/Engine/ContentImporters/CreateMaterial.cpp
index fb16b89ee..9d9af4b38 100644
--- a/Source/Engine/ContentImporters/CreateMaterial.cpp
+++ b/Source/Engine/ContentImporters/CreateMaterial.cpp
@@ -12,9 +12,13 @@
#include "Engine/Tools/MaterialGenerator/MaterialGenerator.h"
#include "Engine/Serialization/MemoryWriteStream.h"
+#define SET_POS(node, pos) meta.Position = pos; node->Meta.AddEntry(11, (byte*)&meta, sizeof(meta));
+#define CONNECT(boxA, boxB) boxA.Connections.Add(&boxB); boxB.Connections.Add(&boxA)
+
namespace
{
- ShaderGraphNode<>* AddFloatValue(MaterialLayer* layer, const float& value, const float& defaultValue)
+ template
+ ShaderGraphNode<>* AddValueNode(MaterialLayer* layer, const float& value, const float& defaultValue)
{
if (Math::NearEqual(value, defaultValue))
return nullptr;
@@ -28,7 +32,8 @@ namespace
return &node;
}
- ShaderGraphNode<>* AddColorNode(MaterialLayer* layer, const Color& value, const Color& defaultValue)
+ template
+ ShaderGraphNode<>* AddValueNode(MaterialLayer* layer, const Color& value, const Color& defaultValue)
{
if (value == defaultValue)
return nullptr;
@@ -86,6 +91,35 @@ namespace
Float2 Position;
bool Selected;
};
+
+ template
+ void AddInput(MaterialLayer* layer, Meta11 meta, MaterialGraphBoxes box, const Guid& texture, const T& value, const T& defaultValue, const Float2& pos, ShaderGraphNode<>** outTextureNode = nullptr)
+ {
+ auto textureNode = AddTextureNode(layer, texture);
+ auto valueNode = AddValueNode(layer, value, defaultValue);
+ if (textureNode && valueNode)
+ {
+ auto diffuseMultiply = AddMultiplyNode(layer);
+ CONNECT(diffuseMultiply->Boxes[0], textureNode->Boxes[1]);
+ CONNECT(diffuseMultiply->Boxes[1], valueNode->Boxes[0]);
+ CONNECT(layer->Root->Boxes[static_cast(box)], diffuseMultiply->Boxes[2]);
+ SET_POS(valueNode, pos + Float2(-467.7404, 91.41332));
+ SET_POS(textureNode, pos + Float2(-538.096, -103.9724));
+ SET_POS(diffuseMultiply, pos + Float2(-293.5272f, -2.926111f));
+ }
+ else if (textureNode)
+ {
+ CONNECT(layer->Root->Boxes[static_cast(box)], textureNode->Boxes[1]);
+ SET_POS(textureNode, pos + Float2(-293.5272f, -2.926111f));
+ }
+ else if (valueNode)
+ {
+ CONNECT(layer->Root->Boxes[static_cast(box)], valueNode->Boxes[0]);
+ SET_POS(valueNode, pos + Float2(-293.5272f, -2.926111f));
+ }
+ if (outTextureNode)
+ *outTextureNode = textureNode;
+ }
}
CreateMaterial::Options::Options()
@@ -129,85 +163,32 @@ CreateAssetResult CreateMaterial::Create(CreateAssetContext& context)
box.Parent = layer->Root;
Meta11 meta;
meta.Selected = false;
-#define SET_POS(node, pos) meta.Position = pos; node->Meta.AddEntry(11, (byte*)&meta, sizeof(meta));
-#define CONNECT(boxA, boxB) boxA.Connections.Add(&boxB); boxB.Connections.Add(&boxA)
- auto diffuseTexture = AddTextureNode(layer, options.Diffuse.Texture);
- auto diffuseColor = AddColorNode(layer, options.Diffuse.Color, Color::White);
- if (diffuseTexture && diffuseColor)
+
+ // Diffuse + Mask
+ ShaderGraphNode<>* diffuseTextureNode;
+ AddInput(layer, meta, MaterialGraphBoxes::Color, options.Diffuse.Texture, options.Diffuse.Color, Color::White, Float2::Zero, &diffuseTextureNode);
+ if (diffuseTextureNode && options.Diffuse.HasAlphaMask)
{
- auto diffuseMultiply = AddMultiplyNode(layer);
- CONNECT(diffuseMultiply->Boxes[0], diffuseTexture->Boxes[1]);
- CONNECT(diffuseMultiply->Boxes[1], diffuseColor->Boxes[0]);
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Color)], diffuseMultiply->Boxes[2]);
- SET_POS(diffuseColor, Float2(-467.7404, 91.41332));
- SET_POS(diffuseTexture, Float2(-538.096, -103.9724));
- SET_POS(diffuseMultiply, Float2(-293.5272f, -2.926111f));
- }
- else if (diffuseTexture)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Color)], diffuseTexture->Boxes[1]);
- SET_POS(diffuseTexture, Float2(-293.5272f, -2.926111f));
- }
- else if (diffuseColor)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Color)], diffuseColor->Boxes[0]);
- SET_POS(diffuseColor, Float2(-293.5272f, -2.926111f));
- }
- if (diffuseTexture && options.Diffuse.HasAlphaMask)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Mask)], diffuseTexture->Boxes[5]);
- }
- auto emissiveTexture = AddTextureNode(layer, options.Emissive.Texture);
- auto emissiveColor = AddColorNode(layer, options.Emissive.Color, Color::Transparent);
- if (emissiveTexture && emissiveColor)
- {
- auto emissiveMultiply = AddMultiplyNode(layer);
- CONNECT(emissiveMultiply->Boxes[0], emissiveTexture->Boxes[1]);
- CONNECT(emissiveMultiply->Boxes[1], emissiveColor->Boxes[0]);
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Emissive)], emissiveMultiply->Boxes[2]);
- SET_POS(emissiveTexture, Float2(-667.7404, 91.41332));
- SET_POS(emissiveTexture, Float2(-738.096, -103.9724));
- SET_POS(emissiveMultiply, Float2(-493.5272f, -2.926111f));
- }
- else if (emissiveTexture)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Emissive)], emissiveTexture->Boxes[1]);
- SET_POS(emissiveTexture, Float2(-493.5272f, -2.926111f));
- }
- else if (emissiveColor)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Emissive)], emissiveColor->Boxes[0]);
- SET_POS(emissiveColor, Float2(-493.5272f, -2.926111f));
+ CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Mask)], diffuseTextureNode->Boxes[5]);
}
+
+ // Emissive
+ AddInput(layer, meta, MaterialGraphBoxes::Emissive, options.Emissive.Texture, options.Emissive.Color, Color::Transparent, Float2(0, 200));
+
+ // Opacity
+ AddInput(layer, meta, MaterialGraphBoxes::Opacity, options.Opacity.Texture, options.Opacity.Value, 1.0f, Float2(0, 400));
+
+ // Opacity
+ AddInput(layer, meta, MaterialGraphBoxes::Roughness, options.Roughness.Texture, options.Roughness.Value, 0.5f, Float2(200, 400));
+
+ // Normal
auto normalMap = AddTextureNode(layer, options.Normals.Texture, true);
if (normalMap)
{
CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Normal)], normalMap->Boxes[1]);
SET_POS(normalMap, Float2(-893.5272f, -200.926111f));
}
- auto opacityTexture = AddTextureNode(layer, options.Opacity.Texture);
- auto opacityValue = AddFloatValue(layer, options.Opacity.Value, 1.0f);
- if (opacityTexture && opacityValue)
- {
- auto opacityMultiply = AddMultiplyNode(layer);
- CONNECT(opacityMultiply->Boxes[0], opacityTexture->Boxes[1]);
- CONNECT(opacityMultiply->Boxes[1], opacityValue->Boxes[0]);
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Opacity)], opacityMultiply->Boxes[2]);
- SET_POS(opacityTexture, Float2(-867.7404, 91.41332));
- SET_POS(opacityTexture, Float2(-938.096, -103.9724));
- SET_POS(opacityMultiply, Float2(-693.5272f, -2.926111f));
- }
- else if (opacityTexture)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Opacity)], opacityTexture->Boxes[1]);
- SET_POS(opacityTexture, Float2(-693.5272f, -2.926111f));
- }
- else if (opacityValue)
- {
- CONNECT(layer->Root->Boxes[static_cast(MaterialGraphBoxes::Opacity)], opacityValue->Boxes[0]);
- SET_POS(opacityValue, Float2(-693.5272f, -2.926111f));
- }
-#undef CONNECT
+
MemoryWriteStream stream(512);
layer->Graph.Save(&stream, true);
context.Data.Header.Chunks[SHADER_FILE_CHUNK_VISJECT_SURFACE]->Data.Copy(stream.GetHandle(), stream.GetPosition());
@@ -224,4 +205,7 @@ CreateAssetResult CreateMaterial::Create(CreateAssetContext& context)
return CreateAssetResult::Ok;
}
+#undef CONNECT
+#undef SET_POS
+
#endif
diff --git a/Source/Engine/ContentImporters/CreateMaterial.h b/Source/Engine/ContentImporters/CreateMaterial.h
index 3f6a2ff7f..27de5721f 100644
--- a/Source/Engine/ContentImporters/CreateMaterial.h
+++ b/Source/Engine/ContentImporters/CreateMaterial.h
@@ -37,6 +37,12 @@ public:
Guid Texture = Guid::Empty;
} Opacity;
+ struct
+ {
+ float Value = 0.5f;
+ Guid Texture = Guid::Empty;
+ } Roughness;
+
struct
{
Guid Texture = Guid::Empty;
diff --git a/Source/Engine/Core/Math/Color.h b/Source/Engine/Core/Math/Color.h
index 836ead090..5d177ee2c 100644
--- a/Source/Engine/Core/Math/Color.h
+++ b/Source/Engine/Core/Math/Color.h
@@ -237,9 +237,10 @@ public:
Color& operator*=(const float b)
{
- R = Math::Saturate(R * b);
- G = Math::Saturate(G * b);
- B = Math::Saturate(B * b);
+ R = R * b;
+ G = G * b;
+ B = B * b;
+ A = A * b;
return *this;
}
diff --git a/Source/Engine/Graphics/Models/ModelData.cpp b/Source/Engine/Graphics/Models/ModelData.cpp
index cc95ed6ba..21905a9ae 100644
--- a/Source/Engine/Graphics/Models/ModelData.cpp
+++ b/Source/Engine/Graphics/Models/ModelData.cpp
@@ -622,9 +622,21 @@ bool MaterialSlotEntry::UsesProperties() const
Emissive.TextureIndex != -1 ||
!Math::IsOne(Opacity.Value) ||
Opacity.TextureIndex != -1 ||
+ Math::NotNearEqual(Roughness.Value, 0.5f) ||
+ Roughness.TextureIndex != -1 ||
Normals.TextureIndex != -1;
}
+float MaterialSlotEntry::ShininessToRoughness(float shininess)
+{
+ // https://github.com/assimp/assimp/issues/4573
+ const float a = -1.0f;
+ const float b = 2.0f;
+ const float c = (shininess / 100) - 1;
+ const float d = b * b - (4 * a * c);
+ return (-b + Math::Sqrt(d)) / (2 * a);
+}
+
ModelLodData::~ModelLodData()
{
Meshes.ClearDelete();
diff --git a/Source/Engine/Graphics/Models/ModelData.h b/Source/Engine/Graphics/Models/ModelData.h
index 65bedf876..f0a0eb3dd 100644
--- a/Source/Engine/Graphics/Models/ModelData.h
+++ b/Source/Engine/Graphics/Models/ModelData.h
@@ -356,6 +356,12 @@ struct FLAXENGINE_API MaterialSlotEntry
int32 TextureIndex = -1;
} Opacity;
+ struct
+ {
+ float Value = 0.5f;
+ int32 TextureIndex = -1;
+ } Roughness;
+
struct
{
int32 TextureIndex = -1;
@@ -364,6 +370,7 @@ struct FLAXENGINE_API MaterialSlotEntry
bool TwoSided = false;
bool UsesProperties() const;
+ static float ShininessToRoughness(float shininess);
};
///
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
index 5c72d963f..8ec8bcbc7 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp
@@ -232,6 +232,8 @@ struct OpenFbxImporterData
if (mat && EnumHasAnyFlags(Options.ImportTypes, ImportDataTypes::Materials))
{
material.Diffuse.Color = ToColor(mat->getDiffuseColor());
+ material.Emissive.Color = ToColor(mat->getEmissiveColor()) * (float)mat->getEmissiveFactor();
+ material.Roughness.Value = MaterialSlotEntry::ShininessToRoughness((float)mat->getShininess());
if (EnumHasAnyFlags(Options.ImportTypes, ImportDataTypes::Textures))
{
diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp
index 74cbfbb52..97789421d 100644
--- a/Source/Engine/Tools/ModelTool/ModelTool.cpp
+++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp
@@ -1219,6 +1219,9 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
materialOptions.Opacity.Value = material.Opacity.Value;
if (material.Opacity.TextureIndex != -1)
materialOptions.Opacity.Texture = data.Textures[material.Opacity.TextureIndex].AssetID;
+ materialOptions.Roughness.Value = material.Roughness.Value;
+ if (material.Roughness.TextureIndex != -1)
+ materialOptions.Roughness.Texture = data.Textures[material.Roughness.TextureIndex].AssetID;
if (material.Normals.TextureIndex != -1)
materialOptions.Normals.Texture = data.Textures[material.Normals.TextureIndex].AssetID;
if (material.TwoSided || material.Diffuse.HasAlphaMask)
From eb12c630a775a0efb3f0917d892dc3998e0ed5ec Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Fri, 23 Feb 2024 19:27:50 +0100
Subject: [PATCH 63/79] Fix incorrect vehicle wheels collisions inside trigger
volumes
#2132
---
.../Physics/PhysX/PhysicsBackendPhysX.cpp | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 8339b0f23..86eb71991 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -382,17 +382,17 @@ public:
return PxQueryHitType::eNONE;
const PxFilterData shapeFilter = shape->getQueryFilterData();
+ // Let triggers through
+ if (shape->getFlags() & PxShapeFlag::eTRIGGER_SHAPE)
+ return PxQueryHitType::eNONE;
+
// Hardcoded id for vehicle shapes masking
if (filterData.word3 == shapeFilter.word3)
- {
return PxQueryHitType::eNONE;
- }
// Collide for pairs (A,B) where the filtermask of A contains the ID of B and vice versa
if ((filterData.word0 & shapeFilter.word1) && (shapeFilter.word0 & filterData.word1))
- {
return PxQueryHitType::eBLOCK;
- }
return PxQueryHitType::eNONE;
}
@@ -1410,7 +1410,6 @@ void PhysicsBackend::EndSimulateScene(void* scene)
float rightThrottle = wheelVehicle->_tankRightThrottle;
float leftBrake = Math::Max(wheelVehicle->_tankLeftBrake, wheelVehicle->_handBrake);
float rightBrake = Math::Max(wheelVehicle->_tankRightBrake, wheelVehicle->_handBrake);
-
WheeledVehicle::DriveModes vehicleDriveMode = wheelVehicle->_driveControl.DriveMode;
if (isTank)
@@ -1559,7 +1558,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
throttle = Math::Max(throttle, 0.0f);
}
- // Force brake the another side track to turn more faster.
+ // Force brake the another side track to turn faster
if (Math::Abs(leftThrottle) > deadZone && Math::Abs(rightThrottle) < deadZone)
{
rightBrake = 1.0f;
@@ -1607,8 +1606,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
};
// @formatter:on
- // Reduce steer by speed to make vehicle more easier to maneuver
-
+ // Reduce steer by speed to make vehicle easier to maneuver
constexpr int steerVsSpeedN = 8;
PxF32 steerVsForwardSpeedData[steerVsSpeedN];
const int lastSteerVsSpeedIndex = wheelVehicle->_driveControl.SteerVsSpeed.Count() - 1;
@@ -1623,7 +1621,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
// ..
// fill the steerVsForwardSpeedData with the speed and steer
- for (int i = 0; i < 8; i += 2)
+ for (int32 i = 0; i < 8; i += 2)
{
steerVsForwardSpeedData[i] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Speed;
steerVsForwardSpeedData[i + 1] = wheelVehicle->_driveControl.SteerVsSpeed[steerVsSpeedIndex].Steer;
@@ -1631,7 +1629,6 @@ void PhysicsBackend::EndSimulateScene(void* scene)
}
const PxFixedSizeLookupTable steerVsForwardSpeed(steerVsForwardSpeedData, 4);
- // @formatter:on
if (wheelVehicle->UseAnalogSteering)
{
switch (wheelVehicle->_driveTypeCurrent)
From ee4fc7c2017e379200d1a0a6a0fcb416a0faa125 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Fri, 23 Feb 2024 19:39:41 +0100
Subject: [PATCH 64/79] Fix cloth editing undo in Prefab viewport
#2136
---
Source/Editor/Tools/ClothPainting.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Source/Editor/Tools/ClothPainting.cs b/Source/Editor/Tools/ClothPainting.cs
index 6a98a3b5f..3a39b30ab 100644
--- a/Source/Editor/Tools/ClothPainting.cs
+++ b/Source/Editor/Tools/ClothPainting.cs
@@ -154,7 +154,7 @@ namespace FlaxEngine.Tools
if (IsPainting)
return;
- if (Editor.Instance.Undo.Enabled)
+ if (Owner.Undo.Enabled)
_undoAction = new EditClothPaintAction(_cloth);
_isPainting = true;
_paintUpdateCount = 0;
@@ -221,7 +221,7 @@ namespace FlaxEngine.Tools
if (_undoAction != null)
{
_undoAction.RecordEnd();
- Editor.Instance.Undo.AddAction(_undoAction);
+ Owner.Undo.AddAction(_undoAction);
_undoAction = null;
}
_isPainting = false;
From 696437d6d0226a5896468fea9a89f328b3536702 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Fri, 23 Feb 2024 19:56:32 +0100
Subject: [PATCH 65/79] Cleanup codestyle #2079
---
Source/Engine/Platform/Linux/LinuxFileSystem.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
index 98c11963b..7af947260 100644
--- a/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
+++ b/Source/Engine/Platform/Linux/LinuxFileSystem.cpp
@@ -434,7 +434,6 @@ bool LinuxFileSystem::MoveFile(const StringView& dst, const StringView& src, boo
return false;
}
}
- LOG(Error, "Cannot copy {} to {}", src, dst);
return true;
}
return false;
@@ -544,12 +543,11 @@ bool LinuxFileSystem::MoveFileToRecycleBin(const StringView& path)
if (!MoveFile(dst, path, true))
{
- // not MoveFile means success so write the info file
+ // Not MoveFile means success so write the info file
const String infoFile = infoDir / trashName + TEXT(".trashinfo");
StringBuilder trashInfo;
const char *ansiPath = path.ToStringAnsi().Get();
- // in the worst case the length will be tripled
- const int maxLength = strlen(ansiPath) * 3 + 1;
+ const int maxLength = strlen(ansiPath) * 3 + 1; // in the worst case the length will be tripled
char encoded[maxLength];
if (!UrnEncodePath(ansiPath, encoded, maxLength))
{
@@ -557,8 +555,7 @@ bool LinuxFileSystem::MoveFileToRecycleBin(const StringView& path)
strcpy(encoded, ansiPath);
}
const DateTime now = DateTime::Now();
- const String rfcDate = String::Format(TEXT("{0}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}"),
- now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
+ const String rfcDate = String::Format(TEXT("{0}-{1:0>2}-{2:0>2}T{3:0>2}:{4:0>2}:{5:0>2}"), now.GetYear(), now.GetMonth(), now.GetDay(), now.GetHour(), now.GetMinute(), now.GetSecond());
trashInfo.AppendLine(TEXT("[Trash Info]")).Append(TEXT("Path=")).Append(encoded).Append(TEXT('\n'));
trashInfo.Append(TEXT("DeletionDate=")).Append(rfcDate).Append(TEXT("\n\0"));
From 8bcf4fdaf0f6235ce85582fb3f99122918538f65 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sat, 24 Feb 2024 12:53:33 +0100
Subject: [PATCH 66/79] Cleanup and improve #2045
---
Source/Editor/Gizmo/IGizmoOwner.cs | 5 +
Source/Editor/Gizmo/TransformGizmo.cs | 6 +
.../Editor/Gizmo/TransformGizmoBase.Draw.cs | 263 +++++----
.../Gizmo/TransformGizmoBase.Selection.cs | 9 +-
.../Editor/Gizmo/TransformGizmoBase.Types.cs | 6 +-
Source/Editor/Gizmo/TransformGizmoBase.cs | 504 +++++++++---------
Source/Editor/Options/InputOptions.cs | 4 +
.../Editor/SceneGraph/Actors/BoxBrushNode.cs | 6 +-
.../Editor/SceneGraph/Actors/BoxVolumeNode.cs | 6 +-
.../Editor/SceneGraph/Actors/FoliageNode.cs | 67 ++-
.../Editor/SceneGraph/Actors/NavLinkNode.cs | 8 +-
Source/Editor/SceneGraph/SceneGraphNode.cs | 81 ++-
.../Editor/Tools/Foliage/EditFoliageGizmo.cs | 15 +-
Source/Editor/Viewport/EditorGizmoViewport.cs | 3 +
.../Editor/Viewport/PrefabWindowViewport.cs | 3 +
15 files changed, 507 insertions(+), 479 deletions(-)
diff --git a/Source/Editor/Gizmo/IGizmoOwner.cs b/Source/Editor/Gizmo/IGizmoOwner.cs
index 3ab0a917b..af3043fd6 100644
--- a/Source/Editor/Gizmo/IGizmoOwner.cs
+++ b/Source/Editor/Gizmo/IGizmoOwner.cs
@@ -51,6 +51,11 @@ namespace FlaxEditor.Gizmo
///
bool SnapToGround { get; }
+ ///
+ /// Gets a value indicating whether to use vertex snapping (check if user pressed the given input key to call action).
+ ///
+ bool SnapToVertex { get; }
+
///
/// Gets the view forward direction.
///
diff --git a/Source/Editor/Gizmo/TransformGizmo.cs b/Source/Editor/Gizmo/TransformGizmo.cs
index 96584caa7..c000f4a30 100644
--- a/Source/Editor/Gizmo/TransformGizmo.cs
+++ b/Source/Editor/Gizmo/TransformGizmo.cs
@@ -274,6 +274,12 @@ namespace FlaxEditor.Gizmo
return _selectionParents[index];
}
+ ///
+ protected override Transform GetSelectedTransform(int index)
+ {
+ return _selectionParents[index].Transform;
+ }
+
///
protected override void GetSelectedObjectsBounds(out BoundingBox bounds, out bool navigationDirty)
{
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
index 33521a084..cb7a7600c 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs
@@ -72,7 +72,6 @@ namespace FlaxEditor.Gizmo
const float gizmoModelsScale2RealGizmoSize = 0.075f;
Mesh sphereMesh, cubeMesh;
- cubeMesh = _modelCube.LODs[0].Meshes[0];
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
Matrix.Multiply(ref m3, ref world, out m1);
@@ -81,129 +80,135 @@ namespace FlaxEditor.Gizmo
switch (_activeMode)
{
- case Mode.Translate:
- {
- if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
-
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
-
- // X axis
- Matrix.RotationY(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // Y axis
- Matrix.RotationX(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Z axis
- Matrix.RotationX(Mathf.Pi, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // XY plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // ZX plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // YZ plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Center sphere
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
-
- break;
- }
-
- case Mode.Rotate:
- {
- if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
-
- // X axis
- Matrix.RotationZ(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // Y axis
- rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
-
- // Z axis
- Matrix.RotationX(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // Center box
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
-
- break;
- }
-
- case Mode.Scale:
- {
- if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
- break;
- var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
- cubeMesh = _modelCube.LODs[0].Meshes[0];
- sphereMesh = _modelSphere.LODs[0].Meshes[0];
-
- // X axis
- Matrix.RotationY(-Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref mx1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // Y axis
- Matrix.RotationX(Mathf.PiOverTwo, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Z axis
- Matrix.RotationX(Mathf.Pi, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // XY plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
-
- // ZX plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
-
- // YZ plane
- m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
- Matrix.Multiply(ref m2, ref m1, out m3);
- cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
-
- // Center box
- Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
- Matrix.Multiply(ref m2, ref m1, out m3);
- sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
-
- break;
- }
- }
- if (verts != null && selectedvert != -1)
+ case Mode.Translate:
{
- Transform t = thisTransform;
+ if (!_modelTranslationAxis || !_modelTranslationAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var transAxisMesh = _modelTranslationAxis.LODs[0].Meshes[0];
+ cubeMesh = _modelCube.LODs[0].Meshes[0];
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
+
+ // X axis
+ Matrix.RotationY(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // Y axis
+ Matrix.RotationX(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Z axis
+ Matrix.RotationX(Mathf.Pi, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // XY plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // ZX plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // YZ plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Center sphere
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
+
+ case Mode.Rotate:
+ {
+ if (!_modelRotationAxis || !_modelRotationAxis.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var rotationAxisMesh = _modelRotationAxis.LODs[0].Meshes[0];
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
+
+ // X axis
+ Matrix.RotationZ(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // Y axis
+ rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
+
+ // Z axis
+ Matrix.RotationX(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // Center box
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
+
+ case Mode.Scale:
+ {
+ if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelCube || !_modelCube.IsLoaded || !_modelSphere || !_modelSphere.IsLoaded)
+ break;
+ var scaleAxisMesh = _modelScaleAxis.LODs[0].Meshes[0];
+ cubeMesh = _modelCube.LODs[0].Meshes[0];
+ sphereMesh = _modelSphere.LODs[0].Meshes[0];
+
+ // X axis
+ Matrix.RotationY(-Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref mx1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // Y axis
+ Matrix.RotationX(Mathf.PiOverTwo, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Z axis
+ Matrix.RotationX(Mathf.Pi, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // XY plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
+
+ // ZX plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
+
+ // YZ plane
+ m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
+
+ // Center box
+ Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
+ Matrix.Multiply(ref m2, ref m1, out m3);
+ sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
+
+ break;
+ }
+ }
+
+ // Vertex snapping
+ if (verts != null && SelectedModel != null && selectedvert != -1)
+ {
+ if (!_modelCube || !_modelCube.IsLoaded)
+ return;
+ cubeMesh = _modelCube.LODs[0].Meshes[0];
+
+ Transform t = SelectedModel.Transform;
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
Matrix matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
@@ -211,21 +216,9 @@ namespace FlaxEditor.Gizmo
if (otherVerts != null && otherSelectedvert != -1)
{
t = otherTransform;
- Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
matrix = new Transform(selected, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
- DebugDraw.DrawLine(other, selected, Color.Aqua);
}
-
- //t = otherTransform;
- //for (int i = 0; i < otherVerts.Length; i++)
- //{
- // Matrix matrix = new Transform(((otherVerts[i].Position * t.Orientation) * t.Scale) + t.Translation, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
- // cubeMesh.Draw(ref renderContext, i == otherSelectedvert ? _materialAxisFocus : _materialSphere, ref matrix);
- //}
-
- //t = GetSelectedObject(0).Transform;
-
}
}
}
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
index 1ebe0f254..2b9eae7b9 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs
@@ -27,7 +27,7 @@ namespace FlaxEditor.Gizmo
// Get center point
Vector3 center = Vector3.Zero;
for (int i = 0; i < count; i++)
- center += GetSelectedObject(i).Transform.Translation;
+ center += GetSelectedTransform(i).Translation;
// Return arithmetic average or whatever it means
return center / count;
@@ -36,22 +36,15 @@ namespace FlaxEditor.Gizmo
private bool IntersectsRotateCircle(Vector3 normal, ref Ray ray, out Real distance)
{
var plane = new Plane(Vector3.Zero, normal);
-
if (!plane.Intersects(ref ray, out distance))
return false;
Vector3 hitPoint = ray.Position + ray.Direction * distance;
-
Real distanceNormalized = hitPoint.Length / RotateRadiusRaw;
return Mathf.IsInRange(distanceNormalized, 0.9f, 1.1f);
}
private void SelectAxis()
{
- if (Owner.IsControlDown)
- {
-
- }
-
// Get mouse ray
Ray ray = Owner.MouseRay;
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Types.cs b/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
index d622a8fcf..66acb4c2b 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.Types.cs
@@ -32,17 +32,17 @@ namespace FlaxEditor.Gizmo
///
/// The XY plane.
///
- XY = X|Y,
+ XY = X | Y,
///
/// The ZX plane.
///
- ZX = Z|X,
+ ZX = Z | X,
///
/// The YZ plane.
///
- YZ = Y|Z,
+ YZ = Y | Z,
///
/// The center point.
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs
index ddd3272ee..3e788d28f 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.cs
@@ -10,7 +10,6 @@ using System;
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEngine;
-using FlaxEditor.Surface;
namespace FlaxEditor.Gizmo
{
@@ -54,6 +53,15 @@ namespace FlaxEditor.Gizmo
private Vector3 _translationDelta;
private Vector3 _translationScaleSnapDelta;
+ //vertex snaping stff
+ private Mesh.Vertex[] verts;
+ private Mesh.Vertex[] otherVerts;
+ private Transform otherTransform;
+ private StaticModel SelectedModel;
+ private bool hasSelectedVertex;
+ private int selectedvert;
+ private int otherSelectedvert;
+
///
/// Gets the gizmo position.
///
@@ -109,7 +117,7 @@ namespace FlaxEditor.Gizmo
_startTransforms.Capacity = Mathf.NextPowerOfTwo(count);
for (var i = 0; i < count; i++)
{
- _startTransforms.Add(GetSelectedObject(i).Transform);
+ _startTransforms.Add(GetSelectedTransform(i));
}
GetSelectedObjectsBounds(out _startBounds, out _navigationDirty);
@@ -136,25 +144,30 @@ namespace FlaxEditor.Gizmo
private void UpdateGizmoPosition()
{
+ // Get gizmo pivot
switch (_activePivotType)
{
- case PivotType.ObjectCenter:
- if (SelectionCount > 0)
- Position = GetSelectedObject(0).Transform.Translation;
- break;
- case PivotType.SelectionCenter:
- Position = GetSelectionCenter();
- break;
- case PivotType.WorldOrigin:
- Position = Vector3.Zero;
- break;
+ case PivotType.ObjectCenter:
+ if (SelectionCount > 0)
+ Position = GetSelectedTransform(0).Translation;
+ break;
+ case PivotType.SelectionCenter:
+ Position = GetSelectionCenter();
+ break;
+ case PivotType.WorldOrigin:
+ Position = Vector3.Zero;
+ break;
}
- if(verts != null)
+
+ // Apply vertex snapping
+ if (verts != null && SelectedModel != null)
{
- Transform t = thisTransform;
+ Transform t = SelectedModel.Transform;
Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
Position += -(Position - selected);
}
+
+ // Apply current movement
Position += _translationDelta;
}
@@ -186,8 +199,9 @@ namespace FlaxEditor.Gizmo
float gizmoSize = Editor.Instance.Options.Options.Visual.GizmoSize;
_screenScale = (float)(vLength.Length / GizmoScaleFactor * gizmoSize);
}
+
// Setup world
- Quaternion orientation = GetSelectedObject(0).Transform.Orientation;
+ Quaternion orientation = GetSelectedTransform(0).Orientation;
_gizmoWorld = new Transform(position, orientation, new Float3(_screenScale));
if (_activeTransformSpace == TransformSpace.World && _activeMode != Mode.Scale)
{
@@ -217,88 +231,88 @@ namespace FlaxEditor.Gizmo
Real intersection;
switch (_activeAxis)
{
- case Axis.X:
- {
- var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, 0, 0);
- }
- break;
- }
- case Axis.Y:
- {
- var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, _tDelta.Y, 0);
- }
- break;
- }
- case Axis.Z:
- {
- var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, 0, _tDelta.Z);
- }
- break;
- }
- case Axis.YZ:
- {
- if (ray.Intersects(ref planeYZ, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(0, _tDelta.Y, _tDelta.Z);
- }
- break;
- }
- case Axis.XY:
- {
- if (ray.Intersects(ref planeXY, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, _tDelta.Y, 0);
- }
- break;
- }
- case Axis.ZX:
- {
- if (ray.Intersects(ref planeZX, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- delta = new Vector3(_tDelta.X, 0, _tDelta.Z);
- }
- break;
- }
- case Axis.Center:
- {
- var gizmoToView = Position - Owner.ViewPosition;
- var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
- if (ray.Intersects(ref plane, out intersection))
- {
- _intersectPosition = ray.Position + ray.Direction * intersection;
- if (_lastIntersectionPosition != Vector3.Zero)
- _tDelta = _intersectPosition - _lastIntersectionPosition;
- }
- delta = _tDelta;
- break;
- }
+ case Axis.X:
+ {
+ var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, 0, 0);
+ }
+ break;
+ }
+ case Axis.Y:
+ {
+ var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, _tDelta.Y, 0);
+ }
+ break;
+ }
+ case Axis.Z:
+ {
+ var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, 0, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.YZ:
+ {
+ if (ray.Intersects(ref planeYZ, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(0, _tDelta.Y, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.XY:
+ {
+ if (ray.Intersects(ref planeXY, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, _tDelta.Y, 0);
+ }
+ break;
+ }
+ case Axis.ZX:
+ {
+ if (ray.Intersects(ref planeZX, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ delta = new Vector3(_tDelta.X, 0, _tDelta.Z);
+ }
+ break;
+ }
+ case Axis.Center:
+ {
+ var gizmoToView = Position - Owner.ViewPosition;
+ var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
+ if (ray.Intersects(ref plane, out intersection))
+ {
+ _intersectPosition = ray.Position + ray.Direction * intersection;
+ if (_lastIntersectionPosition != Vector3.Zero)
+ _tDelta = _intersectPosition - _lastIntersectionPosition;
+ }
+ delta = _tDelta;
+ break;
+ }
}
// Modifiers
@@ -371,45 +385,36 @@ namespace FlaxEditor.Gizmo
switch (_activeAxis)
{
- case Axis.X:
- case Axis.Y:
- case Axis.Z:
- {
- Float3 dir;
- if (_activeAxis == Axis.X)
- dir = Float3.Right * _gizmoWorld.Orientation;
- else if (_activeAxis == Axis.Y)
- dir = Float3.Up * _gizmoWorld.Orientation;
- else
- dir = Float3.Forward * _gizmoWorld.Orientation;
+ case Axis.X:
+ case Axis.Y:
+ case Axis.Z:
+ {
+ Float3 dir;
+ if (_activeAxis == Axis.X)
+ dir = Float3.Right * _gizmoWorld.Orientation;
+ else if (_activeAxis == Axis.Y)
+ dir = Float3.Up * _gizmoWorld.Orientation;
+ else
+ dir = Float3.Forward * _gizmoWorld.Orientation;
- Float3 viewDir = Owner.ViewPosition - Position;
- Float3.Dot(ref viewDir, ref dir, out float dot);
- if (dot < 0.0f)
- delta *= -1;
+ Float3 viewDir = Owner.ViewPosition - Position;
+ Float3.Dot(ref viewDir, ref dir, out float dot);
+ if (dot < 0.0f)
+ delta *= -1;
- Quaternion.RotationAxis(ref dir, delta, out _rotationDelta);
- break;
- }
+ Quaternion.RotationAxis(ref dir, delta, out _rotationDelta);
+ break;
+ }
- default:
- _rotationDelta = Quaternion.Identity;
- break;
+ default:
+ _rotationDelta = Quaternion.Identity;
+ break;
}
}
///
public override bool IsControllingMouse => _isTransforming;
- //vertex snaping stff
- Mesh.Vertex[] verts;
- Mesh.Vertex[] otherVerts;
- Transform otherTransform;
- StaticModel SelectedModel;
- Transform thisTransform => SelectedModel.Transform;
- bool hasSelectedVertex;
- int selectedvert;
- int otherSelectedvert;
///
public override void Update(float dt)
{
@@ -437,33 +442,28 @@ namespace FlaxEditor.Gizmo
{
switch (_activeMode)
{
- case Mode.Translate:
- UpdateTranslateScale();
- if (Owner.UseSnapping)
- VertexSnap();
- break;
- case Mode.Scale:
- UpdateTranslateScale();
- break;
- case Mode.Rotate:
- UpdateRotate(dt);
- break;
+ case Mode.Translate:
+ UpdateTranslateScale();
+ if (Owner.SnapToVertex)
+ UpdateVertexSnapping();
+ break;
+ case Mode.Scale:
+ UpdateTranslateScale();
+ break;
+ case Mode.Rotate:
+ UpdateRotate(dt);
+ break;
}
-
}
else
{
// If nothing selected, try to select any axis
if (!isLeftBtnDown && !Owner.IsRightMouseButtonDown)
{
- if (Owner.IsAltKeyDown && _activeMode == Mode.Translate)
- SelectVertexSnaping();
- SelectAxis();
- }
- else if (Owner.IsAltKeyDown)
- {
- verts = null;
- otherVerts = null;
+ if (Owner.SnapToVertex)
+ SelectVertexSnapping();
+ else
+ SelectAxis();
}
}
@@ -533,6 +533,7 @@ namespace FlaxEditor.Gizmo
// Deactivate
_isActive = false;
_activeAxis = Axis.None;
+ EndVertexSnapping();
return;
}
@@ -546,167 +547,138 @@ namespace FlaxEditor.Gizmo
// Update
UpdateMatrices();
}
- void SelectVertexSnaping()
- {
- Vector3 point = Vector3.Zero;
- var ray = Owner.MouseRay;
- Real lastdistance = Real.MaxValue;
- StaticModel Lastmodel = null;
- int index = 0;
- int i = 0;
- //get first
- for (; i < SelectionCount; i++)
+ private void SelectVertexSnapping()
+ {
+ // Find the closest object in selection that is hit by the mouse ray
+ var ray = new SceneGraphNode.RayCastData
{
- if (GetSelectedObject(i).EditableObject is StaticModel model)
+ Ray = Owner.MouseRay,
+ };
+ var closestDistance = Real.MaxValue;
+ StaticModel closestModel = null;
+ for (int i = 0; i < SelectionCount; i++)
+ {
+ var obj = GetSelectedObject(i);
+ if (obj.EditableObject is StaticModel model)
{
- var bb = model.EditorBox;
- if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 p))
+ if (obj.RayCastSelf(ref ray, out var distance, out var normal) && distance < closestDistance)
{
- Lastmodel = model;
- point = p;
- index = 0;
- break;
+ closestDistance = distance;
+ closestModel = model;
}
}
}
-
- if (Lastmodel == null) // nothing to do return
- return;
-
- //find closest bounding box in selection
- for (; i < SelectionCount; i++)
+ if (closestModel == null)
{
- if (GetSelectedObject(i).EditableObject is StaticModel model)
+ // Find the closest object in selection (in case ray didn't hit anything)
+ for (int i = 0; i < SelectionCount; i++)
{
- var bb = model.EditorBox;
- //check for other we might have one closer
- var d = Vector3.Distance(model.Transform.Translation, ray.Position);
- if (lastdistance < d)
+ var obj = GetSelectedObject(i);
+ if (obj.EditableObject is StaticModel model)
{
- if (CollisionsHelper.RayIntersectsBox(ref ray, ref bb, out Vector3 p))
+ var bounds = model.Box;
+ CollisionsHelper.ClosestPointBoxPoint(ref bounds, ref ray.Ray.Position, out var point);
+ var distance = Vector3.Distance(ref point, ref ray.Ray.Position);
+ if (distance < closestDistance)
{
- lastdistance = d;
- Lastmodel = model;
- point = p;
- index = i;
+ closestDistance = distance;
+ closestModel = model;
}
}
}
}
- SelectedModel = Lastmodel;
+ SelectedModel = closestModel;
+ if (closestModel == null)
+ return;
- //find closest vertex to bounding box point (collision detection approximation)
- //[ToDo] replace this with collision detection with is suporting concave shapes (compute shader)
- point = thisTransform.WorldToLocal(point);
-
- //[To Do] comlite this there is not suport for multy mesh model
- verts = Lastmodel.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
-
- lastdistance = Vector3.Distance(point, verts[0].Position);
+ // Find the closest vertex to bounding box point (collision detection approximation)
+ // TODO: replace this with collision detection which supports concave shapes (compute shader)
+ var hitPoint = SelectedModel.Transform.WorldToLocal(ray.Ray.GetPoint(closestDistance));
+ // TODO: support multi-mesh models
+ verts = closestModel.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+ closestDistance = Vector3.Distance(hitPoint, verts[0].Position);
for (int j = 0; j < verts.Length; j++)
{
- var d = Vector3.Distance(point, verts[j].Position);
- if (d <= lastdistance)
+ var distance = Vector3.Distance(hitPoint, verts[j].Position);
+ if (distance <= closestDistance)
{
- lastdistance = d;
+ closestDistance = distance;
selectedvert = j;
}
-
}
}
- void VertexSnap()
+
+ private void EndVertexSnapping()
{
+ // Clear current vertex snapping data
+ SelectedModel = null;
+ verts = null;
+ otherVerts = null;
+ }
+
+ private void UpdateVertexSnapping()
+ {
+ if (Owner.SceneGraphRoot == null)
+ return;
Profiler.BeginEvent("VertexSnap");
- //ray cast others
+
+ // Ray cast others
if (verts != null)
{
var ray = Owner.MouseRay;
-
- SceneGraphNode.RayCastData rayCast = new SceneGraphNode.RayCastData()
+ var rayCast = new SceneGraphNode.RayCastData
{
Ray = ray,
- Exclude = new List() {},
- Scan = new List() { typeof(StaticModel) }
+ Flags = SceneGraphNode.RayCastData.FlagTypes.SkipColliders | SceneGraphNode.RayCastData.FlagTypes.SkipEditorPrimitives,
+ ExcludeObjects = new(),
};
for (int i = 0; i < SelectionCount; i++)
+ rayCast.ExcludeObjects.Add(GetSelectedObject(i));
+
+ // Raycast objects
+ var hit = Owner.SceneGraphRoot.RayCast(ref rayCast, out var distance, out var _);
+ if (hit != null && hit.EditableObject is StaticModel model)
{
- rayCast.Exclude.Add((Actor)GetSelectedObject(i).EditableObject);
- }
- //grab scene and raycast
- var actor = GetSelectedObject(0).ParentScene.RayCast(ref rayCast, out var distance, out var _);
- if (actor != null)
- {
- if (actor.EditableObject is StaticModel model)
+ otherTransform = model.Transform;
+ Vector3 point = rayCast.Ray.Position + (rayCast.Ray.Direction * distance);
+
+ //[To Do] comlite this there is not suport for multy mesh model
+ otherVerts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
+
+ //find closest vertex to bounding box point (collision detection approximation)
+ //[ToDo] replace this with collision detection with is suporting concave shapes (compute shader)
+ point = hit.Transform.WorldToLocal(point);
+ var closestDistance = Vector3.Distance(point, otherVerts[0].Position);
+ for (int i = 0; i < otherVerts.Length; i++)
{
- otherTransform = model.Transform;
- Vector3 p = rayCast.Ray.Position + (rayCast.Ray.Direction * distance);
-
- //[To Do] comlite this there is not suport for multy mesh model
- otherVerts = model.Model.LODs[0].Meshes[0].DownloadVertexBuffer();
-
- //find closest vertex to bounding box point (collision detection approximation)
- //[ToDo] replace this with collision detection with is suporting concave shapes (compute shader)
- p = actor.Transform.WorldToLocal(p);
- Real lastdistance = Vector3.Distance(p, otherVerts[0].Position);
- for (int i = 0; i < otherVerts.Length; i++)
+ distance = Vector3.Distance(point, otherVerts[i].Position);
+ if (distance < closestDistance)
{
- var d = Vector3.Distance(p, otherVerts[i].Position);
- if (d <= lastdistance)
- {
- lastdistance = d;
- otherSelectedvert = i;
- }
+ closestDistance = distance;
+ otherSelectedvert = i;
}
+ }
- if(lastdistance > 25)
- {
- otherSelectedvert = -1;
- otherVerts = null;
- }
+ if (closestDistance > 25)
+ {
+ otherSelectedvert = -1;
+ otherVerts = null;
}
}
}
- if (verts != null && otherVerts != null)
+ if (verts != null && SelectedModel != null && otherVerts != null)
{
- Transform t = thisTransform;
- Vector3 selected = ((verts[selectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
-
- t = otherTransform;
- Vector3 other = ((otherVerts[otherSelectedvert].Position * t.Orientation) * t.Scale) + t.Translation;
-
- // Translation
- var projection = -(selected - other);
-
- //at some point
- //Quaternion inverse = t.Orientation;
- //inverse.Invert();
- //projection *= inverse; //world to local
- //flip mask
- //var Not = ~_activeAxis;
- //LockAxisWorld(Not, ref projection); //lock axis
- //projection *= t.Orientation; //local to world
-
- _translationDelta = projection;
+ // Snap current vertex to the other vertex
+ Vector3 selected = SelectedModel.Transform.LocalToWorld(verts[selectedvert].Position);
+ Vector3 other = otherTransform.LocalToWorld(otherVerts[otherSelectedvert].Position);
+ _translationDelta = other - selected;
}
Profiler.EndEvent();
}
- ///
- /// zeros the component using the
- ///
- public static void LockAxisWorld(Axis lockAxis, ref Vector3 v)
- {
- if (lockAxis.HasFlag(Axis.X))
- v.X = 0;
- if (lockAxis.HasFlag(Axis.Y))
- v.Y = 0;
- if (lockAxis.HasFlag(Axis.Z))
- v.Z = 0;
- }
-
///
/// Gets a value indicating whether this tool can transform objects.
///
@@ -722,11 +694,19 @@ namespace FlaxEditor.Gizmo
///
protected abstract int SelectionCount { get; }
+ ///
+ /// Gets the selected object.
+ ///
+ /// The selected object index.
+ /// The selected object (eg. actor node).
+ protected abstract SceneGraphNode GetSelectedObject(int index);
+
///
/// Gets the selected object transformation.
///
/// The selected object index.
- protected abstract SceneGraphNode GetSelectedObject(int index);
+ /// The transformation of the selected object.
+ protected abstract Transform GetSelectedTransform(int index);
///
/// Gets the selected objects bounding box (contains the whole selection).
diff --git a/Source/Editor/Options/InputOptions.cs b/Source/Editor/Options/InputOptions.cs
index e2e7d0e71..ec50d1501 100644
--- a/Source/Editor/Options/InputOptions.cs
+++ b/Source/Editor/Options/InputOptions.cs
@@ -112,6 +112,10 @@ namespace FlaxEditor.Options
[EditorDisplay("Scene", "Snap To Ground"), EditorOrder(500)]
public InputBinding SnapToGround = new InputBinding(KeyboardKeys.End);
+ [DefaultValue(typeof(InputBinding), "End")]
+ [EditorDisplay("Scene", "Vertex Snapping"), EditorOrder(550)]
+ public InputBinding SnapToVertex = new InputBinding(KeyboardKeys.V);
+
[DefaultValue(typeof(InputBinding), "F5")]
[EditorDisplay("Scene", "Play/Stop"), EditorOrder(510)]
public InputBinding Play = new InputBinding(KeyboardKeys.F5);
diff --git a/Source/Editor/SceneGraph/Actors/BoxBrushNode.cs b/Source/Editor/SceneGraph/Actors/BoxBrushNode.cs
index da28dad2b..3d5bd9ed2 100644
--- a/Source/Editor/SceneGraph/Actors/BoxBrushNode.cs
+++ b/Source/Editor/SceneGraph/Actors/BoxBrushNode.cs
@@ -200,12 +200,8 @@ namespace FlaxEditor.SceneGraph.Actors
: base(actor)
{
var id = ID;
- var bytes = id.ToByteArray();
for (int i = 0; i < 6; i++)
- {
- bytes[0] += 1;
- AddChildNode(new SideLinkNode(this, new Guid(bytes), i));
- }
+ AddChildNode(new SideLinkNode(this, GetSubID(id, i), i));
}
///
diff --git a/Source/Editor/SceneGraph/Actors/BoxVolumeNode.cs b/Source/Editor/SceneGraph/Actors/BoxVolumeNode.cs
index 92850857b..a2265e3bf 100644
--- a/Source/Editor/SceneGraph/Actors/BoxVolumeNode.cs
+++ b/Source/Editor/SceneGraph/Actors/BoxVolumeNode.cs
@@ -169,12 +169,8 @@ namespace FlaxEditor.SceneGraph.Actors
: base(actor)
{
var id = ID;
- var bytes = id.ToByteArray();
for (int i = 0; i < 6; i++)
- {
- bytes[0] += 1;
- AddChildNode(new SideLinkNode(this, new Guid(bytes), i));
- }
+ AddChildNode(new SideLinkNode(this, GetSubID(id, i), i));
}
///
diff --git a/Source/Editor/SceneGraph/Actors/FoliageNode.cs b/Source/Editor/SceneGraph/Actors/FoliageNode.cs
index 50756170a..9e24d5b66 100644
--- a/Source/Editor/SceneGraph/Actors/FoliageNode.cs
+++ b/Source/Editor/SceneGraph/Actors/FoliageNode.cs
@@ -10,21 +10,68 @@ namespace FlaxEditor.SceneGraph.Actors
[HideInEditor]
public sealed class FoliageNode : ActorNode
{
- private FoliageInstance instance;
- ///
- /// The selected instance index
- ///
- public int SelectedInstanceIndex;
-
///
- public FoliageNode(Foliage actor, int selectedInstanceIndex = -1)
+ public FoliageNode(Actor actor)
: base(actor)
{
- SelectedInstanceIndex = selectedInstanceIndex;
- if (selectedInstanceIndex != -1)
+ }
+ }
+
+ ///
+ /// Scene tree node for instance of .
+ ///
+ [HideInEditor]
+ public sealed class FoliageInstanceNode : SceneGraphNode
+ {
+ ///
+ /// The foliage actor that owns this instance.
+ ///
+ public Foliage Actor;
+
+ ///
+ /// Index of the foliage instance.
+ ///
+ public int Index;
+
+ ///
+ public FoliageInstanceNode(Foliage actor, int index)
+ : base(GetSubID(actor.ID, index))
+ {
+ Actor = actor;
+ Index = index;
+ }
+
+ ///
+ public override string Name => "Foliage Instance";
+
+ ///
+ public override SceneNode ParentScene
+ {
+ get
{
- instance = actor.GetInstance(selectedInstanceIndex);
+ var scene = Actor ? Actor.Scene : null;
+ return scene != null ? SceneGraphFactory.FindNode(scene.ID) as SceneNode : null;
}
}
+
+ ///
+ public override Transform Transform
+ {
+ get => Actor.GetInstance(Index).Transform;
+ set => Actor.SetInstanceTransform(Index, ref value);
+ }
+
+ ///
+ public override bool IsActive => Actor.IsActive;
+
+ ///
+ public override bool IsActiveInHierarchy => Actor.IsActiveInHierarchy;
+
+ ///
+ public override int OrderInParent
+ {
+ get => Index;
+ set { }
+ }
}
}
diff --git a/Source/Editor/SceneGraph/Actors/NavLinkNode.cs b/Source/Editor/SceneGraph/Actors/NavLinkNode.cs
index a0e90622f..4872c312a 100644
--- a/Source/Editor/SceneGraph/Actors/NavLinkNode.cs
+++ b/Source/Editor/SceneGraph/Actors/NavLinkNode.cs
@@ -77,11 +77,9 @@ namespace FlaxEditor.SceneGraph.Actors
public NavLinkNode(Actor actor)
: base(actor)
{
- var bytes = ID.ToByteArray();
- bytes[0] += 1;
- AddChildNode(new LinkNode(this, new Guid(bytes), true));
- bytes[0] += 1;
- AddChildNode(new LinkNode(this, new Guid(bytes), false));
+ var id = ID;
+ AddChildNode(new LinkNode(this, GetSubID(id, 0), true));
+ AddChildNode(new LinkNode(this, GetSubID(id, 1), false));
}
///
diff --git a/Source/Editor/SceneGraph/SceneGraphNode.cs b/Source/Editor/SceneGraph/SceneGraphNode.cs
index 4ca8034e1..a8a26a1b3 100644
--- a/Source/Editor/SceneGraph/SceneGraphNode.cs
+++ b/Source/Editor/SceneGraph/SceneGraphNode.cs
@@ -13,7 +13,6 @@ using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Windows;
using FlaxEngine;
-using System.Runtime.CompilerServices;
namespace FlaxEditor.SceneGraph
{
@@ -147,7 +146,6 @@ namespace FlaxEditor.SceneGraph
{
if (ChildNodes.Contains(node))
return true;
-
return ChildNodes.Any(x => x.ContainsInHierarchy(node));
}
@@ -219,20 +217,9 @@ namespace FlaxEditor.SceneGraph
public FlagTypes Flags;
///
- /// The exclude list actors specyfaied in
+ /// The list of objects to exclude from tracing against. Null if unused.
///
- public List Exclude = new List();
-
- ///
- /// The scan for types
- ///
- public List Scan = new List();
-
- ///
- /// if this is true it will include the types specyfaied in
- /// otherwise it will include all types excluding types specyfaied in
- ///
- public bool ExcludeScan;
+ public List