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); } } } }
//!< FPrimitiveSceneProxy virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector& Collector) const override { FDynamicMeshBuilder MeshBuilder; const auto Num = 20; const auto DeltaUV = 1.0f / (Num - 1); TArray<FDynamicMeshVertex> Vertices; Vertices.Reserve(Num * Num); for (auto i = 0; i < Num; ++i) { for (auto j = 0; j < Num; ++j) { const auto UV = FVector2D(DeltaUV * j, DeltaUV * i); FDynamicMeshVertex Vertex; Vertex.Position = GetPosition(UV); Vertex.TextureCoordinate = GetUV(UV); const auto Edge01 = GetPosition(UV + FVector2D(0.01f, 0.0f)) - Vertex.Position; const auto Edge02 = GetPosition(UV - FVector2D(0.0f, 0.01f)) - Vertex.Position; Vertex.TangentX = Edge01.GetSafeNormal(); Vertex.TangentZ = (Edge02 ^ Edge01).GetSafeNormal(); Vertex.Color = FColor::Green; Vertices.Add(Vertex); } } MeshBuilder.AddVertices(Vertices); TArray<int32> Indices; Indices.Reserve((Num - 1) * (Num - 1) * 6); for (auto i = 0; i < Num - 1; ++i) { for (auto j = 0; j < Num - 1; ++j) { const auto Index = j + i * Num; Indices.Add(Index); Indices.Add(Index + Num); Indices.Add(Index + 1); Indices.Add(Index + 1); Indices.Add(Index + Num); Indices.Add(Index + Num + 1); } } MeshBuilder.AddTriangles(Indices); auto MaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)->GetRenderProxy(IsSelected()); if (nullptr != MaterialInterface) { MaterialRenderProxy = MaterialInterface->GetRenderProxy(false); } if (Views[0]->Family->EngineShowFlags.Wireframe) { MaterialRenderProxy = GEngine->WireframeMaterial->GetRenderProxy(IsSelected()); } MeshBuilder.GetMesh(GetLocalToWorld(), MaterialRenderProxy, 0, false, false, 0, Collector); }
void FKSphylElem::DrawElemSolid(FPrimitiveDrawInterface* PDI, const FTransform& ElemTM, float Scale, const FMaterialRenderProxy* MaterialRenderProxy) { const int32 NumSides = DrawCollisionSides; const int32 NumRings = (DrawCollisionSides/2) + 1; // The first/last arc are on top of each other. const int32 NumVerts = (NumSides+1) * (NumRings+1); FDynamicMeshVertex* Verts = (FDynamicMeshVertex*)FMemory::Malloc( NumVerts * sizeof(FDynamicMeshVertex) ); // Calculate verts for one arc FDynamicMeshVertex* ArcVerts = (FDynamicMeshVertex*)FMemory::Malloc( (NumRings+1) * sizeof(FDynamicMeshVertex) ); for(int32 RingIdx=0; RingIdx<NumRings+1; RingIdx++) { FDynamicMeshVertex* ArcVert = &ArcVerts[RingIdx]; float Angle; float ZOffset; if( RingIdx <= DrawCollisionSides/4 ) { Angle = ((float)RingIdx/(NumRings-1)) * PI; ZOffset = 0.5 * Scale * Length; } else { Angle = ((float)(RingIdx-1)/(NumRings-1)) * PI; ZOffset = -0.5 * Scale * Length; } // Note- unit sphere, so position always has mag of one. We can just use it for normal! FVector SpherePos; SpherePos.X = 0.0f; SpherePos.Y = Scale * Radius * FMath::Sin(Angle); SpherePos.Z = Scale * Radius * FMath::Cos(Angle); ArcVert->Position = SpherePos + FVector(0,0,ZOffset); ArcVert->SetTangents( FVector(1,0,0), FVector(0.0f, -SpherePos.Z, SpherePos.Y), SpherePos ); ArcVert->TextureCoordinate.X = 0.0f; ArcVert->TextureCoordinate.Y = ((float)RingIdx/NumRings); } // Then rotate this arc NumSides+1 times. for(int32 SideIdx=0; SideIdx<NumSides+1; SideIdx++) { const FRotator ArcRotator(0, 360.f * ((float)SideIdx/NumSides), 0); const FRotationMatrix ArcRot( ArcRotator ); const float XTexCoord = ((float)SideIdx/NumSides); for(int32 VertIdx=0; VertIdx<NumRings+1; VertIdx++) { int32 VIx = (NumRings+1)*SideIdx + VertIdx; Verts[VIx].Position = ArcRot.TransformPosition( ArcVerts[VertIdx].Position ); Verts[VIx].SetTangents( ArcRot.TransformVector( ArcVerts[VertIdx].TangentX ), ArcRot.TransformVector( ArcVerts[VertIdx].GetTangentY() ), ArcRot.TransformVector( ArcVerts[VertIdx].TangentZ ) ); Verts[VIx].TextureCoordinate.X = XTexCoord; Verts[VIx].TextureCoordinate.Y = ArcVerts[VertIdx].TextureCoordinate.Y; } } FDynamicMeshBuilder MeshBuilder; { // Add all of the vertices to the mesh. for(int32 VertIdx=0; VertIdx<NumVerts; VertIdx++) { MeshBuilder.AddVertex(Verts[VertIdx]); } // Add all of the triangles to the mesh. for(int32 SideIdx=0; SideIdx<NumSides; SideIdx++) { const int32 a0start = (SideIdx+0) * (NumRings+1); const int32 a1start = (SideIdx+1) * (NumRings+1); for(int32 RingIdx=0; RingIdx<NumRings; RingIdx++) { MeshBuilder.AddTriangle(a0start + RingIdx + 0, a1start + RingIdx + 0, a0start + RingIdx + 1); MeshBuilder.AddTriangle(a1start + RingIdx + 0, a1start + RingIdx + 1, a0start + RingIdx + 1); } } } MeshBuilder.Draw(PDI, ElemTM.ToMatrixWithScale(), MaterialRenderProxy, SDPG_World,0.f); FMemory::Free(Verts); FMemory::Free(ArcVerts); }
void FSpriteGeometryEditingHelper::DrawGeometry(const FSceneView& View, FPrimitiveDrawInterface& PDI, const FLinearColor& GeometryVertexColor, const FLinearColor& NegativeGeometryVertexColor) { if (GeometryBeingEdited == nullptr) { return; } FSpriteGeometryCollection& Geometry = GetGeometryChecked(); const bool bIsHitTesting = PDI.IsHitTesting(); const float UnitsPerPixel = EditorContext->SelectedItemGetUnitsPerPixel(); // Run thru the geometry shapes and draw hit proxies for them for (int32 ShapeIndex = 0; ShapeIndex < Geometry.Shapes.Num(); ++ShapeIndex) { const FSpriteGeometryShape& Shape = Geometry.Shapes[ShapeIndex]; const bool bIsShapeSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, INDEX_NONE)); const FLinearColor LineColorRaw = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor; const FLinearColor VertexColor = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor; const FLinearColor LineColor = Shape.IsShapeValid() ? LineColorRaw : FMath::Lerp(LineColorRaw, FLinearColor::Red, 0.8f); // Draw the interior (allowing selection of the whole shape) if (bIsHitTesting) { TSharedPtr<FSpriteSelectedShape> Data = MakeShareable(new FSpriteSelectedShape(EditorContext, Geometry, ShapeIndex, /*bIsBackground=*/ true)); PDI.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } FColor BackgroundColor(bIsShapeSelected ? SpriteEditingConstantsEX::GeometrySelectedColor : LineColor); BackgroundColor.A = 4; FMaterialRenderProxy* ShapeMaterialProxy = WidgetVertexColorMaterial->GetRenderProxy(bIsShapeSelected); if (Shape.ShapeType == ESpriteShapeType::Circle) { //@TODO: This is going to have issues if we ever support ellipses const FVector2D PixelSpaceRadius = Shape.BoxSize * 0.5f; const float WorldSpaceRadius = PixelSpaceRadius.X * UnitsPerPixel; const FVector CircleCenterWorldPos = EditorContext->TextureSpaceToWorldSpace(Shape.BoxPosition); DrawDisc(&PDI, CircleCenterWorldPos, PaperAxisX, PaperAxisY, BackgroundColor, WorldSpaceRadius, SpriteEditingConstantsEX::CircleShapeNumSides, ShapeMaterialProxy, SDPG_Foreground); } else { TArray<FVector2D> SourceTextureSpaceVertices; Shape.GetTextureSpaceVertices(/*out*/ SourceTextureSpaceVertices); TArray<FVector2D> TriangulatedPolygonVertices; PaperGeomTools::TriangulatePoly(/*out*/ TriangulatedPolygonVertices, SourceTextureSpaceVertices, /*bKeepColinearVertices=*/ true); if (((TriangulatedPolygonVertices.Num() % 3) == 0) && (TriangulatedPolygonVertices.Num() > 0)) { FDynamicMeshBuilder MeshBuilder; FDynamicMeshVertex MeshVertex; MeshVertex.Color = BackgroundColor; MeshVertex.TextureCoordinate = FVector2D::ZeroVector; MeshVertex.SetTangents(PaperAxisX, PaperAxisY, PaperAxisZ); for (const FVector2D& SrcTriangleVertex : TriangulatedPolygonVertices) { MeshVertex.Position = EditorContext->TextureSpaceToWorldSpace(SrcTriangleVertex); MeshBuilder.AddVertex(MeshVertex); } for (int32 TriangleIndex = 0; TriangleIndex < TriangulatedPolygonVertices.Num(); TriangleIndex += 3) { MeshBuilder.AddTriangle(TriangleIndex, TriangleIndex + 1, TriangleIndex + 2); } MeshBuilder.Draw(&PDI, FMatrix::Identity, ShapeMaterialProxy, SDPG_Foreground); } } if (bIsHitTesting) { PDI.SetHitProxy(nullptr); } } }
void FEdModeGeometry::RenderPoly( const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI ) { for( int32 ObjectIdx = 0 ; ObjectIdx < GeomObjects.Num() ; ++ObjectIdx ) { const FGeomObject* GeomObject = GeomObjects[ObjectIdx]; FLinearColor UnselectedColor = GeomObject->GetActualBrush()->GetWireColor(); UnselectedColor.A = .1f; FLinearColor SelectedColor = GetDefault<UEditorStyleSettings>()->SelectionColor; SelectedColor.A = .5f; // Allocate the material proxy and register it so it can be deleted properly once the rendering is done with it. FDynamicColoredMaterialRenderProxy* SelectedColorInstance = new FDynamicColoredMaterialRenderProxy(GEngine->GeomMaterial->GetRenderProxy(false),SelectedColor ); PDI->RegisterDynamicResource( SelectedColorInstance ); FDynamicColoredMaterialRenderProxy* UnselectedColorInstance = new FDynamicColoredMaterialRenderProxy(GEngine->GeomMaterial->GetRenderProxy(false),UnselectedColor); PDI->RegisterDynamicResource( UnselectedColorInstance ); // Render selected filled polygons. for( int32 PolyIdx = 0 ; PolyIdx < GeomObject->PolyPool.Num() ; ++PolyIdx ) { const FGeomPoly* GeomPoly = &GeomObject->PolyPool[PolyIdx]; PDI->SetHitProxy( new HGeomPolyProxy(const_cast<FGeomObject*>(GeomPoly->GetParentObject()),PolyIdx) ); { FDynamicMeshBuilder MeshBuilder; TArray<FVector> Verts; // Look at the edge list and create a list of vertices to render from. FVector LastPos(0); for( int32 EdgeIdx = 0 ; EdgeIdx < GeomPoly->EdgeIndices.Num() ; ++EdgeIdx ) { const FGeomEdge* GeomEdge = &GeomPoly->GetParentObject()->EdgePool[ GeomPoly->EdgeIndices[EdgeIdx] ]; if( EdgeIdx == 0 ) { Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ] ); LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ]; } else if( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ].Equals( LastPos ) ) { Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[1] ] ); LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[1] ]; } else { Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ] ); LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ]; } } // Draw Polygon Triangles const int32 VertexOffset = MeshBuilder.AddVertex(Verts[0], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor(255,255,255)); MeshBuilder.AddVertex(Verts[1], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor(255,255,255)); for( int32 VertIdx = 2 ; VertIdx < Verts.Num() ; ++VertIdx ) { MeshBuilder.AddVertex(Verts[VertIdx], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor(255,255,255)); MeshBuilder.AddTriangle( VertexOffset + VertIdx - 1, VertexOffset, VertexOffset + VertIdx); } if( GeomPoly->IsSelected() ) { MeshBuilder.Draw(PDI, GeomObject->GetActualBrush()->ActorToWorld().ToMatrixWithScale(), SelectedColorInstance, SDPG_World, false ); } else { // We only draw unselected polygons in the perspective viewport if( !Viewport->GetClient()->IsOrtho() ) { // Unselected polygons are drawn at the world level but are bumped slightly forward to avoid z-fighting MeshBuilder.Draw(PDI, GeomObject->GetActualBrush()->ActorToWorld().ToMatrixWithScale(), UnselectedColorInstance, SDPG_World, false ); } } } PDI->SetHitProxy( NULL ); } } }
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); } } } }