Skip to content

Commit 75ddc43

Browse files
committed
Add simple collision debug viewmode
1 parent f480d4d commit 75ddc43

2 files changed

Lines changed: 196 additions & 2 deletions

File tree

Source/RuntimeMeshComponent/Private/RuntimeMeshComponentProxy.cpp

Lines changed: 187 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,85 @@ void FRuntimeMeshComponentSceneProxy::DrawStaticElements(FStaticPrimitiveDrawInt
226226
}
227227
}
228228

229+
bool FRuntimeMeshComponentSceneProxy::GetCollisionMeshElement(
230+
int32 LODIndex,
231+
int32 BatchIndex,
232+
int32 SectionIndex,
233+
uint8 InDepthPriorityGroup,
234+
const FMaterialRenderProxy* RenderProxy,
235+
FMeshBatch& OutMeshBatch) const
236+
{
237+
/*const FRuntimeMeshLODData& LOD = RuntimeMeshProxy->GetLOD(LODIndex);
238+
const FRuntimeMeshSectionProxy& Section = LOD.Sections[SectionIndex];
239+
const FRuntimeMeshVertexFactory& VFs = Section.Buffers->VertexFactory;
240+
const FVertexFactory* VertexFactory = &VFs;
241+
242+
243+
const bool bWireframe = false;
244+
const bool bRequiresAdjacencyInformation = false;
245+
const bool bUseReversedIndices = false;
246+
const bool bAllowPreCulledIndices = true;
247+
const bool bDitheredLODTransition = false;
248+
249+
FMeshBatchElement& OutMeshBatchElement = OutMeshBatch.Elements[0];
250+
OutMeshBatch.Type = PT_TriangleList;
251+
OutMeshBatch.VertexFactory = VertexFactory;
252+
253+
{
254+
OutMeshBatchElement.VertexFactoryUserData = VFs.GetUniformBuffer();
255+
OutMeshBatchElement.IndexBuffer = &Section.Buffers->IndexBuffer;
256+
OutMeshBatchElement.NumPrimitives = Section.NumTriangles;
257+
OutMeshBatchElement.MaxScreenSize = 0.0f;
258+
OutMeshBatchElement.MinScreenSize = -1.0f;
259+
OutMeshBatch.bDitheredLODTransition = false;
260+
}
261+
262+
if (OutMeshBatchElement.NumPrimitives > 0)
263+
{
264+
OutMeshBatch.LODIndex = LODIndex;
265+
#if STATICMESH_ENABLE_DEBUG_RENDERING
266+
OutMeshBatch.VisualizeLODIndex = LODIndex;
267+
#endif
268+
OutMeshBatch.ReverseCulling = false;
269+
OutMeshBatch.CastShadow = false;
270+
OutMeshBatch.DepthPriorityGroup = (ESceneDepthPriorityGroup)InDepthPriorityGroup;
271+
OutMeshBatch.LCI = NULL;
272+
OutMeshBatch.VertexFactory = VertexFactory;
273+
OutMeshBatch.MaterialRenderProxy = RenderProxy;
274+
275+
OutMeshBatchElement.MinVertexIndex = Section.MinVertexIndex;
276+
OutMeshBatchElement.MaxVertexIndex = Section.MaxVertexIndex;
277+
#if STATICMESH_ENABLE_DEBUG_RENDERING
278+
OutMeshBatchElement.VisualizeElementIndex = SectionIndex;
279+
#endif
280+
281+
return true;
282+
}
283+
else*/
284+
{
285+
return false;
286+
}
287+
}
288+
229289
void FRuntimeMeshComponentSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
230290
{
231291
SCOPE_CYCLE_COUNTER(STAT_RuntimeMeshComponentSceneProxy_GetDynamicMeshElements);
232292

233293
// Set up wireframe material (if needed)
234294
const bool bWireframe = AllowDebugViewmodes() && ViewFamily.EngineShowFlags.Wireframe;
235-
295+
const bool bProxyIsSelected = IsSelected();
296+
const FEngineShowFlags& EngineShowFlags = ViewFamily.EngineShowFlags;
297+
ECollisionTraceFlag CollisionTraceFlag = ECollisionTraceFlag::CTF_UseDefault;
298+
bool bDrawSimpleCollision = false, bDrawComplexCollision = false;
299+
if (IsValid(BodySetup))
300+
{
301+
CollisionTraceFlag = BodySetup->GetCollisionTraceFlag();
302+
bDrawSimpleCollision = EngineShowFlags.CollisionPawn;
303+
bDrawComplexCollision = EngineShowFlags.CollisionVisibility;
304+
}
305+
306+
bool bInCollisionView = bDrawSimpleCollision || bDrawComplexCollision;
307+
236308
FColoredMaterialRenderProxy* WireframeMaterialInstance = nullptr;
237309
if (bWireframe)
238310
{
@@ -241,7 +313,7 @@ void FRuntimeMeshComponentSceneProxy::GetDynamicMeshElements(const TArray<const
241313
Collector.RegisterOneFrameMaterialProxy(WireframeMaterialInstance);
242314
}
243315

244-
if (RuntimeMeshProxy->HasValidLODs())
316+
if (RuntimeMeshProxy->HasValidLODs() && !bInCollisionView)
245317
{
246318
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
247319
{
@@ -305,6 +377,119 @@ void FRuntimeMeshComponentSceneProxy::GetDynamicMeshElements(const TArray<const
305377
}
306378
#endif
307379
}
380+
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) //Collision debug view in editor
381+
FColor SimpleCollisionColor = FColor(255, 107, 2, 255);
382+
//FColor ComplexCollisionColor = FColor(0, 255, 255, 255);
383+
384+
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
385+
{
386+
if (VisibilityMap & (1 << ViewIndex))
387+
{
388+
//Complex collision
389+
/*if(AllowDebugViewmodes() && false)
390+
{
391+
// Should we draw the mesh wireframe to indicate we are using the mesh as collision
392+
bool bDrawComplexWireframeCollision = (EngineShowFlags.Collision && IsCollisionEnabled() && CollisionTraceFlag == ECollisionTraceFlag::CTF_UseComplexAsSimple);
393+
// Requested drawing complex in wireframe, but check that we are not using simple as complex
394+
bDrawComplexWireframeCollision |= bDrawComplexCollision && bWireframe;
395+
396+
// If drawing complex collision as solid or wireframe
397+
if(bDrawComplexWireframeCollision || (bInCollisionView && bDrawComplexCollision))
398+
{
399+
// If we have at least one valid LOD to draw
400+
if(RuntimeMeshProxy->HasValidLODs())
401+
{
402+
// Get LOD used for collision
403+
int32 DrawLOD = RuntimeMeshProxy->GetMinLOD();//FMath::Clamp(LODForCollision, 0, RenderData->LODResources.Num() - 1);
404+
const FRuntimeMeshLODData& LODModel = RuntimeMeshProxy->GetLOD(DrawLOD);
405+
406+
UMaterial* MaterialToUse = UMaterial::GetDefaultMaterial(MD_Surface);
407+
FLinearColor DrawCollisionColor = GetWireframeColor();
408+
// Collision view modes draw collision mesh as solid
409+
if(bInCollisionView)
410+
{
411+
MaterialToUse = GEngine->ShadedLevelColorationUnlitMaterial;
412+
}
413+
// Wireframe, choose color based on complex or simple
414+
else
415+
{
416+
MaterialToUse = GEngine->WireframeMaterial;
417+
DrawCollisionColor = (CollisionTraceFlag == ECollisionTraceFlag::CTF_UseComplexAsSimple) ? SimpleCollisionColor : ComplexCollisionColor;
418+
}
419+
420+
// Iterate over sections of that LOD
421+
for (int32 SectionIndex = 0; SectionIndex < LODModel.Sections.Num(); SectionIndex++)
422+
{
423+
// If this section has collision enabled
424+
if (LODModel.Sections[SectionIndex].bIsValid)
425+
{
426+
427+
// Create colored proxy
428+
FColoredMaterialRenderProxy* CollisionMaterialInstance = new FColoredMaterialRenderProxy(MaterialToUse->GetRenderProxy(), DrawCollisionColor);
429+
Collector.RegisterOneFrameMaterialProxy(CollisionMaterialInstance);
430+
431+
// Iterate over batches
432+
int32 nummeshbatches = 1; //GetNumMeshBatches();
433+
for (int32 BatchIndex = 0; BatchIndex < nummeshbatches; BatchIndex++)
434+
{
435+
FMeshBatch& CollisionElement = Collector.AllocateMesh();
436+
if (GetCollisionMeshElement(DrawLOD, BatchIndex, SectionIndex, SDPG_World, CollisionMaterialInstance, CollisionElement))
437+
{
438+
Collector.AddMesh(ViewIndex, CollisionElement);
439+
INC_DWORD_STAT_BY(STAT_StaticMeshTriangles, CollisionElement.GetNumPrimitives());
440+
}
441+
}
442+
}
443+
}
444+
}
445+
}
446+
}*/
447+
448+
// Draw simple collision as wireframe if 'show collision', collision is enabled, and we are not using the complex as the simple
449+
const bool bDrawSimpleWireframeCollision = (EngineShowFlags.Collision);
450+
451+
if((bDrawSimpleCollision || bDrawSimpleWireframeCollision) && BodySetup)
452+
{
453+
if(FMath::Abs(GetLocalToWorld().Determinant()) < SMALL_NUMBER)
454+
{
455+
// Catch this here or otherwise GeomTransform below will assert
456+
// This spams so commented out
457+
//UE_LOG(LogStaticMesh, Log, TEXT("Zero scaling not supported (%s)"), *StaticMesh->GetPathName());
458+
}
459+
else
460+
{
461+
const bool bDrawSolid = !bDrawSimpleWireframeCollision;
462+
463+
if(AllowDebugViewmodes() && bDrawSolid)
464+
{
465+
// Make a material for drawing solid collision stuff
466+
auto SolidMaterialInstance = new FColoredMaterialRenderProxy(
467+
GEngine->ShadedLevelColorationUnlitMaterial->GetRenderProxy(),
468+
SimpleCollisionColor
469+
);
470+
471+
Collector.RegisterOneFrameMaterialProxy(SolidMaterialInstance);
472+
473+
FTransform GeomTransform(GetLocalToWorld());
474+
BodySetup->AggGeom.GetAggGeom(GeomTransform, SimpleCollisionColor, SolidMaterialInstance, true, true, DrawsVelocity(), ViewIndex, Collector);
475+
}
476+
// wireframe
477+
else
478+
{
479+
FTransform GeomTransform(GetLocalToWorld());
480+
BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(SimpleCollisionColor, bProxyIsSelected, IsHovered()).ToFColor(true), NULL, false, false, DrawsVelocity(), ViewIndex, Collector);
481+
}
482+
}
483+
}
484+
485+
if(EngineShowFlags.MassProperties && DebugMassData.Num() > 0)
486+
{
487+
DebugMassData[0].DrawDebugMass(Collector.GetPDI(ViewIndex), FTransform(GetLocalToWorld()));
488+
}
489+
}
490+
}
491+
#endif
492+
308493
}
309494

310495

Source/RuntimeMeshComponent/Private/RuntimeMeshComponentProxy.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ class FRuntimeMeshComponentSceneProxy : public FPrimitiveSceneProxy
7272

7373
virtual void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) override;
7474

75+
/** Sets up a collision FMeshBatch for a specific LOD and element. Used to show complex collision in debug viewmodes */
76+
virtual bool GetCollisionMeshElement(
77+
int32 LODIndex,
78+
int32 BatchIndex,
79+
int32 ElementIndex,
80+
uint8 InDepthPriorityGroup,
81+
const FMaterialRenderProxy* RenderProxy,
82+
FMeshBatch& OutMeshBatch) const;
83+
7584
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override;
7685

7786

0 commit comments

Comments
 (0)