void DrawWireShape(NxShape *shape, const NxVec3& color) { switch(shape->getType()) { case NX_SHAPE_PLANE: DrawWirePlane(shape, color); break; case NX_SHAPE_BOX: DrawWireBox(shape, color); break; case NX_SHAPE_SPHERE: DrawWireSphere(shape, color); break; case NX_SHAPE_CAPSULE: DrawWireCapsule(shape, color); break; case NX_SHAPE_CONVEX: DrawWireConvex(shape, color); break; case NX_SHAPE_MESH: DrawWireMesh(shape, color); break; default: break; } }
void FSpringComponentVisualizer::DrawVisualization( const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI ) { if (const UPhysicsSpringComponent* SpringComp = Cast<const UPhysicsSpringComponent>(Component)) { //interpolate color by compression const float CompressionNormalized = SpringComp->GetNormalizedCompressionScalar(); float R = FMath::Lerp(RestColor.R, CompressedColor.R, CompressionNormalized); float G = FMath::Lerp(RestColor.G, CompressedColor.G, CompressionNormalized); float B = FMath::Lerp(RestColor.B, CompressedColor.B, CompressionNormalized); const FColor CurrentColor = SpringComp->bIsActive ? FColor(R, G, B) : DisabledColor; //draw capsule for spring sweep const FTransform& WorldTM = SpringComp->GetComponentToWorld(); const FVector SpringStart = WorldTM.GetLocation(); const FVector SpringEnd = SpringComp->GetSpringCurrentEndPoint(); const float HalfHeight = (SpringEnd - SpringStart).Size() * 0.5f + SpringComp->SpringRadius; DrawWireCapsule(PDI, FMath::Lerp(SpringStart, SpringEnd, 0.5f), WorldTM.GetUnitAxis(EAxis::Z), WorldTM.GetUnitAxis(EAxis::Y), WorldTM.GetUnitAxis(EAxis::X), CurrentColor, SpringComp->SpringRadius, HalfHeight, 25, SDPG_World); } }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_GetDynamicMeshElements_DrawDynamicElements ); const FMatrix& LocalToWorld = GetLocalToWorld(); const int32 CapsuleSides = FMath::Clamp<int32>(CapsuleRadius/4.f, 16, 64); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; const FLinearColor DrawCapsuleColor = GetViewSelectionColor(ShapeColor, *View, IsSelected(), IsHovered(), false, IsIndividuallySelected() ); FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); DrawWireCapsule( PDI, LocalToWorld.GetOrigin(), LocalToWorld.GetScaledAxis( EAxis::X ), LocalToWorld.GetScaledAxis( EAxis::Y ), LocalToWorld.GetScaledAxis( EAxis::Z ), DrawCapsuleColor, CapsuleRadius, CapsuleHalfHeight, CapsuleSides, SDPG_World ); } } }
void Update() { NxMat34 mat34; NxMat33 mat; NxQuat quat(0.0f,NxVec3(0,1,0)); mat.fromQuat(quat); NxBox worldBox; worldBox.extents = NxVec3(2, 2, 2); worldBox.rot = mat; NxSphere worldSphere; NxBounds3 worldBounds; NxCapsule worldCapsule; worldCapsule.radius = 2.0f; NxU32 nbPlanes = 2; NxPlane worldPlanes[2]; worldPlanes[0].set(NxVec3(-2,0,2), NxVec3(0,0,1)); worldPlanes[1].set(NxVec3(-2,0,2), NxVec3(1,0,0)); NxU32 nbDynamicShapes = gScene->getNbDynamicShapes(); NxU32 nbStaticShapes = gScene->getNbStaticShapes(); NxU32 nbShapes = 0; NxShapesType type; int i = 0; for (i = 0; i < 3; ++ i) { if (i == 0) { nbShapes = nbDynamicShapes; type = NX_DYNAMIC_SHAPES; switch(gOverlapType) { case OVERLAP_AABB: case OVERLAP_CHECK_AABB: worldBounds.set(gMIN, gMAX); break; case OVERLAP_OBB: case OVERLAP_CHECK_OBB: worldBox.center = gBoxCenter; break; case OVERLAP_CAPSULE: case OVERLAP_CHECK_CAPSULE: worldCapsule = NxCapsule(gCapsuleSegment, gCapsuleRadius); break; case OVERLAP_SPHERE: case OVERLAP_CHECK_SPHERE: worldSphere = NxSphere(gSphereCenter, gSphereRadius); break; } } else if (i == 1) { nbShapes = nbStaticShapes; type = NX_STATIC_SHAPES; switch(gOverlapType) { case OVERLAP_AABB: case OVERLAP_CHECK_AABB: worldBounds.set(gMIN+NxVec3(-6.0f,0,0),gMAX+NxVec3(-6.0f,0,0)); break; case OVERLAP_OBB: case OVERLAP_CHECK_OBB: worldBox.center = gBoxCenter+NxVec3(-6,0,0); break; case OVERLAP_CAPSULE: case OVERLAP_CHECK_CAPSULE: worldCapsule.p0.x = gCapsuleSegment.p0.x - 6.0f; worldCapsule.p1.x = gCapsuleSegment.p1.x - 6.0f; break; case OVERLAP_SPHERE: case OVERLAP_CHECK_SPHERE: worldSphere = NxSphere(gSphereCenter + NxVec3(-6,0,0), gSphereRadius); break; } } else if (i == 2) { nbShapes = nbStaticShapes + nbDynamicShapes; type = NX_ALL_SHAPES; switch(gOverlapType) { case OVERLAP_AABB: case OVERLAP_CHECK_AABB: worldBounds.set(gMIN+NxVec3(6.0f,0,0),gMAX+NxVec3(6.0f,0,0)); break; case OVERLAP_OBB: case OVERLAP_CHECK_OBB: worldBox.center = gBoxCenter+NxVec3(6,0,0); break; case OVERLAP_CAPSULE: case OVERLAP_CHECK_CAPSULE: worldCapsule.p0.x = gCapsuleSegment.p0.x + 6.0f; worldCapsule.p1.x = gCapsuleSegment.p1.x + 6.0f; break; case OVERLAP_SPHERE: case OVERLAP_CHECK_SPHERE: worldSphere = NxSphere(gSphereCenter + NxVec3(6,0,0), gSphereRadius); break; } } NxShape** shapes = (NxShape**)NxAlloca(nbShapes*sizeof(NxShape*)); for (NxU32 j = 0; j < nbShapes; j++) shapes[j] = NULL; NxU32 activeGroups = 0xffffffff; NxGroupsMask* groupsMask = NULL; bool bResult = true; float linewidth = 1.0f; switch(gOverlapType) { case OVERLAP_AABB: gScene->overlapAABBShapes(worldBounds, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask, true); NxCreateBox(worldBox, worldBounds, mat34); DrawWireBox(worldBox, NxVec3(1,0,0), linewidth); break; case OVERLAP_CHECK_AABB: bResult = gScene->checkOverlapAABB(worldBounds, type, activeGroups, groupsMask); NxCreateBox(worldBox, worldBounds, mat34); if (bResult == true) DrawWireBox(worldBox, NxVec3(1,0,0), linewidth); else DrawWireBox(worldBox, NxVec3(0,1,0), linewidth); break; case OVERLAP_OBB: gScene->overlapOBBShapes(worldBox, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask); DrawWireBox(worldBox, NxVec3(1,0,0), linewidth); break; case OVERLAP_CHECK_OBB: if (gScene->checkOverlapOBB(worldBox, type, activeGroups, groupsMask) == true) DrawWireBox(worldBox, NxVec3(1,0,0), linewidth); else DrawWireBox(worldBox, NxVec3(0,1,0), linewidth); break; case OVERLAP_CAPSULE: gScene->overlapCapsuleShapes(worldCapsule, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask); DrawWireCapsule(worldCapsule, NxVec3(1,0,0)); break; case OVERLAP_CHECK_CAPSULE: if (gScene->checkOverlapCapsule(worldCapsule, type,activeGroups, groupsMask) == true) DrawWireCapsule(worldCapsule, NxVec3(1,0,0)); else DrawWireCapsule(worldCapsule, NxVec3(0,1,0)); break; case OVERLAP_SPHERE: gScene->overlapSphereShapes(worldSphere, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask); DrawWireSphere(&worldSphere, NxVec3(1,0,0)); break; case OVERLAP_CHECK_SPHERE: if (gScene->checkOverlapSphere(worldSphere, type,activeGroups, groupsMask) == true) DrawWireSphere(&worldSphere, NxVec3(1,0,0)); else DrawWireSphere(&worldSphere, NxVec3(0,1,0)); break; case OVERLAP_CULL: gScene->cullShapes(nbPlanes, worldPlanes, type, nbShapes, shapes, &gShapeReport, activeGroups, groupsMask); DrawLine(NxVec3(-20,0,2), NxVec3(-2,0,2),NxVec3(1,0,0), linewidth); DrawLine(NxVec3(-2,0,-20), NxVec3(-2,0,2),NxVec3(1,0,0), linewidth); break; } } }
void FDebugRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { QUICK_SCOPE_CYCLE_COUNTER( STAT_DebugRenderSceneProxy_GetDynamicMeshElements ); // Draw solid spheres struct FMaterialCache { FMaterialCache() : bUseFakeLight(false) {} FMaterialRenderProxy* operator[](FLinearColor Color) { FMaterialRenderProxy* MeshColor = NULL; const uint32 HashKey = GetTypeHash(Color); if (MeshColorInstances.Contains(HashKey)) { MeshColor = *MeshColorInstances.Find(HashKey); } else { if (bUseFakeLight && SolidMeshMaterial.IsValid()) { MeshColor = new(FMemStack::Get()) FColoredMaterialRenderProxy( SolidMeshMaterial->GetRenderProxy(false, false), Color, "GizmoColor" ); } else { MeshColor = new(FMemStack::Get()) FColoredMaterialRenderProxy(GEngine->DebugMeshMaterial->GetRenderProxy(false, false), Color); } MeshColorInstances.Add(HashKey, MeshColor); } return MeshColor; } void UseFakeLight(bool UseLight, class UMaterial* InMaterial) { bUseFakeLight = UseLight; SolidMeshMaterial = InMaterial; } TMap<uint32, FMaterialRenderProxy*> MeshColorInstances; TWeakObjectPtr<class UMaterial> SolidMeshMaterial; bool bUseFakeLight; }; FMaterialCache MaterialCache[2]; MaterialCache[1].UseFakeLight(true, SolidMeshMaterial.Get()); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); // Draw Lines const int32 LinesNum = Lines.Num(); PDI->AddReserveLines(SDPG_World, LinesNum, false, false); for (const auto& CurrentLine : Lines) { PDI->DrawLine(CurrentLine.Start, CurrentLine.End, CurrentLine.Color, SDPG_World, CurrentLine.Thickness, 0, CurrentLine.Thickness > 0); } // Draw Dashed Lines for(int32 DashIdx=0; DashIdx<DashedLines.Num(); DashIdx++) { const FDashedLine& Dash = DashedLines[DashIdx]; DrawDashedLine(PDI, Dash.Start, Dash.End, Dash.Color, Dash.DashSize, SDPG_World); } // Draw Arrows const uint32 ArrowsNum = ArrowLines.Num(); PDI->AddReserveLines(SDPG_World, 5 * ArrowsNum, false, false); for (const auto& CurrentArrow : ArrowLines) { DrawLineArrow(PDI, CurrentArrow.Start, CurrentArrow.End, CurrentArrow.Color, 8.0f); } // Draw Stars for(int32 StarIdx=0; StarIdx<Stars.Num(); StarIdx++) { const FWireStar& Star = Stars[StarIdx]; DrawWireStar(PDI, Star.Position, Star.Size, Star.Color, SDPG_World); } // Draw Cylinders for(const auto& Cylinder : Cylinders) { if (DrawType == SolidAndWireMeshes || DrawType == WireMesh) { DrawWireCylinder(PDI, Cylinder.Base, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Cylinder.Color, Cylinder.Radius, Cylinder.HalfHeight, (DrawType == SolidAndWireMeshes) ? 9 : 16, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true); } if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh) { GetCylinderMesh(Cylinder.Base, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Cylinder.Radius, Cylinder.HalfHeight, 16, MaterialCache[0][Cylinder.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector); } } // Draw Boxes for(const auto& Box : Boxes) { if (DrawType == SolidAndWireMeshes || DrawType == WireMesh) { DrawWireBox(PDI, Box.Transform.ToMatrixWithScale(), Box.Box, Box.Color, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true); } if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh) { GetBoxMesh(FTransform(Box.Box.GetCenter()).ToMatrixNoScale() * Box.Transform.ToMatrixWithScale(), Box.Box.GetExtent(), MaterialCache[0][Box.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector); } } // Draw Boxes TArray<FVector> Verts; for (auto& CurrentCone : Cones) { if (DrawType == SolidAndWireMeshes || DrawType == WireMesh) { DrawWireCone(PDI, Verts, CurrentCone.ConeToWorld, 1, CurrentCone.Angle2, (DrawType == SolidAndWireMeshes) ? 9 : 16, CurrentCone.Color, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true); } if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh) { GetConeMesh(CurrentCone.ConeToWorld, CurrentCone.Angle1, CurrentCone.Angle2, 16, MaterialCache[0][CurrentCone.Color.WithAlpha(DrawAlpha)], SDPG_World, ViewIndex, Collector); } } for (auto It = Spheres.CreateConstIterator(); It; ++It) { if (PointInView(It->Location, View)) { if (DrawType == SolidAndWireMeshes || DrawType == WireMesh) { DrawWireSphere(PDI, It->Location, It->Color.WithAlpha(255), It->Radius, 20, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true); } if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh) { GetSphereMesh(It->Location, FVector(It->Radius), 20, 7, MaterialCache[0][It->Color.WithAlpha(DrawAlpha)], SDPG_World, false, ViewIndex, Collector); } } } for (auto It = Capsles.CreateConstIterator(); It; ++It) { if (PointInView(It->Location, View)) { if (DrawType == SolidAndWireMeshes || DrawType == WireMesh) { const float HalfAxis = FMath::Max<float>(It->HalfHeight - It->Radius, 1.f); const FVector BottomEnd = It->Location + It->Radius * It->Z; const FVector TopEnd = BottomEnd + (2 * HalfAxis) * It->Z; const float CylinderHalfHeight = (TopEnd - BottomEnd).Size() * 0.5; const FVector CylinderLocation = BottomEnd + CylinderHalfHeight * It->Z; DrawWireCapsule(PDI, CylinderLocation, It->X, It->Y, It->Z, It->Color, It->Radius, It->HalfHeight, (DrawType == SolidAndWireMeshes) ? 9 : 16, SDPG_World, DrawType == SolidAndWireMeshes ? 2 : 0, 0, true); } if (DrawType == SolidAndWireMeshes || DrawType == SolidMesh) { GetCapsuleMesh(It->Location, It->X, It->Y, It->Z, It->Color, It->Radius, It->HalfHeight, 16, MaterialCache[0][It->Color.WithAlpha(DrawAlpha)], SDPG_World, false, ViewIndex, Collector); } } } for (const auto& Mesh : Meshes) { FDynamicMeshBuilder MeshBuilder; MeshBuilder.AddVertices(Mesh.Vertices); MeshBuilder.AddTriangles(Mesh.Indices); MeshBuilder.GetMesh(FMatrix::Identity, MaterialCache[Mesh.Color.A == 255 ? 1 : 0][Mesh.Color.WithAlpha(DrawAlpha)], SDPG_World, false, false, ViewIndex, Collector); } } } }
void FAudioComponentVisualizer::DrawVisualization( const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI ) { if(View->Family->EngineShowFlags.AudioRadius) { const UAudioComponent* AudioComp = Cast<const UAudioComponent>(Component); if(AudioComp != NULL) { const FTransform& Transform = AudioComp->ComponentToWorld; TMultiMap<EAttenuationShape::Type, FAttenuationSettings::AttenuationShapeDetails> ShapeDetailsMap; AudioComp->CollectAttenuationShapesForVisualization(ShapeDetailsMap); FVector Translation = Transform.GetTranslation(); FVector UnitXAxis = Transform.GetUnitAxis( EAxis::X ); FVector UnitYAxis = Transform.GetUnitAxis( EAxis::Y ); FVector UnitZAxis = Transform.GetUnitAxis( EAxis::Z ); for ( auto It = ShapeDetailsMap.CreateConstIterator(); It; ++It ) { FColor AudioOuterRadiusColor(255, 153, 0); FColor AudioInnerRadiusColor(216, 130, 0); const FAttenuationSettings::AttenuationShapeDetails& ShapeDetails = It.Value(); switch(It.Key()) { case EAttenuationShape::Box: if (ShapeDetails.Falloff > 0.f) { DrawOrientedWireBox( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, ShapeDetails.Extents + FVector(ShapeDetails.Falloff), AudioOuterRadiusColor, SDPG_World); DrawOrientedWireBox( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, ShapeDetails.Extents, AudioInnerRadiusColor, SDPG_World); } else { DrawOrientedWireBox( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, ShapeDetails.Extents, AudioOuterRadiusColor, SDPG_World); } break; case EAttenuationShape::Capsule: if (ShapeDetails.Falloff > 0.f) { DrawWireCapsule( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, AudioOuterRadiusColor, ShapeDetails.Extents.Y + ShapeDetails.Falloff, ShapeDetails.Extents.X + ShapeDetails.Falloff, 25, SDPG_World); DrawWireCapsule( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, AudioInnerRadiusColor, ShapeDetails.Extents.Y, ShapeDetails.Extents.X, 25, SDPG_World); } else { DrawWireCapsule( PDI, Translation, UnitXAxis, UnitYAxis, UnitZAxis, AudioOuterRadiusColor, ShapeDetails.Extents.Y, ShapeDetails.Extents.X, 25, SDPG_World); } break; case EAttenuationShape::Cone: { FTransform Origin = Transform; Origin.SetScale3D(FVector(1.f)); Origin.SetTranslation(Translation - (UnitXAxis * ShapeDetails.ConeOffset)); if (ShapeDetails.Falloff > 0.f || ShapeDetails.Extents.Z > 0.f) { float ConeRadius = ShapeDetails.Extents.X + ShapeDetails.Falloff + ShapeDetails.ConeOffset; float ConeAngle = ShapeDetails.Extents.Y + ShapeDetails.Extents.Z; DrawWireSphereCappedCone(PDI, Origin, ConeRadius, ConeAngle, 16, 4, 10, AudioOuterRadiusColor, SDPG_World); ConeRadius = ShapeDetails.Extents.X + ShapeDetails.ConeOffset; ConeAngle = ShapeDetails.Extents.Y; DrawWireSphereCappedCone(PDI, Origin, ConeRadius, ConeAngle, 16, 4, 10, AudioInnerRadiusColor, SDPG_World ); } else { const float ConeRadius = ShapeDetails.Extents.X + ShapeDetails.ConeOffset; const float ConeAngle = ShapeDetails.Extents.Y; DrawWireSphereCappedCone(PDI, Origin, ConeRadius, ConeAngle, 16, 4, 10, AudioOuterRadiusColor, SDPG_World ); } } break; case EAttenuationShape::Sphere: if (ShapeDetails.Falloff > 0.f) { DrawWireSphereAutoSides(PDI, Translation, AudioOuterRadiusColor, ShapeDetails.Extents.X + ShapeDetails.Falloff, SDPG_World); DrawWireSphereAutoSides(PDI, Translation, AudioInnerRadiusColor, ShapeDetails.Extents.X, SDPG_World); } else { DrawWireSphereAutoSides(PDI, Translation, AudioOuterRadiusColor, ShapeDetails.Extents.X, SDPG_World); } break; default: check(false); } } } } }