diff --git a/Flax.sln.DotSettings b/Flax.sln.DotSettings index ec2e8d359..f9c066bae 100644 --- a/Flax.sln.DotSettings +++ b/Flax.sln.DotSettings @@ -341,6 +341,7 @@ True True True + True True True True diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index 18162284e..5fb5c12f2 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -41,8 +41,7 @@ namespace FlaxEditor.Gizmo _materialAxisZ == null || _materialAxisFocus == null || _materialWire == null || - _materialWireFocus == null - ) + _materialWireFocus == null) { // Error Platform.Fatal("Failed to load transform gizmo resources."); @@ -56,13 +55,12 @@ namespace FlaxEditor.Gizmo return; Matrix m1, m2, m3; - bool isXAxis = _activeAxis == Axis.X || _activeAxis == Axis.XY || _activeAxis == Axis.ZX; bool isYAxis = _activeAxis == Axis.Y || _activeAxis == Axis.XY || _activeAxis == Axis.YZ; bool isZAxis = _activeAxis == Axis.Z || _activeAxis == Axis.YZ || _activeAxis == Axis.ZX; bool isCenter = _activeAxis == Axis.Center; + renderContext.View.GetWorldMatrix(ref _gizmoWorld, out Matrix world); - // Switch mode const float gizmoModelsScale2RealGizmoSize = 0.075f; switch (_activeMode) { @@ -71,7 +69,7 @@ namespace FlaxEditor.Gizmo if (!_modelTranslateAxis || !_modelTranslateAxis.IsLoaded || !_modelBox || !_modelBox.IsLoaded) break; Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); - Matrix.Multiply(ref m3, ref _gizmoWorld, out m1); + Matrix.Multiply(ref m3, ref world, out m1); var axisMesh = _modelTranslateAxis.LODs[0].Meshes[0]; var boxMesh = _modelBox.LODs[0].Meshes[0]; var boxSize = 10.0f; @@ -114,7 +112,7 @@ namespace FlaxEditor.Gizmo var circleMesh = _modelCircle.LODs[0].Meshes[0]; var boxMesh = _modelBox.LODs[0].Meshes[0]; Matrix.Scaling(8.0f, out m3); - Matrix.Multiply(ref m3, ref _gizmoWorld, out m1); + Matrix.Multiply(ref m3, ref world, out m1); // X axis Matrix.RotationZ(Mathf.PiOverTwo, out m2); @@ -131,7 +129,7 @@ namespace FlaxEditor.Gizmo // Center box Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); - Matrix.Multiply(ref m3, ref _gizmoWorld, out m1); + Matrix.Multiply(ref m3, ref world, out m1); Matrix.Scaling(1.0f, out m2); Matrix.Multiply(ref m2, ref m1, out m3); boxMesh.Draw(ref renderContext, isCenter ? _materialWireFocus : _materialWire, ref m3); @@ -144,7 +142,7 @@ namespace FlaxEditor.Gizmo if (!_modelScaleAxis || !_modelScaleAxis.IsLoaded || !_modelBox || !_modelBox.IsLoaded) break; Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); - Matrix.Multiply(ref m3, ref _gizmoWorld, out m1); + Matrix.Multiply(ref m3, ref world, out m1); var axisMesh = _modelScaleAxis.LODs[0].Meshes[0]; var boxMesh = _modelBox.LODs[0].Meshes[0]; diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs index 2042e1164..be0da7ad0 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Selection.cs @@ -52,9 +52,8 @@ namespace FlaxEditor.Gizmo // Transform ray into local space of the gizmo Ray localRay; - Matrix.Invert(ref _gizmoWorld, out Matrix invGizmoWorld); - Vector3.TransformNormal(ref ray.Direction, ref invGizmoWorld, out localRay.Direction); - Vector3.Transform(ref ray.Position, ref invGizmoWorld, out localRay.Position); + _gizmoWorld.WorldToLocalVector(ref ray.Direction, out localRay.Direction); + _gizmoWorld.WorldToLocal(ref ray.Position, out localRay.Position); // Find gizmo collisions with mouse Real closestIntersection = Real.MaxValue; diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 41f35d470..0f3cc0a16 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -36,9 +36,7 @@ namespace FlaxEditor.Gizmo protected BoundingBox _startBounds = BoundingBox.Empty; private Vector3 _accMoveDelta; - private Matrix _axisAlignedWorld = Matrix.Identity; - - private Matrix _gizmoWorld = Matrix.Identity; + private Transform _gizmoWorld = Transform.Identity; private Vector3 _intersectPosition; private bool _isActive; private bool _isDuplicating; @@ -46,19 +44,11 @@ namespace FlaxEditor.Gizmo private bool _isTransforming; private Vector3 _lastIntersectionPosition; - private Vector3 _localForward = Vector3.Forward; - private Vector3 _localRight = Vector3.Right; - private Vector3 _localUp = Vector3.Up; - - private Matrix _objectOrientedWorld = Matrix.Identity; - private Quaternion _rotationDelta = Quaternion.Identity; - private Matrix _rotationMatrix; private float _rotationSnapDelta; private Vector3 _scaleDelta; private float _screenScale; - private Matrix _screenScaleMatrix; private Vector3 _tDelta; private Vector3 _translationDelta; private Vector3 _translationScaleSnapDelta; @@ -170,43 +160,17 @@ namespace FlaxEditor.Gizmo UpdateGizmoPosition(); // Scale gizmo to fit on-screen - Vector3 vLength = Owner.ViewPosition - Position; + Vector3 position = Position; + Vector3 vLength = Owner.ViewPosition - position; float gizmoSize = Editor.Instance.Options.Options.Visual.GizmoSize; _screenScale = (float)(vLength.Length / GizmoScaleFactor * gizmoSize); - Matrix.Scaling(_screenScale, out _screenScaleMatrix); + // Setup world Quaternion orientation = GetSelectedObject(0).Orientation; - Matrix.RotationQuaternion(ref orientation, out Matrix rotation); - _localForward = rotation.Forward; - _localUp = rotation.Up; - - // Vector Rotation (Local/World) - _localForward.Normalize(); - Vector3.Cross(ref _localForward, ref _localUp, out _localRight); - Vector3.Cross(ref _localRight, ref _localForward, out _localUp); - _localRight.Normalize(); - _localUp.Normalize(); - - // Create both world matrices - _objectOrientedWorld = _screenScaleMatrix * Matrix.CreateWorld(Position, _localForward, _localUp); - _axisAlignedWorld = _screenScaleMatrix * Matrix.CreateWorld(Position, Vector3.Backward, Vector3.Up); - - // Assign world + _gizmoWorld = new Transform(position, orientation, new Float3(_screenScale)); if (_activeTransformSpace == TransformSpace.World && _activeMode != Mode.Scale) { - _gizmoWorld = _axisAlignedWorld; - - // Align lines, boxes etc. with the grid-lines - _rotationMatrix = Matrix.Identity; - } - else - { - _gizmoWorld = _objectOrientedWorld; - - // Align lines, boxes etc. with the selected object - _rotationMatrix.Forward = _localForward; - _rotationMatrix.Up = _localUp; - _rotationMatrix.Right = _localRight; + _gizmoWorld.Orientation = Quaternion.Identity; } } @@ -216,7 +180,8 @@ namespace FlaxEditor.Gizmo Vector3 delta = Vector3.Zero; Ray ray = Owner.MouseRay; - Matrix.Invert(ref _rotationMatrix, out var invRotationMatrix); + Matrix.RotationQuaternion(ref _gizmoWorld.Orientation, out var rotationMatrix); + Matrix.Invert(ref rotationMatrix, out var invRotationMatrix); ray.Position = Vector3.Transform(ray.Position, invRotationMatrix); Vector3.TransformNormal(ref ray.Direction, ref invRotationMatrix, out ray.Direction); @@ -334,7 +299,7 @@ namespace FlaxEditor.Gizmo if (_activeMode == Mode.Translate) { // Transform (local or world) - delta = Vector3.Transform(delta, _rotationMatrix); + delta = Vector3.Transform(delta, rotationMatrix); _translationDelta = delta; } else if (_activeMode == Mode.Scale) @@ -369,11 +334,11 @@ namespace FlaxEditor.Gizmo { Float3 dir; if (_activeAxis == Axis.X) - dir = _rotationMatrix.Right; + dir = Float3.Right * _gizmoWorld.Orientation; else if (_activeAxis == Axis.Y) - dir = _rotationMatrix.Up; + dir = Float3.Up * _gizmoWorld.Orientation; else - dir = _rotationMatrix.Forward; + dir = Float3.Forward * _gizmoWorld.Orientation; Float3 viewDir = Owner.ViewPosition - Position; Float3.Dot(ref viewDir, ref dir, out float dot); diff --git a/Source/Engine/Core/Math/OrientedBoundingBox.cs b/Source/Engine/Core/Math/OrientedBoundingBox.cs index 47c46f3cf..c35cfac6c 100644 --- a/Source/Engine/Core/Math/OrientedBoundingBox.cs +++ b/Source/Engine/Core/Math/OrientedBoundingBox.cs @@ -151,6 +151,16 @@ namespace FlaxEngine corners.AddRange(GetCorners()); } + /// + /// Transforms this box using a transformation. + /// + /// The transformation. + /// While any kind of transformation can be applied, it is recommended to apply scaling using scale method instead, which scales the Extents and keeps the Transformation for rotation only, and that preserves collision detection accuracy. + public void Transform(ref Transform transform) + { + Transformation = transform.LocalToWorld(Transformation); + } + /// /// Transforms this box using a transformation matrix. /// @@ -425,6 +435,20 @@ namespace FlaxEngine return result; } + /// + /// Transforms bounding box using the given transformation. + /// + /// The bounding box to transform. + /// The transformation. + /// The result of the transformation. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static OrientedBoundingBox operator *(OrientedBoundingBox box, Transform transform) + { + OrientedBoundingBox result = box; + result.Transformation = transform.LocalToWorld(result.Transformation); + return result; + } + /// /// Tests for equality between two objects. /// diff --git a/Source/Engine/Core/Math/Vector3.cpp b/Source/Engine/Core/Math/Vector3.cpp index 42f938d74..535afead8 100644 --- a/Source/Engine/Core/Math/Vector3.cpp +++ b/Source/Engine/Core/Math/Vector3.cpp @@ -7,6 +7,7 @@ #include "Quaternion.h" #include "Matrix.h" #include "Matrix3x3.h" +#include "Transform.h" #include "../Types/String.h" // Float @@ -214,6 +215,14 @@ Float3 Float3::Transform(const Float3& vector, const Matrix& transform) vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); } +template<> +Float3 Float3::Transform(const Float3& vector, const ::Transform& transform) +{ + Vector3 result; + transform.LocalToWorld(vector, result); + return result; +} + template<> void Float3::TransformCoordinate(const Float3& coordinate, const Matrix& transform, Float3& result) { @@ -508,6 +517,14 @@ Double3 Double3::Transform(const Double3& vector, const Matrix& transform) vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); } +template<> +Double3 Double3::Transform(const Double3& vector, const ::Transform& transform) +{ + Vector3 result; + transform.LocalToWorld(vector, result); + return result; +} + template<> void Double3::TransformCoordinate(const Double3& coordinate, const Matrix& transform, Double3& result) { @@ -748,6 +765,12 @@ Int3 Int3::Transform(const Int3& vector, const Matrix& transform) return vector; } +template<> +Int3 Int3::Transform(const Int3& vector, const ::Transform& transform) +{ + return vector; +} + template<> void Int3::TransformCoordinate(const Int3& coordinate, const Matrix& transform, Int3& result) { diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs index 8695a15f4..9b1f5b18e 100644 --- a/Source/Engine/Core/Math/Vector3.cs +++ b/Source/Engine/Core/Math/Vector3.cs @@ -1432,6 +1432,17 @@ namespace FlaxEngine vector.X * transform.M14 + vector.Y * transform.M24 + vector.Z * transform.M34 + transform.M44); } + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// When the method completes, contains the transformed . + public static void Transform(ref Vector3 vector, ref Transform transform, out Vector3 result) + { + transform.LocalToWorld(ref vector, out result); + } + /// /// Transforms a 3D vector by the given . /// @@ -1444,6 +1455,18 @@ namespace FlaxEngine return result; } + /// + /// Transforms a 3D vector by the given . + /// + /// The source vector. + /// The transformation . + /// The transformed . + public static Vector3 Transform(Vector3 vector, Transform transform) + { + Transform(ref vector, ref transform, out Vector3 result); + return result; + } + /// /// Performs a coordinate transformation using the given . /// diff --git a/Source/Engine/Core/Math/Vector3.h b/Source/Engine/Core/Math/Vector3.h index b87552133..7e34031ae 100644 --- a/Source/Engine/Core/Math/Vector3.h +++ b/Source/Engine/Core/Math/Vector3.h @@ -712,12 +712,24 @@ public: // @param result When the method completes, contains the transformed Vector3 static FLAXENGINE_API void Transform(const Vector3Base& vector, const Matrix3x3& transform, Vector3Base& result); + // Transforms a 3D vector by the given transformation + // @param vector The source vector + // @param transform The transformation + // @param result When the method completes, contains the transformed Vector3 + static FLAXENGINE_API void Transform(const Vector3Base& vector, const ::Transform& transform, Vector3Base& result); + // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix // @returns Transformed Vector3 static FLAXENGINE_API Vector3Base Transform(const Vector3Base& vector, const Matrix& transform); + // Transforms a 3D vector by the given transformation + // @param vector The source vector + // @param transform The transformation + // @returns Transformed Vector3 + static FLAXENGINE_API Vector3Base Transform(const Vector3Base& vector, const ::Transform& transform); + // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index 11211bdd2..1d76014e4 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -191,6 +191,41 @@ void UpdateList(float dt, Array& list) } } +void TeleportList(const Float3& delta, Array& list) +{ + for (auto& l : list) + { + l.Start += delta; + l.End += delta; + } +} + +void TeleportList(const Float3& delta, Array& list) +{ + for (auto& v : list) + { + v.Position += delta; + } +} + +void TeleportList(const Float3& delta, Array& list) +{ + for (auto& v : list) + { + v.V0 += delta; + v.V1 += delta; + v.V2 += delta; + } +} + +void TeleportList(const Float3& delta, Array& list) +{ + for (auto& v : list) + { + v.Transform.Translation += delta; + } +} + struct DebugDrawData { Array DefaultLines; @@ -255,6 +290,18 @@ struct DebugDrawData OneFrameText3D.Clear(); } + void Teleport(const Float3& delta) + { + TeleportList(delta, DefaultLines); + TeleportList(delta, OneFrameLines); + TeleportList(delta, DefaultTriangles); + TeleportList(delta, OneFrameTriangles); + TeleportList(delta, DefaultWireTriangles); + TeleportList(delta, OneFrameWireTriangles); + TeleportList(delta, DefaultText3D); + TeleportList(delta, OneFrameText3D); + } + inline void Clear() { DefaultLines.Clear(); @@ -286,6 +333,7 @@ struct DebugDrawData struct DebugDrawContext { + Vector3 Origin = Vector3::Zero; DebugDrawData DebugDrawDefault; DebugDrawData DebugDrawDepthTest; Float3 LastViewPos = Float3::Zero; @@ -670,6 +718,14 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe if (renderContext.Buffers == nullptr || !DebugDrawVB) return; auto context = GPUDevice::Instance->GetMainContext(); + if (Context->Origin != renderContext.View.Origin) + { + // Teleport existing debug shapes to maintain their location + Float3 delta = Context->Origin - renderContext.View.Origin; + Context->DebugDrawDefault.Teleport(delta); + Context->DebugDrawDepthTest.Teleport(delta); + Context->Origin = renderContext.View.Origin; + } Context->LastViewPos = renderContext.View.Position; Context->LastViewProj = renderContext.View.Projection; @@ -858,17 +914,18 @@ void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount, bo void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color& color, float duration, bool depthTest) { + const Float3 startF = start - Context->Origin, endF = end - Context->Origin; auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; if (duration > 0) { - DebugLine l = { start, end, Color32(color), duration }; + DebugLine l = { startF, endF, Color32(color), duration }; debugDrawData.DefaultLines.Add(l); } else { - Vertex l = { start, Color32(color) }; + Vertex l = { startF, Color32(color) }; debugDrawData.OneFrameLines.Add(l); - l.Position = end; + l.Position = endF; debugDrawData.OneFrameLines.Add(l); } } @@ -886,14 +943,15 @@ void DebugDraw::DrawLines(const Span& lines, const Matrix& transform, co // Draw lines const Float3* p = lines.Get(); auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); if (duration > 0) { DebugLine l = { Float3::Zero, Float3::Zero, Color32(color), duration }; debugDrawData.DefaultLines.EnsureCapacity(debugDrawData.DefaultLines.Count() + lines.Length()); for (int32 i = 0; i < lines.Length(); i += 2) { - Float3::Transform(*p++, transform, l.Start); - Float3::Transform(*p++, transform, l.End); + Float3::Transform(*p++, transformF, l.Start); + Float3::Transform(*p++, transformF, l.End); debugDrawData.DefaultLines.Add(l); } } @@ -903,9 +961,9 @@ void DebugDraw::DrawLines(const Span& lines, const Matrix& transform, co debugDrawData.OneFrameLines.EnsureCapacity(debugDrawData.OneFrameLines.Count() + lines.Length() * 2); for (int32 i = 0; i < lines.Length(); i += 2) { - Float3::Transform(*p++, transform, l.Position); + Float3::Transform(*p++, transformF, l.Position); debugDrawData.OneFrameLines.Add(l); - Float3::Transform(*p++, transform, l.Position); + Float3::Transform(*p++, transformF, l.Position); debugDrawData.OneFrameLines.Add(l); } } @@ -929,14 +987,15 @@ void DebugDraw::DrawLines(const Span& lines, const Matrix& transform, c // Draw lines const Double3* p = lines.Get(); auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); if (duration > 0) { DebugLine l = { Float3::Zero, Float3::Zero, Color32(color), duration }; debugDrawData.DefaultLines.EnsureCapacity(debugDrawData.DefaultLines.Count() + lines.Length()); for (int32 i = 0; i < lines.Length(); i += 2) { - Float3::Transform(*p++, transform, l.Start); - Float3::Transform(*p++, transform, l.End); + Float3::Transform(*p++, transformF, l.Start); + Float3::Transform(*p++, transformF, l.End); debugDrawData.DefaultLines.Add(l); } } @@ -946,9 +1005,9 @@ void DebugDraw::DrawLines(const Span& lines, const Matrix& transform, c debugDrawData.OneFrameLines.EnsureCapacity(debugDrawData.OneFrameLines.Count() + lines.Length() * 2); for (int32 i = 0; i < lines.Length(); i += 2) { - Float3::Transform(*p++, transform, l.Position); + Float3::Transform(*p++, transformF, l.Position); debugDrawData.OneFrameLines.Add(l); - Float3::Transform(*p++, transform, l.Position); + Float3::Transform(*p++, transformF, l.Position); debugDrawData.OneFrameLines.Add(l); } } @@ -961,25 +1020,27 @@ void DebugDraw::DrawLines(const Array& lines, const Mat void DebugDraw::DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4, const Color& color, float duration, bool depthTest) { + const Float3 p1F = p1 - Context->Origin, p2F = p2 - Context->Origin, p3F = p3 - Context->Origin, p4F = p4 - Context->Origin; + // Find amount of segments to use - const Vector3 d1 = p2 - p1; - const Vector3 d2 = p3 - p2; - const Vector3 d3 = p4 - p3; - const Real len = d1.Length() + d2.Length() + d3.Length(); - const int32 segmentCount = Math::Clamp(Math::CeilToInt((float)len * 0.05f), 1, 100); + const Float3 d1 = p2F - p1F; + const Float3 d2 = p3F - p2F; + const Float3 d3 = p4F - p3F; + const float len = d1.Length() + d2.Length() + d3.Length(); + const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100); const float segmentCountInv = 1.0f / (float)segmentCount; // Draw segmented curve from lines auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; if (duration > 0) { - DebugLine l = { p1, Float3::Zero, Color32(color), duration }; + DebugLine l = { p1F, Float3::Zero, Color32(color), duration }; debugDrawData.DefaultLines.EnsureCapacity(debugDrawData.DefaultLines.Count() + segmentCount + 2); for (int32 i = 0; i <= segmentCount; i++) { const float t = (float)i * segmentCountInv; - Vector3 end; - AnimationUtils::Bezier(p1, p2, p3, p4, t, end); + Float3 end; + AnimationUtils::Bezier(p1F, p2F, p3F, p4F, t, end); l.End = end; debugDrawData.DefaultLines.Add(l); l.Start = l.End; @@ -987,14 +1048,14 @@ void DebugDraw::DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3& } else { - Vertex l = { p1, Color32(color) }; + Vertex l = { p1F, Color32(color) }; debugDrawData.OneFrameLines.EnsureCapacity(debugDrawData.OneFrameLines.Count() + segmentCount * 2 + 4); for (int32 i = 0; i <= segmentCount; i++) { const float t = (float)i * segmentCountInv; debugDrawData.OneFrameLines.Add(l); - Vector3 position; - AnimationUtils::Bezier(p1, p2, p3, p4, t, position); + Float3 position; + AnimationUtils::Bezier(p1F, p2F, p3F, p4F, t, position); l.Position = position; debugDrawData.OneFrameLines.Add(l); } @@ -1004,8 +1065,10 @@ void DebugDraw::DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3& void DebugDraw::DrawWireBox(const BoundingBox& box, const Color& color, float duration, bool depthTest) { // Get corners - Float3 corners[8]; + Vector3 corners[8]; box.GetCorners(corners); + for (Vector3& c : corners) + c -= Context->Origin; // Draw lines auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; @@ -1036,8 +1099,10 @@ void DebugDraw::DrawWireBox(const BoundingBox& box, const Color& color, float du void DebugDraw::DrawWireFrustum(const BoundingFrustum& frustum, const Color& color, float duration, bool depthTest) { // Get corners - Float3 corners[8]; + Vector3 corners[8]; frustum.GetCorners(corners); + for (Vector3& c : corners) + c -= Context->Origin; // Draw lines auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; @@ -1068,8 +1133,10 @@ void DebugDraw::DrawWireFrustum(const BoundingFrustum& frustum, const Color& col void DebugDraw::DrawWireBox(const OrientedBoundingBox& box, const Color& color, float duration, bool depthTest) { // Get corners - Float3 corners[8]; + Vector3 corners[8]; box.GetCorners(corners); + for (Vector3& c : corners) + c -= Context->Origin; // Draw lines auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; @@ -1101,7 +1168,9 @@ void DebugDraw::DrawWireSphere(const BoundingSphere& sphere, const Color& color, { // Select LOD int32 index; - const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(sphere.Center, (float)sphere.Radius, Context->LastViewPos, Context->LastViewProj); + const Float3 centerF = sphere.Center - Context->Origin; + const float radiusF = (float)sphere.Radius; + const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(centerF, radiusF, Context->LastViewPos, Context->LastViewProj); if (screenRadiusSquared > DEBUG_DRAW_SPHERE_LOD0_SCREEN_SIZE * DEBUG_DRAW_SPHERE_LOD0_SCREEN_SIZE * 0.25f) index = 0; else if (screenRadiusSquared > DEBUG_DRAW_SPHERE_LOD1_SCREEN_SIZE * DEBUG_DRAW_SPHERE_LOD1_SCREEN_SIZE * 0.25f) @@ -1117,8 +1186,8 @@ void DebugDraw::DrawWireSphere(const BoundingSphere& sphere, const Color& color, DebugLine l = { Float3::Zero, Float3::Zero, Color32(color), duration }; for (int32 i = 0; i < cache.Vertices.Count();) { - l.Start = sphere.Center + cache.Vertices.Get()[i++] * sphere.Radius; - l.End = sphere.Center + cache.Vertices.Get()[i++] * sphere.Radius; + l.Start = centerF + cache.Vertices.Get()[i++] * radiusF; + l.End = centerF + cache.Vertices.Get()[i++] * radiusF; debugDrawData.DefaultLines.Add(l); } } @@ -1127,9 +1196,9 @@ void DebugDraw::DrawWireSphere(const BoundingSphere& sphere, const Color& color, Vertex l = { Float3::Zero, Color32(color) }; for (int32 i = 0; i < cache.Vertices.Count();) { - l.Position = sphere.Center + cache.Vertices.Get()[i++] * sphere.Radius; + l.Position = centerF + cache.Vertices.Get()[i++] * radiusF; debugDrawData.OneFrameLines.Add(l); - l.Position = sphere.Center + cache.Vertices.Get()[i++] * sphere.Radius; + l.Position = centerF + cache.Vertices.Get()[i++] * radiusF; debugDrawData.OneFrameLines.Add(l); } } @@ -1148,16 +1217,18 @@ void DebugDraw::DrawSphere(const BoundingSphere& sphere, const Color& color, flo list = duration > 0 ? &Context->DebugDrawDefault.DefaultTriangles : &Context->DebugDrawDefault.OneFrameTriangles; list->EnsureCapacity(list->Count() + SphereTriangleCache.Count()); + const Float3 centerF = sphere.Center - Context->Origin; + const float radiusF = (float)sphere.Radius; for (int32 i = 0; i < SphereTriangleCache.Count();) { - t.V0 = sphere.Center + SphereTriangleCache[i++] * sphere.Radius; - t.V1 = sphere.Center + SphereTriangleCache[i++] * sphere.Radius; - t.V2 = sphere.Center + SphereTriangleCache[i++] * sphere.Radius; + t.V0 = centerF + SphereTriangleCache[i++] * radiusF; + t.V1 = centerF + SphereTriangleCache[i++] * radiusF; + t.V2 = centerF + SphereTriangleCache[i++] * radiusF; list->Add(t); } } -void DebugDraw::DrawCircle(const Vector3& position, const Vector3& normal, float radius, const Color& color, float duration, bool depthTest) +void DebugDraw::DrawCircle(const Vector3& position, const Float3& normal, float radius, const Color& color, float duration, bool depthTest) { // Create matrix transform for unit circle points Matrix world, scale, matrix; @@ -1170,15 +1241,28 @@ void DebugDraw::DrawCircle(const Vector3& position, const Vector3& normal, float Float3::Cross(normal, Float3::Up, right); Float3::Cross(right, normal, up); Matrix::Scaling(radius, scale); - Matrix::CreateWorld(position, normal, up, world); + const Float3 positionF = position - Context->Origin; + Matrix::CreateWorld(positionF, normal, up, world); Matrix::Multiply(scale, world, matrix); // Draw lines of the unit circle after linear transform Float3 prev = Float3::Transform(CircleCache[0], matrix); + auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; for (int32 i = 1; i < DEBUG_DRAW_CIRCLE_VERTICES;) { Float3 cur = Float3::Transform(CircleCache[i++], matrix); - DrawLine(prev, cur, color, duration, depthTest); + if (duration > 0) + { + DebugLine l = { prev, cur, Color32(color), duration }; + debugDrawData.DefaultLines.Add(l); + } + else + { + Vertex l = { prev, Color32(color) }; + debugDrawData.OneFrameLines.Add(l); + l.Position = cur; + debugDrawData.OneFrameLines.Add(l); + } prev = cur; } } @@ -1195,18 +1279,13 @@ void DebugDraw::DrawTriangle(const Vector3& v0, const Vector3& v1, const Vector3 DebugTriangle t; t.Color = Color32(color); t.TimeLeft = duration; - t.V0 = v0; - t.V1 = v1; - t.V2 = v2; - + t.V0 = v0 - Context->Origin; + t.V1 = v1 - Context->Origin; + t.V2 = v2 - Context->Origin; if (depthTest) - { Context->DebugDrawDepthTest.Add(t); - } else - { Context->DebugDrawDefault.Add(t); - } } void DebugDraw::DrawTriangles(const Span& vertices, const Color& color, float duration, bool depthTest) @@ -1216,11 +1295,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Color& color, t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Float3 origin = Context->Origin; for (int32 i = 0; i < vertices.Length();) { - t.V0 = vertices.Get()[i++]; - t.V1 = vertices.Get()[i++]; - t.V2 = vertices.Get()[i++]; + t.V0 = vertices.Get()[i++] - origin; + t.V1 = vertices.Get()[i++] - origin; + t.V2 = vertices.Get()[i++] - origin; *dst++ = t; } } @@ -1232,11 +1312,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Matrix& transf t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); for (int32 i = 0; i < vertices.Length();) { - Float3::Transform(vertices.Get()[i++], transform, t.V0); - Float3::Transform(vertices.Get()[i++], transform, t.V1); - Float3::Transform(vertices.Get()[i++], transform, t.V2); + Float3::Transform(vertices.Get()[i++], transformF, t.V0); + Float3::Transform(vertices.Get()[i++], transformF, t.V1); + Float3::Transform(vertices.Get()[i++], transformF, t.V2); *dst++ = t; } } @@ -1258,11 +1339,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Span& i t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(indices.Length() / 3, duration, depthTest); + const Float3 origin = Context->Origin; for (int32 i = 0; i < indices.Length();) { - t.V0 = vertices[indices.Get()[i++]]; - t.V1 = vertices[indices.Get()[i++]]; - t.V2 = vertices[indices.Get()[i++]]; + t.V0 = vertices[indices.Get()[i++]] - origin; + t.V1 = vertices[indices.Get()[i++]] - origin; + t.V2 = vertices[indices.Get()[i++]] - origin; *dst++ = t; } } @@ -1274,11 +1356,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Span& i t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(indices.Length() / 3, duration, depthTest); + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); for (int32 i = 0; i < indices.Length();) { - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V0); - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V1); - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V2); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V0); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V1); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V2); *dst++ = t; } } @@ -1300,11 +1383,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Color& color, t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Double3 origin = Context->Origin; for (int32 i = 0; i < vertices.Length();) { - t.V0 = vertices.Get()[i++]; - t.V1 = vertices.Get()[i++]; - t.V2 = vertices.Get()[i++]; + t.V0 = vertices.Get()[i++] - origin; + t.V1 = vertices.Get()[i++] - origin; + t.V2 = vertices.Get()[i++] - origin; *dst++ = t; } } @@ -1316,11 +1400,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Matrix& trans t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); for (int32 i = 0; i < vertices.Length();) { - Float3::Transform(vertices.Get()[i++], transform, t.V0); - Float3::Transform(vertices.Get()[i++], transform, t.V1); - Float3::Transform(vertices.Get()[i++], transform, t.V2); + Float3::Transform(vertices.Get()[i++], transformF, t.V0); + Float3::Transform(vertices.Get()[i++], transformF, t.V1); + Float3::Transform(vertices.Get()[i++], transformF, t.V2); *dst++ = t; } } @@ -1342,11 +1427,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Span& t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(indices.Length() / 3, duration, depthTest); + const Double3 origin = Context->Origin; for (int32 i = 0; i < indices.Length();) { - t.V0 = vertices[indices.Get()[i++]]; - t.V1 = vertices[indices.Get()[i++]]; - t.V2 = vertices[indices.Get()[i++]]; + t.V0 = vertices[indices.Get()[i++]] - origin; + t.V1 = vertices[indices.Get()[i++]] - origin; + t.V2 = vertices[indices.Get()[i++]] - origin; *dst++ = t; } } @@ -1358,11 +1444,12 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Span& t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(indices.Length() / 3, duration, depthTest); + const Matrix transformF = transform * Matrix::Translation(-Context->Origin); for (int32 i = 0; i < indices.Length();) { - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V0); - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V1); - Float3::Transform(vertices[indices.Get()[i++]], transform, t.V2); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V0); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V1); + Float3::Transform(vertices[indices.Get()[i++]], transformF, t.V2); *dst++ = t; } } @@ -1384,11 +1471,12 @@ void DebugDraw::DrawWireTriangles(const Span& vertices, const Color& col t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Float3 origin = Context->Origin; for (int32 i = 0; i < vertices.Length();) { - t.V0 = vertices.Get()[i++]; - t.V1 = vertices.Get()[i++]; - t.V2 = vertices.Get()[i++]; + t.V0 = vertices.Get()[i++] - origin; + t.V1 = vertices.Get()[i++] - origin; + t.V2 = vertices.Get()[i++] - origin; *dst++ = t; } } @@ -1405,11 +1493,12 @@ void DebugDraw::DrawWireTriangles(const Span& vertices, const SpanOrigin; for (int32 i = 0; i < indices.Length();) { - t.V0 = vertices[indices.Get()[i++]]; - t.V1 = vertices[indices.Get()[i++]]; - t.V2 = vertices[indices.Get()[i++]]; + t.V0 = vertices[indices.Get()[i++]] - origin; + t.V1 = vertices[indices.Get()[i++]] - origin; + t.V2 = vertices[indices.Get()[i++]] - origin; *dst++ = t; } } @@ -1426,11 +1515,12 @@ void DebugDraw::DrawWireTriangles(const Span& vertices, const Color& co t.Color = Color32(color); t.TimeLeft = duration; auto dst = AppendTriangles(vertices.Length() / 3, duration, depthTest); + const Double3 origin = Context->Origin; for (int32 i = 0; i < vertices.Length();) { - t.V0 = vertices.Get()[i++]; - t.V1 = vertices.Get()[i++]; - t.V2 = vertices.Get()[i++]; + t.V0 = vertices.Get()[i++] - origin; + t.V1 = vertices.Get()[i++] - origin; + t.V2 = vertices.Get()[i++] - origin; *dst++ = t; } } @@ -1447,11 +1537,12 @@ void DebugDraw::DrawWireTriangles(const Span& vertices, const SpanOrigin; for (int32 i = 0; i < indices.Length();) { - t.V0 = vertices[indices.Get()[i++]]; - t.V1 = vertices[indices.Get()[i++]]; - t.V2 = vertices[indices.Get()[i++]]; + t.V0 = vertices[indices.Get()[i++]] - origin; + t.V1 = vertices[indices.Get()[i++]] - origin; + t.V2 = vertices[indices.Get()[i++]] - origin; *dst++ = t; } } @@ -1497,50 +1588,97 @@ void DebugDraw::DrawWireTube(const Vector3& position, const Quaternion& orientat const float halfLength = length / 2.0f; Matrix rotation, translation, world; Matrix::RotationQuaternion(orientation, rotation); - Matrix::Translation(position, translation); + const Float3 positionF = position - Context->Origin; + Matrix::Translation(positionF, translation); Matrix::Multiply(rotation, translation, world); // Write vertices -#define DRAW_WIRE_BOX_LINE(x1, y1, z1, x2, y2, z2) DrawLine(Float3::Transform(Float3(x1, y1, z1), world), Float3::Transform(Float3(x2, y2, z2), world), color, duration, depthTest) - for (float a = 0.0f; a < TWO_PI; a += step) + auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; + Color32 color32(color); + if (duration > 0) { - // Calculate sines and cosines - // TODO: optimize this stuff - float sinA = Math::Sin(a) * radius; - float cosA = Math::Cos(a) * radius; - float sinB = Math::Sin(a + step) * radius; - float cosB = Math::Cos(a + step) * radius; - - // First XY loop - DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosB, sinB, -halfLength); - - // Second loop - DRAW_WIRE_BOX_LINE(cosA, sinA, halfLength, cosB, sinB, halfLength); - - if (a >= PI) +#define DRAW_WIRE_BOX_LINE(x1, y1, z1, x2, y2, z2) debugDrawData.DefaultLines.Add({ Float3::Transform(Float3(x1, y1, z1), world), Float3::Transform(Float3(x2, y2, z2), world), color32, duration }); + for (float a = 0.0f; a < TWO_PI; a += step) { - // First XZ loop - DRAW_WIRE_BOX_LINE(cosA, 0, sinA - halfLength, cosB, 0, sinB - halfLength); + // Calculate sines and cosines + float sinA = Math::Sin(a) * radius; + float cosA = Math::Cos(a) * radius; + float sinB = Math::Sin(a + step) * radius; + float cosB = Math::Cos(a + step) * radius; - // First YZ loop - DRAW_WIRE_BOX_LINE(0, cosA, sinA - halfLength, 0, cosB, sinB - halfLength); + // First XY loop + DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosB, sinB, -halfLength); + + // Second loop + DRAW_WIRE_BOX_LINE(cosA, sinA, halfLength, cosB, sinB, halfLength); + + if (a >= PI) + { + // First XZ loop + DRAW_WIRE_BOX_LINE(cosA, 0, sinA - halfLength, cosB, 0, sinB - halfLength); + + // First YZ loop + DRAW_WIRE_BOX_LINE(0, cosA, sinA - halfLength, 0, cosB, sinB - halfLength); + } + else + { + // Second XZ loop + DRAW_WIRE_BOX_LINE(cosA, 0, sinA + halfLength, cosB, 0, sinB + halfLength); + + // Second YZ loop + DRAW_WIRE_BOX_LINE(0, cosA, sinA + halfLength, 0, cosB, sinB + halfLength); + } + + // Connection + if (Math::NearEqual(sinA, radius) || Math::NearEqual(cosA, radius) || Math::NearEqual(sinA, -radius) || Math::NearEqual(cosA, -radius)) + { + DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosA, sinA, halfLength); + } } - else +#undef DRAW_WIRE_BOX_LINE + } + else + { +#define DRAW_WIRE_BOX_LINE(x1, y1, z1, x2, y2, z2) debugDrawData.OneFrameLines.Add({ Float3::Transform(Float3(x1, y1, z1), world), color32 }); debugDrawData.OneFrameLines.Add({ Float3::Transform(Float3(x2, y2, z2), world), color32 }); + for (float a = 0.0f; a < TWO_PI; a += step) { - // Second XZ loop - DRAW_WIRE_BOX_LINE(cosA, 0, sinA + halfLength, cosB, 0, sinB + halfLength); + // Calculate sines and cosines + float sinA = Math::Sin(a) * radius; + float cosA = Math::Cos(a) * radius; + float sinB = Math::Sin(a + step) * radius; + float cosB = Math::Cos(a + step) * radius; - // Second YZ loop - DRAW_WIRE_BOX_LINE(0, cosA, sinA + halfLength, 0, cosB, sinB + halfLength); - } + // First XY loop + DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosB, sinB, -halfLength); - // Connection - if (Math::NearEqual(sinA, radius) || Math::NearEqual(cosA, radius) || Math::NearEqual(sinA, -radius) || Math::NearEqual(cosA, -radius)) - { - DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosA, sinA, halfLength); + // Second loop + DRAW_WIRE_BOX_LINE(cosA, sinA, halfLength, cosB, sinB, halfLength); + + if (a >= PI) + { + // First XZ loop + DRAW_WIRE_BOX_LINE(cosA, 0, sinA - halfLength, cosB, 0, sinB - halfLength); + + // First YZ loop + DRAW_WIRE_BOX_LINE(0, cosA, sinA - halfLength, 0, cosB, sinB - halfLength); + } + else + { + // Second XZ loop + DRAW_WIRE_BOX_LINE(cosA, 0, sinA + halfLength, cosB, 0, sinB + halfLength); + + // Second YZ loop + DRAW_WIRE_BOX_LINE(0, cosA, sinA + halfLength, 0, cosB, sinB + halfLength); + } + + // Connection + if (Math::NearEqual(sinA, radius) || Math::NearEqual(cosA, radius) || Math::NearEqual(sinA, -radius) || Math::NearEqual(cosA, -radius)) + { + DRAW_WIRE_BOX_LINE(cosA, sinA, -halfLength, cosA, sinA, halfLength); + } +#undef DRAW_WIRE_BOX_LINE } } -#undef DRAW_WIRE_BOX_LINE } } @@ -1575,7 +1713,8 @@ namespace DebugTriangle t; t.Color = Color32(color); t.TimeLeft = duration; - const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(position); + const Float3 positionF = position - Context->Origin; + const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(positionF); // Write triangles for (uint32 i = 0; i < DEBUG_DRAW_CYLINDER_VERTICES; i += 4) @@ -1631,7 +1770,8 @@ namespace DebugTriangle t; t.Color = Color32(color); t.TimeLeft = duration; - const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(position); + const Float3 positionF = position - Context->Origin; + const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(positionF); t.V0 = world.GetTranslation(); Float3 vertices[DEBUG_DRAW_CONE_RESOLUTION]; @@ -1716,7 +1856,8 @@ void DebugDraw::DrawArc(const Vector3& position, const Quaternion& orientation, list = duration > 0 ? &Context->DebugDrawDefault.DefaultTriangles : &Context->DebugDrawDefault.OneFrameTriangles; const int32 resolution = Math::CeilToInt((float)DEBUG_DRAW_CONE_RESOLUTION / TWO_PI * angle); const float angleStep = angle / (float)resolution; - const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(position); + const Float3 positionF = position - Context->Origin; + const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(positionF); float currentAngle = 0.0f; DebugTriangle t; t.Color = Color32(color); @@ -1742,7 +1883,8 @@ void DebugDraw::DrawWireArc(const Vector3& position, const Quaternion& orientati angle = TWO_PI; const int32 resolution = Math::CeilToInt((float)DEBUG_DRAW_CONE_RESOLUTION / TWO_PI * angle); const float angleStep = angle / (float)resolution; - const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(position); + const Float3 positionF = position - Context->Origin; + const Matrix world = Matrix::RotationQuaternion(orientation) * Matrix::Translation(positionF); float currentAngle = 0.0f; Float3 prevPos(world.GetTranslation()); if (angle >= TWO_PI) @@ -1768,8 +1910,8 @@ void DebugDraw::DrawWireArrow(const Vector3& position, const Quaternion& orienta Float3::Transform(Float3::Forward, orientation, direction); Float3::Transform(Float3::Up, orientation, up); Float3::Transform(Float3::Right, orientation, right); - const auto end = position + direction * (100.0f * scale); - const auto capEnd = position + direction * (70.0f * scale); + const Vector3 end = position + direction * (100.0f * scale); + const Vector3 capEnd = position + direction * (70.0f * scale); const float arrowSidesRatio = scale * 30.0f; DrawLine(position, end, color, duration, depthTest); @@ -1782,8 +1924,10 @@ void DebugDraw::DrawWireArrow(const Vector3& position, const Quaternion& orienta void DebugDraw::DrawBox(const BoundingBox& box, const Color& color, float duration, bool depthTest) { // Get corners - Float3 corners[8]; + Vector3 corners[8]; box.GetCorners(corners); + for (Vector3& c : corners) + c -= Context->Origin; // Draw triangles DebugTriangle t; @@ -1808,8 +1952,10 @@ void DebugDraw::DrawBox(const BoundingBox& box, const Color& color, float durati void DebugDraw::DrawBox(const OrientedBoundingBox& box, const Color& color, float duration, bool depthTest) { // Get corners - Float3 corners[8]; + Vector3 corners[8]; box.GetCorners(corners); + for (Vector3& c : corners) + c -= Context->Origin; // Draw triangles DebugTriangle t; @@ -1855,7 +2001,7 @@ void DebugDraw::DrawText(const StringView& text, const Vector3& position, const t.Text.Resize(text.Length() + 1); Platform::MemoryCopy(t.Text.Get(), text.Get(), text.Length() * sizeof(Char)); t.Text[text.Length()] = 0; - t.Transform = position; + t.Transform = position - Context->Origin; t.FaceCamera = true; t.Size = size; t.Color = color; @@ -1872,6 +2018,7 @@ void DebugDraw::DrawText(const StringView& text, const Transform& transform, con Platform::MemoryCopy(t.Text.Get(), text.Get(), text.Length() * sizeof(Char)); t.Text[text.Length()] = 0; t.Transform = transform; + t.Transform.Translation -= Context->Origin; t.FaceCamera = false; t.Size = size; t.Color = color; diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h index 95e640d7b..0fc690a3b 100644 --- a/Source/Engine/Debug/DebugDraw.h +++ b/Source/Engine/Debug/DebugDraw.h @@ -140,7 +140,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawCircle(const Vector3& position, const Vector3& normal, float radius, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawCircle(const Vector3& position, const Float3& normal, float radius, const Color& color, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangle. diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 574add86d..78e3757bd 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -201,6 +201,6 @@ DrawPass RenderView::GetShadowsDrawPassMask(ShadowsCastingMode shadowsMode) cons void RenderView::GetWorldMatrix(const Transform& transform, Matrix& world) const { - const Vector3 translation = transform.Translation - Origin; + const Float3 translation = transform.Translation - Origin; Matrix::Transformation(transform.Scale, transform.Orientation, translation, world); } diff --git a/Source/Engine/Graphics/RenderView.cs b/Source/Engine/Graphics/RenderView.cs index 7b54ab9ba..69de869e1 100644 --- a/Source/Engine/Graphics/RenderView.cs +++ b/Source/Engine/Graphics/RenderView.cs @@ -103,5 +103,16 @@ namespace FlaxEngine UpdateCachedData(); } + + /// + /// Calculates the world matrix for the given transformation instance rendering. + /// + /// The object transformation. + /// The output matrix. + public void GetWorldMatrix(ref Transform transform, out Matrix world) + { + Float3 translation = transform.Translation - Origin; + Matrix.Transformation(ref transform.Scale, ref transform.Orientation, ref translation, out world); + } } } diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 97af41f2b..df1359f7a 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -23,7 +23,8 @@ AnimatedModel::AnimatedModel(const SpawnParams& params) , _lastUpdateFrame(0) { GraphInstance.Object = this; - UpdateBounds(); + _box = _boxLocal = BoundingBox(Vector3::Zero); + _sphere = BoundingSphere(Vector3::Zero, 0.0f); SkinnedModel.Changed.Bind(this); SkinnedModel.Loaded.Bind(this); @@ -709,7 +710,7 @@ void AnimatedModel::Draw(RenderContext& renderContext) const DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass & (int32)renderContext.View.GetShadowsDrawPassMask(ShadowsMode)); if (SkinnedModel && SkinnedModel->IsLoaded() && drawModes != DrawPass::None) { - _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(GetPosition(), renderContext.View.Position)); + _lastMinDstSqr = Math::Min(_lastMinDstSqr, Vector3::DistanceSquared(_transform.Translation, renderContext.View.Position + renderContext.View.Origin)); if (_skinningData.IsReady()) { @@ -729,6 +730,7 @@ void AnimatedModel::Draw(RenderContext& renderContext) draw.DrawState = &_drawState; draw.DrawModes = drawModes; draw.Bounds = _sphere; + draw.Bounds.Center -= renderContext.View.Origin; draw.PerInstanceRandom = GetPerInstanceRandom(); draw.LODBias = LODBias; draw.ForcedLOD = ForcedLOD; diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index d4f634f64..a6d60fa12 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -27,7 +27,8 @@ void BoxCollider::SetSize(const Float3& value) void BoxCollider::DrawPhysicsDebug(RenderView& view) { - if (!view.CullingFrustum.Intersects(_sphere)) + const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius); + if (!view.CullingFrustum.Intersects(sphere)) return; if (view.Mode == ViewMode::PhysicsColliders && !GetIsTrigger()) DebugDraw::DrawBox(_bounds, _staticActor ? Color::CornflowerBlue : Color::Orchid, 0, true); diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp index 81f030a9a..84b16cb74 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp @@ -39,7 +39,8 @@ void CapsuleCollider::SetHeight(const float value) void CapsuleCollider::DrawPhysicsDebug(RenderView& view) { - if (!view.CullingFrustum.Intersects(_sphere)) + const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius); + if (!view.CullingFrustum.Intersects(sphere)) return; Quaternion rot; Quaternion::Multiply(_transform.Orientation, Quaternion::Euler(0, 90, 0), rot); diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp index 52c18978c..18eaf3882 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.cpp +++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp @@ -69,7 +69,8 @@ void MeshCollider::DrawPhysicsDebug(RenderView& view) { if (CollisionData && CollisionData->IsLoaded()) { - if (!view.CullingFrustum.Intersects(_sphere)) + const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius); + if (!view.CullingFrustum.Intersects(sphere)) return; if (view.Mode == ViewMode::PhysicsColliders && !GetIsTrigger()) { diff --git a/Source/Engine/Physics/Colliders/SphereCollider.cpp b/Source/Engine/Physics/Colliders/SphereCollider.cpp index a036d6d59..e0a4acbe9 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.cpp +++ b/Source/Engine/Physics/Colliders/SphereCollider.cpp @@ -27,7 +27,8 @@ void SphereCollider::SetRadius(const float value) void SphereCollider::DrawPhysicsDebug(RenderView& view) { - if (!view.CullingFrustum.Intersects(_sphere)) + const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius); + if (!view.CullingFrustum.Intersects(sphere)) return; if (view.Mode == ViewMode::PhysicsColliders && !GetIsTrigger()) DebugDraw::DrawSphere(_sphere, _staticActor ? Color::CornflowerBlue : Color::Orchid, 0, true); diff --git a/Source/Engine/Physics/Colliders/SplineCollider.cpp b/Source/Engine/Physics/Colliders/SplineCollider.cpp index 86680e0c5..75c61b6c3 100644 --- a/Source/Engine/Physics/Colliders/SplineCollider.cpp +++ b/Source/Engine/Physics/Colliders/SplineCollider.cpp @@ -88,7 +88,8 @@ bool SplineCollider::CanBeTrigger() const void SplineCollider::DrawPhysicsDebug(RenderView& view) { - if (!view.CullingFrustum.Intersects(_sphere)) + const BoundingSphere sphere(_sphere.Center - view.Origin, _sphere.Radius); + if (!view.CullingFrustum.Intersects(sphere)) return; if (view.Mode == ViewMode::PhysicsColliders && !GetIsTrigger()) DebugDraw::DrawTriangles(_vertexBuffer, _indexBuffer, Color::CornflowerBlue, 0, true);