From 0f3044ae722db1c157370b79d20af9f76ac16ec8 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 31 May 2025 23:27:51 +0200 Subject: [PATCH] Optimize debug drawing of terrain shape in Physics Colliders view mode #3469 --- Source/Engine/Debug/DebugDraw.cpp | 25 ++++++++++++++++-- Source/Engine/Debug/DebugDraw.h | 25 ++++++++++++------ Source/Engine/Physics/Actors/Cloth.cpp | 1 + Source/Engine/Terrain/Terrain.cpp | 1 + Source/Engine/Terrain/TerrainPatch.cpp | 35 +++++++++++++++++++++++++- Source/Engine/Terrain/TerrainPatch.h | 2 ++ 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index a026267cc..44f0f2ce1 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -99,6 +99,7 @@ struct DebugGeometryBuffer { GPUBuffer* Buffer; float TimeLeft; + bool Lines; Matrix Transform; }; @@ -810,6 +811,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe defaultWireTriangles = WriteLists(vertexCounter, Context->DebugDrawDefault.DefaultWireTriangles, Context->DebugDrawDefault.OneFrameWireTriangles); { PROFILE_CPU_NAMED("Flush"); + ZoneValue(DebugDrawVB->Data.Count() / 1024); // Size in kB DebugDrawVB->Flush(context); } } @@ -869,8 +871,8 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe Matrix mvp; Matrix::Multiply(geometry.Transform, vp, mvp); Matrix::Transpose(mvp, tmp.ViewProjection); + auto state = data.EnableDepthTest ? (geometry.Lines ? &DebugDrawPsLinesDepthTest : &DebugDrawPsTrianglesDepthTest) : (geometry.Lines ? &DebugDrawPsLinesDefault : &DebugDrawPsTrianglesDefault); context->UpdateCB(cb, &tmp); - auto state = data.EnableDepthTest ? &DebugDrawPsLinesDepthTest : &DebugDrawPsLinesDefault; context->SetState(state->Get(enableDepthWrite, true)); context->BindVB(ToSpan(&geometry.Buffer, 1)); context->Draw(0, geometry.Buffer->GetElementsCount()); @@ -918,8 +920,9 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe Matrix mvp; Matrix::Multiply(geometry.Transform, vp, mvp); Matrix::Transpose(mvp, tmp.ViewProjection); + auto state = geometry.Lines ? &DebugDrawPsLinesDefault : &DebugDrawPsTrianglesDefault; context->UpdateCB(cb, &tmp); - context->SetState(DebugDrawPsLinesDefault.Get(false, false)); + context->SetState(state->Get(false, false)); context->BindVB(ToSpan(&geometry.Buffer, 1)); context->Draw(0, geometry.Buffer->GetElementsCount()); } @@ -1164,6 +1167,7 @@ void DebugDraw::DrawLines(GPUBuffer* lines, const Matrix& transform, float durat auto& geometry = debugDrawData.GeometryBuffers.AddOne(); geometry.Buffer = lines; geometry.TimeLeft = duration; + geometry.Lines = true; geometry.Transform = transform * Matrix::Translation(-Context->Origin); } @@ -1520,6 +1524,23 @@ void DebugDraw::DrawTriangles(const Span& vertices, const Matrix& transf } } +void DebugDraw::DrawTriangles(GPUBuffer* triangles, const Matrix& transform, float duration, bool depthTest) +{ + if (triangles == nullptr || triangles->GetSize() == 0) + return; + if (triangles->GetSize() % (sizeof(Vertex) * 3) != 0) + { + DebugLog::ThrowException("Cannot draw debug lines with incorrect amount of items in array"); + return; + } + auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault; + auto& geometry = debugDrawData.GeometryBuffers.AddOne(); + geometry.Buffer = triangles; + geometry.TimeLeft = duration; + geometry.Lines = false; + geometry.Transform = transform * Matrix::Translation(-Context->Origin); +} + void DebugDraw::DrawTriangles(const Array& vertices, const Color& color, float duration, bool depthTest) { DrawTriangles(Span(vertices.Get(), vertices.Count()), color, duration, depthTest); diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h index aa3836105..c3ea5f254 100644 --- a/Source/Engine/Debug/DebugDraw.h +++ b/Source/Engine/Debug/DebugDraw.h @@ -296,12 +296,21 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// Draws the triangles. /// /// The triangle vertices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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 DrawTriangles(const Span& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); + /// + /// Draws the triangles using the provided vertex buffer that contains groups of 3 Vertex elements per-triangle. + /// + /// The GPU buffer with vertices for triangles (must have multiple of 3 elements). + /// The custom matrix used to transform all triangle vertices. + /// 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 DrawTriangles(GPUBuffer* triangles, const Matrix& transform, float duration = 0.0f, bool depthTest = true); + /// /// Draws the triangles. /// @@ -315,7 +324,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// Draws the triangles. /// /// The triangle vertices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -336,7 +345,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// /// The triangle vertices list. /// The triangle indices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -357,7 +366,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// /// The triangle vertices list. /// The triangle indices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -376,7 +385,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// Draws the triangles. /// /// The triangle vertices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -395,7 +404,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// Draws the triangles. /// /// The triangle vertices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -416,7 +425,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// /// The triangle vertices list. /// The triangle indices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. @@ -437,7 +446,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// /// The triangle vertices list. /// The triangle indices list (must have multiple of 3 elements). - /// The custom matrix used to transform all line vertices. + /// The custom matrix used to transform all triangle vertices. /// 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. diff --git a/Source/Engine/Physics/Actors/Cloth.cpp b/Source/Engine/Physics/Actors/Cloth.cpp index 889a0874e..b184bfbda 100644 --- a/Source/Engine/Physics/Actors/Cloth.cpp +++ b/Source/Engine/Physics/Actors/Cloth.cpp @@ -335,6 +335,7 @@ void Cloth::DrawPhysicsDebug(RenderView& view) #if WITH_CLOTH && COMPILE_WITH_DEBUG_DRAW if (_cloth) { + PROFILE_CPU(); const ModelInstanceActor::MeshReference mesh = GetMesh(); if (mesh.Actor == nullptr) return; diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp index b39b7ef2f..f8c9bc22e 100644 --- a/Source/Engine/Terrain/Terrain.cpp +++ b/Source/Engine/Terrain/Terrain.cpp @@ -240,6 +240,7 @@ void Terrain::DrawChunk(const RenderContext& renderContext, const Int2& patchCoo void Terrain::DrawPhysicsDebug(RenderView& view) { + PROFILE_CPU(); for (int32 pathIndex = 0; pathIndex < _patches.Count(); pathIndex++) { _patches[pathIndex]->DrawPhysicsDebug(view); diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp index b2f668a9d..1c754d843 100644 --- a/Source/Engine/Terrain/TerrainPatch.cpp +++ b/Source/Engine/Terrain/TerrainPatch.cpp @@ -104,6 +104,8 @@ void TerrainPatch::Init(Terrain* terrain, int16 x, int16 z) #endif #if USE_EDITOR _collisionTriangles.Resize(0); + SAFE_DELETE_GPU_RESOURCE(_collisionTrianglesBuffer); + _collisionTrianglesBufferDirty = true; #endif _collisionVertices.Resize(0); } @@ -120,6 +122,9 @@ TerrainPatch::~TerrainPatch() #if TERRAIN_USE_PHYSICS_DEBUG SAFE_DELETE_GPU_RESOURCE(_debugLines); #endif +#if USE_EDITOR + SAFE_DELETE_GPU_RESOURCE(_collisionTrianglesBuffer); +#endif } RawDataAsset* TerrainPatch::GetHeightfield() const @@ -2225,6 +2230,8 @@ void TerrainPatch::DestroyCollision() #endif #if USE_EDITOR _collisionTriangles.Resize(0); + SAFE_DELETE(_collisionTrianglesBuffer); + _collisionTrianglesBufferDirty = true; #endif _collisionVertices.Resize(0); } @@ -2317,7 +2324,32 @@ void TerrainPatch::DrawPhysicsDebug(RenderView& view) return; if (view.Mode == ViewMode::PhysicsColliders) { - DEBUG_DRAW_TRIANGLES(GetCollisionTriangles(), Color::DarkOliveGreen, 0, true); + const auto& triangles = GetCollisionTriangles(); + typedef DebugDraw::Vertex Vertex; + if (!_collisionTrianglesBuffer) + _collisionTrianglesBuffer = GPUDevice::Instance->CreateBuffer(TEXT("Terrain.CollisionTriangles")); + const uint32 count = triangles.Count(); + if (_collisionTrianglesBuffer->GetElementsCount() != count) + { + if (_collisionTrianglesBuffer->Init(GPUBufferDescription::Vertex(Vertex::GetLayout(), sizeof(Vertex), count))) + return; + _collisionTrianglesBufferDirty = true; + } + if (_collisionTrianglesBufferDirty) + { + const Color32 color(Color::DarkOliveGreen); + Array vertices; + vertices.Resize((int32)count); + const Vector3* src = triangles.Get(); + Vertex* dst = vertices.Get(); + for (uint32 i = 0; i < count; i++) + { + dst[i] = { (Float3)src[i], color }; + } + _collisionTrianglesBuffer->SetData(vertices.Get(), _collisionTrianglesBuffer->GetSize()); + _collisionTrianglesBufferDirty = false; + } + DebugDraw::DrawTriangles(_collisionTrianglesBuffer, Matrix::Identity, 0, true); } else { @@ -2351,6 +2383,7 @@ const Array& TerrainPatch::GetCollisionTriangles() PhysicsBackend::GetHeightFieldSize(_physicsHeightField, rows, cols); _collisionTriangles.Resize((rows - 1) * (cols - 1) * 6); + _collisionTrianglesBufferDirty = true; Vector3* data = _collisionTriangles.Get(); #define GET_VERTEX(x, y) Vector3 v##x##y((float)(row + (x)), PhysicsBackend::GetHeightFieldHeight(_physicsHeightField, row + (x), col + (y)) / TERRAIN_PATCH_COLLISION_QUANTIZATION, (float)(col + (y))); Vector3::Transform(v##x##y, world, v##x##y) diff --git a/Source/Engine/Terrain/TerrainPatch.h b/Source/Engine/Terrain/TerrainPatch.h index 8e4277068..7d85c5b1c 100644 --- a/Source/Engine/Terrain/TerrainPatch.h +++ b/Source/Engine/Terrain/TerrainPatch.h @@ -49,6 +49,8 @@ private: #endif #if USE_EDITOR Array _collisionTriangles; // TODO: large-worlds + class GPUBuffer* _collisionTrianglesBuffer = nullptr; + bool _collisionTrianglesBufferDirty = true; #endif Array _collisionVertices; // TODO: large-worlds