virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_LineBatcherSceneProxy_GetDynamicMeshElements ); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); for (int32 i = 0; i < Lines.Num(); i++) { PDI->DrawLine(Lines[i].Start, Lines[i].End, Lines[i].Color, Lines[i].DepthPriority, Lines[i].Thickness); } for (int32 i = 0; i < Points.Num(); i++) { PDI->DrawPoint(Points[i].Position, Points[i].Color, Points[i].PointSize, Points[i].DepthPriority); } for (int32 i = 0; i < Meshes.Num(); i++) { static FVector const PosX(1.f,0,0); static FVector const PosY(0,1.f,0); static FVector const PosZ(0,0,1.f); FBatchedMesh const& M = Meshes[i]; // this seems far from optimal in terms of perf, but it's for debugging FDynamicMeshBuilder MeshBuilder; // set up geometry for (int32 VertIdx=0; VertIdx < M.MeshVerts.Num(); ++VertIdx) { MeshBuilder.AddVertex( M.MeshVerts[VertIdx], FVector2D::ZeroVector, PosX, PosY, PosZ, FColor::White ); } //MeshBuilder.AddTriangles(M.MeshIndices); for (int32 Idx=0; Idx < M.MeshIndices.Num(); Idx+=3) { MeshBuilder.AddTriangle( M.MeshIndices[Idx], M.MeshIndices[Idx+1], M.MeshIndices[Idx+2] ); } FMaterialRenderProxy* const MaterialRenderProxy = new(FMemStack::Get()) FColoredMaterialRenderProxy(GEngine->DebugMeshMaterial->GetRenderProxy(false), M.Color); MeshBuilder.GetMesh(FMatrix::Identity, MaterialRenderProxy, M.DepthPriority, false, false, ViewIndex, Collector); } } } }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_BoxSceneProxy_GetDynamicMeshElements ); const FMatrix& LocalToWorld = GetLocalToWorld(); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; const FLinearColor DrawColor = GetViewSelectionColor(BoxColor, *View, IsSelected(), IsHovered(), false, IsIndividuallySelected() ); FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); DrawOrientedWireBox(PDI, LocalToWorld.GetOrigin(), LocalToWorld.GetScaledAxis( EAxis::X ), LocalToWorld.GetScaledAxis( EAxis::Y ), LocalToWorld.GetScaledAxis( EAxis::Z ), BoxExtents, DrawColor, 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 FTextRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { QUICK_SCOPE_CYCLE_COUNTER( STAT_TextRenderSceneProxy_GetDynamicMeshElements ); // Vertex factory will not been initialized when the text string is empty or font is invalid. if(VertexFactory.IsInitialized()) { for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; // Draw the mesh. FMeshBatch& Mesh = Collector.AllocateMesh(); FMeshBatchElement& BatchElement = Mesh.Elements[0]; BatchElement.IndexBuffer = &IndexBuffer; Mesh.VertexFactory = &VertexFactory; BatchElement.PrimitiveUniformBufferResource = &GetUniformBuffer(); BatchElement.FirstIndex = 0; BatchElement.NumPrimitives = IndexBuffer.Indices.Num() / 3; BatchElement.MinVertexIndex = 0; BatchElement.MaxVertexIndex = VertexBuffer.Vertices.Num() - 1; Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); Mesh.bDisableBackfaceCulling = false; Mesh.Type = PT_TriangleList; Mesh.DepthPriorityGroup = SDPG_World; const bool bUseSelectedMaterial = GIsEditor && (View->Family->EngineShowFlags.Selection) ? IsSelected() : false; Mesh.MaterialRenderProxy = TextMaterial->GetRenderProxy(bUseSelectedMaterial); Mesh.bCanApplyViewModeOverrides = !bAlwaysRenderAsText; Collector.AddMesh(ViewIndex, Mesh); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) RenderBounds(Collector.GetPDI(ViewIndex), View->Family->EngineShowFlags, GetBounds(), IsSelected()); #endif } } } }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { if (SkeletalMeshComponent->bDrawMesh) { // We don't want to draw the mesh geometry to the hit testing render target // so that we can get to triangle strips that are partially obscured by other // triangle strips easier. const bool bSelectable = false; GetMeshElementsConditionallySelectable(Views, ViewFamily, bSelectable, VisibilityMap, Collector); } //@todo - the rendering thread should never read from UObjects directly! These are race conditions, the properties should be mirrored on the proxy if( SkeletalMeshComponent->MeshObject && (SkeletalMeshComponent->bDrawNormals || SkeletalMeshComponent->bDrawTangents || SkeletalMeshComponent->bDrawBinormals) ) { for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { SkeletalMeshComponent->MeshObject->DrawVertexElements(Collector.GetPDI(ViewIndex), SkeletalMeshComponent->ComponentToWorld, SkeletalMeshComponent->bDrawNormals, SkeletalMeshComponent->bDrawTangents, SkeletalMeshComponent->bDrawBinormals); } } } }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_DrawFrustumSceneProxy_DrawDynamicElements ); FVector Direction(1,0,0); FVector LeftVector(0,1,0); FVector UpVector(0,0,1); FVector Verts[8]; // FOVAngle controls the horizontal angle. const float HozHalfAngleInRadians = FMath::DegreesToRadians(FrustumAngle * 0.5f); float HozLength = 0.0f; float VertLength = 0.0f; if (FrustumAngle > 0.0f) { HozLength = FrustumStartDist * FMath::Tan(HozHalfAngleInRadians); VertLength = HozLength / FrustumAspectRatio; } else { const float OrthoWidth = (FrustumAngle == 0.0f) ? 1000.0f : -FrustumAngle; HozLength = OrthoWidth * 0.5f; VertLength = HozLength / FrustumAspectRatio; } // near plane verts Verts[0] = (Direction * FrustumStartDist) + (UpVector * VertLength) + (LeftVector * HozLength); Verts[1] = (Direction * FrustumStartDist) + (UpVector * VertLength) - (LeftVector * HozLength); Verts[2] = (Direction * FrustumStartDist) - (UpVector * VertLength) - (LeftVector * HozLength); Verts[3] = (Direction * FrustumStartDist) - (UpVector * VertLength) + (LeftVector * HozLength); if (FrustumAngle > 0.0f) { HozLength = FrustumEndDist * FMath::Tan(HozHalfAngleInRadians); VertLength = HozLength / FrustumAspectRatio; } // far plane verts Verts[4] = (Direction * FrustumEndDist) + (UpVector * VertLength) + (LeftVector * HozLength); Verts[5] = (Direction * FrustumEndDist) + (UpVector * VertLength) - (LeftVector * HozLength); Verts[6] = (Direction * FrustumEndDist) - (UpVector * VertLength) - (LeftVector * HozLength); Verts[7] = (Direction * FrustumEndDist) - (UpVector * VertLength) + (LeftVector * HozLength); for (int32 X = 0; X < 8; ++X) { Verts[X] = GetLocalToWorld().TransformPosition(Verts[X]); } for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); const FSceneView* View = Views[ViewIndex]; const uint8 DepthPriorityGroup = GetDepthPriorityGroup(View); PDI->DrawLine( Verts[0], Verts[1], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[1], Verts[2], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[2], Verts[3], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[3], Verts[0], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[4], Verts[5], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[5], Verts[6], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[6], Verts[7], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[7], Verts[4], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[0], Verts[4], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[1], Verts[5], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[2], Verts[6], FrustumColor, DepthPriorityGroup ); PDI->DrawLine( Verts[3], Verts[7], FrustumColor, DepthPriorityGroup ); } } }
void FNavLinkRenderingProxy::GetLinkMeshes(const TArray<FNavLinkDrawing>& OffMeshPointLinks, const TArray<FNavLinkSegmentDrawing>& OffMeshSegmentLinks, TArray<float>& StepHeights, FMaterialRenderProxy* const MeshColorInstance, int32 ViewIndex, FMeshElementCollector& Collector, uint32 AgentMask) { static const FColor LinkColor(0,0,166); static const float LinkArcThickness = 3.f; static const float LinkArcHeight = 0.4f; if (StepHeights.Num() == 0) { StepHeights.Add(FNavigationSystem::FallbackAgentHeight / 2); } FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); for (int32 LinkIndex = 0; LinkIndex < OffMeshPointLinks.Num(); ++LinkIndex) { const FNavLinkDrawing& Link = OffMeshPointLinks[LinkIndex]; if ((Link.SupportedAgentsBits & AgentMask) == 0) { continue; } const uint32 Segments = FPlatformMath::Max<uint32>(LinkArcHeight*(Link.Right - Link.Left).Size() / 10, 8); DrawArc(PDI, Link.Left, Link.Right, LinkArcHeight, Segments, Link.Color, SDPG_World, 3.5f); const FVector VOffset(0,0,FVector::Dist(Link.Left, Link.Right)*1.333f); switch (Link.Direction) { case ENavLinkDirection::LeftToRight: DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; case ENavLinkDirection::RightToLeft: DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; case ENavLinkDirection::BothWays: default: DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; } // draw snap-spheres on both ends if (Link.SnapHeight < 0) { for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex) { GetCylinderMesh(Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); } } else { GetCylinderMesh(Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); } } static const float SegmentArcHeight = 0.25f; for (int32 LinkIndex = 0; LinkIndex < OffMeshSegmentLinks.Num(); ++LinkIndex) { const FNavLinkSegmentDrawing& Link = OffMeshSegmentLinks[LinkIndex]; if ((Link.SupportedAgentsBits & AgentMask) == 0) { continue; } const uint32 SegmentsStart = FPlatformMath::Max<uint32>(SegmentArcHeight*(Link.RightStart - Link.LeftStart).Size() / 10, 8); const uint32 SegmentsEnd = FPlatformMath::Max<uint32>(SegmentArcHeight*(Link.RightEnd-Link.LeftEnd).Size()/10, 8); DrawArc(PDI, Link.LeftStart, Link.RightStart, SegmentArcHeight, SegmentsStart, Link.Color, SDPG_World, 3.5f); DrawArc(PDI, Link.LeftEnd, Link.RightEnd, SegmentArcHeight, SegmentsEnd, Link.Color, SDPG_World, 3.5f); const FVector VOffset(0,0,FVector::Dist(Link.LeftStart, Link.RightStart)*1.333f); switch (Link.Direction) { case ENavLinkDirection::LeftToRight: DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; case ENavLinkDirection::RightToLeft: DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; case ENavLinkDirection::BothWays: default: DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f); break; } // draw snap-spheres on both ends if (Link.SnapHeight < 0) { for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex) { GetCylinderMesh(Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); } } else { GetCylinderMesh(Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); GetCylinderMesh(Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector); } } }
virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override { QUICK_SCOPE_CYCLE_COUNTER( STAT_SpriteSceneProxy_GetDynamicMeshElements ); FTexture* TextureResource = (Texture != NULL) ? Texture->Resource : NULL; if (TextureResource) { for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; // Calculate the view-dependent scaling factor. float ViewedSizeX = SizeX; float ViewedSizeY = SizeY; if (bIsScreenSizeScaled && (View->ViewMatrices.ProjMatrix.M[3][3] != 1.0f)) { const float ZoomFactor = FMath::Min<float>(View->ViewMatrices.ProjMatrix.M[0][0], View->ViewMatrices.ProjMatrix.M[1][1]); if(ZoomFactor != 0.0f) { const float Radius = View->WorldToScreen(Origin).W * (ScreenSize / ZoomFactor); if (Radius < 1.0f) { ViewedSizeX *= Radius; ViewedSizeY *= Radius; } } } #if WITH_EDITORONLY_DATA ViewedSizeX *= EditorScale; ViewedSizeY *= EditorScale; #endif FLinearColor ColorToUse = Color; // Set the selection/hover color from the current engine setting. // The color is multiplied by 10 because this value is normally expected to be blended // additively, this is not how the sprites work and therefore need an extra boost // to appear the same color as previously #if WITH_EDITOR if( View->bHasSelectedComponents && !IsIndividuallySelected() ) { ColorToUse = FLinearColor::White + (GEngine->GetSubduedSelectionOutlineColor() * GEngine->SelectionHighlightIntensityBillboards * 10); } else #endif if (IsSelected()) { ColorToUse = FLinearColor::White + (GEngine->GetSelectedMaterialColor() * GEngine->SelectionHighlightIntensityBillboards * 10); } else if (IsHovered()) { ColorToUse = FLinearColor::White + (GEngine->GetHoveredMaterialColor() * GEngine->HoverHighlightIntensity * 10); } // Sprites of locked actors draw in red. if (bIsActorLocked) { ColorToUse = FColor::Red; } FLinearColor LevelColorToUse = IsSelected() ? ColorToUse : (FLinearColor)LevelColor; FLinearColor PropertyColorToUse = PropertyColor; const FLinearColor& SpriteColor = View->Family->EngineShowFlags.LevelColoration ? LevelColorToUse : ( (View->Family->EngineShowFlags.PropertyColoration) ? PropertyColorToUse : ColorToUse ); Collector.GetPDI(ViewIndex)->DrawSprite( Origin, ViewedSizeX, ViewedSizeY, TextureResource, SpriteColor, GetDepthPriorityGroup(View), U,UL,V,VL ); } } #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; RenderBounds(Collector.GetPDI(ViewIndex), View->Family->EngineShowFlags, GetBounds(), IsSelected()); } } #endif } }
void FPaperTileMapRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { QUICK_SCOPE_CYCLE_COUNTER(STAT_FPaperTileMapRenderSceneProxy_GetDynamicMeshElements); checkSlow(IsInRenderingThread()); // Slight depth bias so that the wireframe grid overlay doesn't z-fight with the tiles themselves const float DepthBias = 0.0001f; for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); // Draw the tile maps //@TODO: RenderThread race condition if (TileMap != nullptr) { FColor WireframeColor = FColor(0, 255, 255, 255); if ((View->Family->EngineShowFlags.Collision /*@TODO: && bIsCollisionEnabled*/) && AllowDebugViewmodes()) { if (UBodySetup2D* BodySetup2D = Cast<UBodySetup2D>(TileMap->BodySetup)) { //@TODO: Draw 2D debugging geometry } else if (UBodySetup* BodySetup = TileMap->BodySetup) { if (FMath::Abs(GetLocalToWorld().Determinant()) < SMALL_NUMBER) { // Catch this here or otherwise GeomTransform below will assert // This spams so commented out //UE_LOG(LogStaticMesh, Log, TEXT("Zero scaling not supported (%s)"), *StaticMesh->GetPathName()); } else { // Make a material for drawing solid collision stuff const UMaterial* LevelColorationMaterial = View->Family->EngineShowFlags.Lighting ? GEngine->ShadedLevelColorationLitMaterial : GEngine->ShadedLevelColorationUnlitMaterial; auto CollisionMaterialInstance = new FColoredMaterialRenderProxy( LevelColorationMaterial->GetRenderProxy(IsSelected(), IsHovered()), WireframeColor ); // Draw the static mesh's body setup. // Get transform without scaling. FTransform GeomTransform(GetLocalToWorld()); // In old wireframe collision mode, always draw the wireframe highlighted (selected or not). bool bDrawWireSelected = IsSelected(); if (View->Family->EngineShowFlags.Collision) { bDrawWireSelected = true; } // Differentiate the color based on bBlockNonZeroExtent. Helps greatly with skimming a level for optimization opportunities. FColor CollisionColor = FColor(157, 149, 223, 255); const bool bPerHullColor = false; const bool bDrawSimpleSolid = false; BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(CollisionColor, bDrawWireSelected, IsHovered()), CollisionMaterialInstance, bPerHullColor, bDrawSimpleSolid, UseEditorDepthTest(), ViewIndex, Collector); } } } // Draw the bounds RenderBounds(PDI, View->Family->EngineShowFlags, GetBounds(), IsSelected()); #if WITH_EDITOR // Draw the debug outline if (View->Family->EngineShowFlags.Grid) { const uint8 DPG = SDPG_Foreground;//GetDepthPriorityGroup(View); // Draw separation wires if selected FLinearColor OverrideColor; bool bUseOverrideColor = false; const bool bShowAsSelected = !(GIsEditor && View->Family->EngineShowFlags.Selection) || IsSelected(); if (bShowAsSelected || IsHovered()) { bUseOverrideColor = true; OverrideColor = GetSelectionColor(FLinearColor::White, bShowAsSelected, IsHovered()); } FTransform LocalToWorld(GetLocalToWorld()); if (bUseOverrideColor) { const int32 SelectedLayerIndex = TileMap->SelectedLayerIndex; // Draw a bound for any invisible layers for (int32 LayerIndex = 0; LayerIndex < TileMap->TileLayers.Num(); ++LayerIndex) { if (LayerIndex != SelectedLayerIndex) { const FVector TL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, 0, LayerIndex))); const FVector TR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, 0, LayerIndex))); const FVector BL(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(0, TileMap->MapHeight, LayerIndex))); const FVector BR(LocalToWorld.TransformPosition(TileMap->GetTilePositionInLocalSpace(TileMap->MapWidth, TileMap->MapHeight, LayerIndex))); PDI->DrawLine(TL, TR, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(TR, BR, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(BR, BL, OverrideColor, DPG, 0.0f, DepthBias); PDI->DrawLine(BL, TL, OverrideColor, DPG, 0.0f, DepthBias); } } if (SelectedLayerIndex != INDEX_NONE) { // Draw horizontal lines on the selection for (int32 Y = 0; Y <= TileMap->MapHeight; ++Y) { int32 X = 0; const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); X = TileMap->MapWidth; const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias); } // Draw vertical lines for (int32 X = 0; X <= TileMap->MapWidth; ++X) { int32 Y = 0; const FVector Start(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); Y = TileMap->MapHeight; const FVector End(TileMap->GetTilePositionInLocalSpace(X, Y, SelectedLayerIndex)); PDI->DrawLine(LocalToWorld.TransformPosition(Start), LocalToWorld.TransformPosition(End), OverrideColor, DPG, 0.0f, DepthBias); } } } } #endif } } } // Draw all of the queued up sprites FPaperRenderSceneProxy::GetDynamicMeshElements(Views, ViewFamily, VisibilityMap, Collector); }
void FGeometryCacheSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { SCOPE_CYCLE_COUNTER(STAT_GeometryCacheSceneProxy_GetMeshElements); // Set up wireframe material (if needed) const bool bWireframe = AllowDebugViewmodes() && ViewFamily.EngineShowFlags.Wireframe; FColoredMaterialRenderProxy* WireframeMaterialInstance = NULL; if (bWireframe) { WireframeMaterialInstance = new FColoredMaterialRenderProxy( GEngine->WireframeMaterial ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : NULL, FLinearColor(0, 0.5f, 1.f) ); Collector.RegisterOneFrameMaterialProxy(WireframeMaterialInstance); } // Iterate over sections for (const FGeomCacheTrackProxy* TrackProxy : Sections ) { // QQQ if (TrackProxy != nullptr) { INC_DWORD_STAT_BY(STAT_GeometryCacheSceneProxy_MeshBatchCount, TrackProxy->MeshData->BatchesInfo.Num()); int32 BatchIndex = 0; for (FGeometryCacheMeshBatchInfo& BatchInfo : TrackProxy->MeshData->BatchesInfo) { FMaterialRenderProxy* MaterialProxy = bWireframe ? WireframeMaterialInstance : TrackProxy->Materials[BatchIndex]->GetRenderProxy(IsSelected()); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; // Draw the mesh. FMeshBatch& Mesh = Collector.AllocateMesh(); FMeshBatchElement& BatchElement = Mesh.Elements[0]; BatchElement.IndexBuffer = &TrackProxy->IndexBuffer; Mesh.bWireframe = bWireframe; Mesh.VertexFactory = &TrackProxy->VertexFactory; Mesh.MaterialRenderProxy = MaterialProxy; BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(TrackProxy->WorldMatrix * GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest()); BatchElement.FirstIndex = BatchInfo.StartIndex; BatchElement.NumPrimitives = BatchInfo.NumTriangles; BatchElement.MinVertexIndex = 0; BatchElement.MaxVertexIndex = TrackProxy->VertexBuffer.Vertices.Num() - 1; Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); Mesh.Type = PT_TriangleList; Mesh.DepthPriorityGroup = SDPG_World; Mesh.bCanApplyViewModeOverrides = false; Collector.AddMesh(ViewIndex, Mesh); INC_DWORD_STAT_BY(STAT_GeometryCacheSceneProxy_TriangleCount, BatchElement.NumPrimitives); } } ++BatchIndex; } } } // Draw bounds #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (VisibilityMap & (1 << ViewIndex)) { // Render bounds RenderBounds(Collector.GetPDI(ViewIndex), ViewFamily.EngineShowFlags, GetBounds(), IsSelected()); } } #endif }
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 FPaperTileMapRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const { SCOPE_CYCLE_COUNTER(STAT_TileMap_GetDynamicMeshElements); checkSlow(IsInRenderingThread()); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { SCOPE_CYCLE_COUNTER(STAT_TileMap_EditorWireDrawing); if (VisibilityMap & (1 << ViewIndex)) { const FSceneView* View = Views[ViewIndex]; FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); // Draw the tile maps //@TODO: RenderThread race condition if (TileMap != nullptr) { if ((View->Family->EngineShowFlags.Collision /*@TODO: && bIsCollisionEnabled*/) && AllowDebugViewmodes()) { if (UBodySetup2D* BodySetup2D = Cast<UBodySetup2D>(TileMap->BodySetup)) { //@TODO: Draw 2D debugging geometry } else if (UBodySetup* BodySetup = TileMap->BodySetup) { if (FMath::Abs(GetLocalToWorld().Determinant()) < SMALL_NUMBER) { // Catch this here or otherwise GeomTransform below will assert // This spams so commented out //UE_LOG(LogStaticMesh, Log, TEXT("Zero scaling not supported (%s)"), *StaticMesh->GetPathName()); } else { // Make a material for drawing solid collision stuff const UMaterial* LevelColorationMaterial = View->Family->EngineShowFlags.Lighting ? GEngine->ShadedLevelColorationLitMaterial : GEngine->ShadedLevelColorationUnlitMaterial; auto CollisionMaterialInstance = new FColoredMaterialRenderProxy( LevelColorationMaterial->GetRenderProxy(IsSelected(), IsHovered()), WireframeColor ); // Draw the static mesh's body setup. // Get transform without scaling. FTransform GeomTransform(GetLocalToWorld()); // In old wireframe collision mode, always draw the wireframe highlighted (selected or not). bool bDrawWireSelected = IsSelected(); if (View->Family->EngineShowFlags.Collision) { bDrawWireSelected = true; } // Differentiate the color based on bBlockNonZeroExtent. Helps greatly with skimming a level for optimization opportunities. FColor CollisionColor = FColor(157, 149, 223, 255); const bool bPerHullColor = false; const bool bDrawSimpleSolid = false; BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(CollisionColor, bDrawWireSelected, IsHovered()).ToFColor(true), CollisionMaterialInstance, bPerHullColor, bDrawSimpleSolid, UseEditorDepthTest(), ViewIndex, Collector); } } } // Draw the bounds RenderBounds(PDI, View->Family->EngineShowFlags, GetBounds(), IsSelected()); #if WITH_EDITOR const bool bShowAsSelected = IsSelected(); const bool bEffectivelySelected = bShowAsSelected || IsHovered(); const uint8 DPG = SDPG_Foreground;//GetDepthPriorityGroup(View); // Draw separation wires if selected const FLinearColor OverrideColor = GetSelectionColor(FLinearColor::White, bShowAsSelected, IsHovered(), /*bUseOverlayIntensity=*/ false); // Draw the debug outline if (bEffectivelySelected) { const int32 SelectedLayerIndex = (OnlyLayerIndex != INDEX_NONE) ? OnlyLayerIndex : TileMap->SelectedLayerIndex; if (bShowPerLayerGrid) { if (OnlyLayerIndex == INDEX_NONE) { // Draw a bound for every layer but the selected one (and even that one if the per-tile grid is off) for (int32 LayerIndex = 0; LayerIndex < TileMap->TileLayers.Num(); ++LayerIndex) { if ((LayerIndex != SelectedLayerIndex) || !bShowPerTileGrid) { DrawBoundsForLayer(PDI, OverrideColor, LayerIndex); } } } else if (!bShowPerTileGrid) { DrawBoundsForLayer(PDI, OverrideColor, OnlyLayerIndex); } } if (bShowPerTileGrid && (SelectedLayerIndex != INDEX_NONE)) { switch (TileMap->ProjectionMode) { default: case ETileMapProjectionMode::Orthogonal: case ETileMapProjectionMode::IsometricDiamond: DrawNormalGridLines(PDI, OverrideColor, SelectedLayerIndex); break; case ETileMapProjectionMode::IsometricStaggered: DrawStaggeredGridLines(PDI, OverrideColor, SelectedLayerIndex); break; case ETileMapProjectionMode::HexagonalStaggered: DrawHexagonalGridLines(PDI, OverrideColor, SelectedLayerIndex); break; } } } else if (View->Family->EngineShowFlags.Grid && bShowOutlineWhenUnselected) { // Draw a layer rectangle even when not selected, so you can see where the tile map is in the editor DrawBoundsForLayer(PDI, WireframeColor, /*LayerIndex=*/ (OnlyLayerIndex != INDEX_NONE) ? OnlyLayerIndex : 0); } #endif } } } // Draw all of the queued up sprites FPaperRenderSceneProxy::GetDynamicMeshElements(Views, ViewFamily, VisibilityMap, Collector); }