Optimize debug drawing of terrain shape in Physics Colliders view mode

#3469
This commit is contained in:
Wojtek Figat
2025-05-31 23:27:51 +02:00
parent 11dec8e868
commit 0f3044ae72
6 changed files with 78 additions and 11 deletions

View File

@@ -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<Float3>& 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<Float3>& vertices, const Color& color, float duration, bool depthTest)
{
DrawTriangles(Span<Float3>(vertices.Get(), vertices.Count()), color, duration, depthTest);

View File

@@ -296,12 +296,21 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// Draws the triangles.
/// </summary>
/// <param name="vertices">The triangle vertices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the provided vertex buffer that contains groups of 3 Vertex elements per-triangle.
/// </summary>
/// <param name="triangles">The GPU buffer with vertices for triangles (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(GPUBuffer* triangles, const Matrix& transform, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
/// </summary>
@@ -315,7 +324,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// Draws the triangles.
/// </summary>
/// <param name="vertices">The triangle vertices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -336,7 +345,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// </summary>
/// <param name="vertices">The triangle vertices list.</param>
/// <param name="indices">The triangle indices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -357,7 +366,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// </summary>
/// <param name="vertices">The triangle vertices list.</param>
/// <param name="indices">The triangle indices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -376,7 +385,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// Draws the triangles.
/// </summary>
/// <param name="vertices">The triangle vertices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -395,7 +404,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// Draws the triangles.
/// </summary>
/// <param name="vertices">The triangle vertices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -416,7 +425,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// </summary>
/// <param name="vertices">The triangle vertices list.</param>
/// <param name="indices">The triangle indices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
@@ -437,7 +446,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// </summary>
/// <param name="vertices">The triangle vertices list.</param>
/// <param name="indices">The triangle indices list (must have multiple of 3 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="transform">The custom matrix used to transform all triangle vertices.</param>
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>

View File

@@ -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;

View File

@@ -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);

View File

@@ -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<Vertex> 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<Vector3>& 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)

View File

@@ -49,6 +49,8 @@ private:
#endif
#if USE_EDITOR
Array<Vector3> _collisionTriangles; // TODO: large-worlds
class GPUBuffer* _collisionTrianglesBuffer = nullptr;
bool _collisionTrianglesBufferDirty = true;
#endif
Array<Float3> _collisionVertices; // TODO: large-worlds