// Copyright 2017 Mike Fricker. All Rights Reserved. #include "StreetMapRuntime.h" #include "StreetMapSceneProxy.h" #include "StreetMapComponent.h" #include "Runtime/Engine/Public/SceneManagement.h" FStreetMapSceneProxy::FStreetMapSceneProxy(const UStreetMapComponent* InComponent) : FPrimitiveSceneProxy(InComponent), StreetMapComp(InComponent), CollisionResponse(InComponent->GetCollisionResponseToChannels()), VertexFactory(GetScene().GetFeatureLevel(), "FStreetMapSceneProxy") { } void FStreetMapSceneProxy::Init(const UStreetMapComponent* InComponent, const TArray< FStreetMapVertex >& Vertices, const TArray< uint32 >& Indices) { // Copy index buffer IndexBuffer32.Indices = Indices; MaterialInterface = nullptr; this->MaterialRelevance = InComponent->GetMaterialRelevance(GetScene().GetFeatureLevel()); // Copy vertex data const int32 NumVerts = Vertices.Num(); TArray DynamicVertices; DynamicVertices.SetNumUninitialized(NumVerts); for (int VertIdx = 0; VertIdx < NumVerts; VertIdx++) { const FStreetMapVertex& StreetMapVert = Vertices[VertIdx]; FDynamicMeshVertex& Vert = DynamicVertices[VertIdx]; Vert.Position = StreetMapVert.Position; Vert.Color = StreetMapVert.Color; Vert.TextureCoordinate[0] = StreetMapVert.TextureCoordinate; Vert.TangentX = StreetMapVert.TangentX; Vert.TangentZ = StreetMapVert.TangentZ; } VertexBuffer.InitFromDynamicVertex(&VertexFactory, DynamicVertices); // Enqueue initialization of render resource InitResources(); // Set a material { if (InComponent->GetNumMaterials() > 0) { MaterialInterface = InComponent->GetMaterial(0); } // Use the default material if we don't have one set if (MaterialInterface == nullptr) { MaterialInterface = UMaterial::GetDefaultMaterial(MD_Surface); } } } FStreetMapSceneProxy::~FStreetMapSceneProxy() { VertexBuffer.PositionVertexBuffer.ReleaseResource(); VertexBuffer.StaticMeshVertexBuffer.ReleaseResource(); VertexBuffer.ColorVertexBuffer.ReleaseResource(); IndexBuffer32.ReleaseResource(); VertexFactory.ReleaseResource(); } SIZE_T FStreetMapSceneProxy::GetTypeHash() const { static size_t UniquePointer; return reinterpret_cast(&UniquePointer); } void FStreetMapSceneProxy::InitResources() { // Start initializing our vertex buffer, index buffer, and vertex factory. This will be kicked off on the render thread. BeginInitResource(&VertexBuffer.PositionVertexBuffer); BeginInitResource(&VertexBuffer.StaticMeshVertexBuffer); BeginInitResource(&VertexBuffer.ColorVertexBuffer); BeginInitResource(&IndexBuffer32); BeginInitResource(&VertexFactory); } bool FStreetMapSceneProxy::MustDrawMeshDynamically(const FSceneView& View) const { return (AllowDebugViewmodes() && View.Family->EngineShowFlags.Wireframe) || IsSelected(); } bool FStreetMapSceneProxy::IsInCollisionView(const FEngineShowFlags& EngineShowFlags) const { return EngineShowFlags.CollisionVisibility || EngineShowFlags.CollisionPawn; } FPrimitiveViewRelevance FStreetMapSceneProxy::GetViewRelevance(const FSceneView* View) const { FPrimitiveViewRelevance Result; Result.bDrawRelevance = IsShown(View); Result.bShadowRelevance = IsShadowCast(View); const bool bAlwaysHasDynamicData = false; // Only draw dynamically if we're drawing in wireframe or we're selected in the editor Result.bDynamicRelevance = MustDrawMeshDynamically(*View) || bAlwaysHasDynamicData; Result.bStaticRelevance = !MustDrawMeshDynamically(*View); MaterialRelevance.SetPrimitiveViewRelevance(Result); return Result; } bool FStreetMapSceneProxy::CanBeOccluded() const { return !MaterialRelevance.bDisableDepthTest; } void FStreetMapSceneProxy::MakeMeshBatch(FMeshBatch& Mesh, FMaterialRenderProxy* WireframeMaterialRenderProxyOrNull, bool bDrawCollision) const { FMaterialRenderProxy* MaterialProxy = NULL; if (WireframeMaterialRenderProxyOrNull != nullptr) { MaterialProxy = WireframeMaterialRenderProxyOrNull; } else { if (bDrawCollision) { MaterialProxy = new FColoredMaterialRenderProxy(GEngine->ShadedLevelColorationUnlitMaterial->GetRenderProxy(IsSelected(), IsHovered()), FColor::Cyan); } else if (MaterialProxy == nullptr) { MaterialProxy = StreetMapComp->GetDefaultMaterial()->GetRenderProxy(IsSelected()); } } FMeshBatchElement& BatchElement = Mesh.Elements[0]; BatchElement.IndexBuffer = &IndexBuffer32; Mesh.bWireframe = WireframeMaterialRenderProxyOrNull != nullptr; Mesh.VertexFactory = &VertexFactory; Mesh.MaterialRenderProxy = MaterialProxy; Mesh.CastShadow = true; BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest()); BatchElement.FirstIndex = 0; const int IndexCount = IndexBuffer32.Indices.Num(); BatchElement.NumPrimitives = IndexCount / 3; BatchElement.MinVertexIndex = 0; BatchElement.MaxVertexIndex = VertexBuffer.PositionVertexBuffer.GetNumVertices() - 1; Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative(); Mesh.Type = PT_TriangleList; Mesh.DepthPriorityGroup = SDPG_World; } void FStreetMapSceneProxy::DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) { const int IndexCount = IndexBuffer32.Indices.Num(); if (VertexBuffer.PositionVertexBuffer.GetNumVertices() > 0 && IndexCount > 0) { const float ScreenSize = 1.0f; FMeshBatch MeshBatch; MakeMeshBatch(MeshBatch, nullptr); PDI->DrawMesh(MeshBatch, ScreenSize); } } void FStreetMapSceneProxy::GetDynamicMeshElements(const TArray& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector& Collector) const { const int IndexCount = IndexBuffer32.Indices.Num(); if (VertexBuffer.PositionVertexBuffer.GetNumVertices() > 0 && IndexCount > 0) { for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex) { const FSceneView& View = *Views[ViewIndex]; const bool bIsWireframe = AllowDebugViewmodes() && View.Family->EngineShowFlags.Wireframe; FColoredMaterialRenderProxy* WireframeMaterialRenderProxy = GEngine->WireframeMaterial && bIsWireframe ? new FColoredMaterialRenderProxy(GEngine->WireframeMaterial->GetRenderProxy(IsSelected()), FLinearColor(0, 0.5f, 1.f)) : NULL; if (MustDrawMeshDynamically(View)) { const bool bInCollisionView = IsInCollisionView(ViewFamily.EngineShowFlags); const bool bCanDrawCollision = bInCollisionView && IsCollisionEnabled(); if (!IsCollisionEnabled() && bInCollisionView) { continue; } // Draw the mesh! FMeshBatch& MeshBatch = Collector.AllocateMesh(); MakeMeshBatch(MeshBatch, WireframeMaterialRenderProxy, bCanDrawCollision); Collector.AddMesh(ViewIndex, MeshBatch); } } } } uint32 FStreetMapSceneProxy::GetMemoryFootprint(void) const { return sizeof(*this) + GetAllocatedSize(); }