You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
251 lines
8.8 KiB
C++
251 lines
8.8 KiB
C++
|
|
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
|
||
|
|
|
||
|
|
#include "GeometryCollectionSceneProxy.h"
|
||
|
|
|
||
|
|
#include "Async/ParallelFor.h"
|
||
|
|
#include "Engine/Engine.h"
|
||
|
|
#include "Materials/Material.h"
|
||
|
|
#include "GeometryCollectionComponent.h"
|
||
|
|
|
||
|
|
DEFINE_LOG_CATEGORY_STATIC(FGeometryCollectionSceneProxyLogging, Log, All);
|
||
|
|
|
||
|
|
|
||
|
|
FGeometryCollectionSceneProxy::FGeometryCollectionSceneProxy(UGeometryCollectionComponent* Component)
|
||
|
|
: FPrimitiveSceneProxy(Component)
|
||
|
|
, Material(Component->GetMaterial(0))
|
||
|
|
, MaterialRelevance(Component->GetMaterialRelevance(GetScene().GetFeatureLevel()))
|
||
|
|
, NumVertices(0)
|
||
|
|
, NumIndices(0)
|
||
|
|
, VertexFactory(GetScene().GetFeatureLevel(), "FGeometryCollectionSceneProxy")
|
||
|
|
, DynamicData(nullptr)
|
||
|
|
, ConstantData(nullptr)
|
||
|
|
{
|
||
|
|
if (Material == nullptr)
|
||
|
|
{
|
||
|
|
Material = UMaterial::GetDefaultMaterial(MD_Surface);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
FGeometryCollectionSceneProxy::~FGeometryCollectionSceneProxy()
|
||
|
|
{
|
||
|
|
ReleaseResources();
|
||
|
|
|
||
|
|
if (DynamicData != nullptr)
|
||
|
|
{
|
||
|
|
delete DynamicData;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ConstantData != nullptr)
|
||
|
|
{
|
||
|
|
delete ConstantData;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::InitResources()
|
||
|
|
{
|
||
|
|
check(ConstantData);
|
||
|
|
|
||
|
|
NumVertices = ConstantData->Vertices.Num();
|
||
|
|
NumIndices = ConstantData->Indices.Num()*3;
|
||
|
|
|
||
|
|
VertexBuffers.InitWithDummyData(&VertexFactory, GetRequiredVertexCount());
|
||
|
|
|
||
|
|
IndexBuffer.NumIndices = GetRequiredIndexCount();
|
||
|
|
|
||
|
|
BeginInitResource(&IndexBuffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::ReleaseResources()
|
||
|
|
{
|
||
|
|
VertexBuffers.PositionVertexBuffer.ReleaseResource();
|
||
|
|
VertexBuffers.StaticMeshVertexBuffer.ReleaseResource();
|
||
|
|
VertexBuffers.ColorVertexBuffer.ReleaseResource();
|
||
|
|
IndexBuffer.ReleaseResource();
|
||
|
|
VertexFactory.ReleaseResource();
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::BuildGeometry( const FGeometryCollectionConstantData* ConstantDataIn, TArray<FDynamicMeshVertex>& OutVertices, TArray<int32>& OutIndices)
|
||
|
|
{
|
||
|
|
OutVertices.SetNumUninitialized(ConstantDataIn->Vertices.Num());
|
||
|
|
ParallelFor(ConstantData->Vertices.Num(), [&](int32 PointIdx)
|
||
|
|
{
|
||
|
|
OutVertices[PointIdx] =
|
||
|
|
FDynamicMeshVertex(
|
||
|
|
ConstantDataIn->Vertices[PointIdx],
|
||
|
|
ConstantDataIn->UVs[PointIdx],
|
||
|
|
ConstantDataIn->Colors[PointIdx].ToFColor(true)
|
||
|
|
);
|
||
|
|
OutVertices[PointIdx].SetTangents(ConstantDataIn->TangentU[PointIdx], ConstantDataIn->TangentV[PointIdx], ConstantDataIn->Normals[PointIdx]);
|
||
|
|
});
|
||
|
|
|
||
|
|
check(ConstantDataIn->Indices.Num() * 3 == NumIndices);
|
||
|
|
|
||
|
|
OutIndices.SetNumUninitialized(NumIndices);
|
||
|
|
ParallelFor (ConstantDataIn->Indices.Num(), [&](int32 IndexIdx)
|
||
|
|
{
|
||
|
|
OutIndices[IndexIdx * 3 ] = ConstantDataIn->Indices[IndexIdx].X;
|
||
|
|
OutIndices[IndexIdx * 3 + 1] = ConstantDataIn->Indices[IndexIdx].Y;
|
||
|
|
OutIndices[IndexIdx * 3 + 2] = ConstantDataIn->Indices[IndexIdx].Z;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::SetConstantData_RenderThread(FGeometryCollectionConstantData* NewConstantData)
|
||
|
|
{
|
||
|
|
check(IsInRenderingThread());
|
||
|
|
check(NewConstantData);
|
||
|
|
|
||
|
|
if (ConstantData)
|
||
|
|
{
|
||
|
|
delete ConstantData;
|
||
|
|
ConstantData = nullptr;
|
||
|
|
}
|
||
|
|
ConstantData = NewConstantData;
|
||
|
|
|
||
|
|
if (ConstantData->Vertices.Num() != VertexBuffers.PositionVertexBuffer.GetNumVertices())
|
||
|
|
{
|
||
|
|
ReleaseResources();
|
||
|
|
InitResources();
|
||
|
|
}
|
||
|
|
|
||
|
|
TArray<int32> Indices;
|
||
|
|
TArray<FDynamicMeshVertex> Vertices;
|
||
|
|
BuildGeometry(ConstantData, Vertices, Indices);
|
||
|
|
check(Vertices.Num() == GetRequiredVertexCount());
|
||
|
|
check(Indices.Num() == GetRequiredIndexCount());
|
||
|
|
|
||
|
|
if (GetRequiredVertexCount())
|
||
|
|
{
|
||
|
|
ParallelFor(Vertices.Num(), [&](int32 i)
|
||
|
|
{
|
||
|
|
const FDynamicMeshVertex& Vertex = Vertices[i];
|
||
|
|
|
||
|
|
VertexBuffers.PositionVertexBuffer.VertexPosition(i) = Vertex.Position;
|
||
|
|
VertexBuffers.StaticMeshVertexBuffer.SetVertexTangents(i, Vertex.TangentX.ToFVector(), Vertex.GetTangentY(), Vertex.TangentZ.ToFVector());
|
||
|
|
VertexBuffers.StaticMeshVertexBuffer.SetVertexUV(i, 0, Vertex.TextureCoordinate[0]);
|
||
|
|
VertexBuffers.ColorVertexBuffer.VertexColor(i) = Vertex.Color;
|
||
|
|
});
|
||
|
|
|
||
|
|
{
|
||
|
|
auto& VertexBuffer = VertexBuffers.PositionVertexBuffer;
|
||
|
|
void* VertexBufferData = RHILockVertexBuffer(VertexBuffer.VertexBufferRHI, 0, VertexBuffer.GetNumVertices() * VertexBuffer.GetStride(), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(VertexBufferData, VertexBuffer.GetVertexData(), VertexBuffer.GetNumVertices() * VertexBuffer.GetStride());
|
||
|
|
RHIUnlockVertexBuffer(VertexBuffer.VertexBufferRHI);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
auto& VertexBuffer = VertexBuffers.ColorVertexBuffer;
|
||
|
|
void* VertexBufferData = RHILockVertexBuffer(VertexBuffer.VertexBufferRHI, 0, VertexBuffer.GetNumVertices() * VertexBuffer.GetStride(), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(VertexBufferData, VertexBuffer.GetVertexData(), VertexBuffer.GetNumVertices() * VertexBuffer.GetStride());
|
||
|
|
RHIUnlockVertexBuffer(VertexBuffer.VertexBufferRHI);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
auto& VertexBuffer = VertexBuffers.StaticMeshVertexBuffer;
|
||
|
|
void* VertexBufferData = RHILockVertexBuffer(VertexBuffer.TangentsVertexBuffer.VertexBufferRHI, 0, VertexBuffer.GetTangentSize(), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(VertexBufferData, VertexBuffer.GetTangentData(), VertexBuffer.GetTangentSize());
|
||
|
|
RHIUnlockVertexBuffer(VertexBuffer.TangentsVertexBuffer.VertexBufferRHI);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
auto& VertexBuffer = VertexBuffers.StaticMeshVertexBuffer;
|
||
|
|
void* VertexBufferData = RHILockVertexBuffer(VertexBuffer.TexCoordVertexBuffer.VertexBufferRHI, 0, VertexBuffer.GetTexCoordSize(), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(VertexBufferData, VertexBuffer.GetTexCoordData(), VertexBuffer.GetTexCoordSize());
|
||
|
|
RHIUnlockVertexBuffer(VertexBuffer.TexCoordVertexBuffer.VertexBufferRHI);
|
||
|
|
}
|
||
|
|
|
||
|
|
{
|
||
|
|
void* IndexBufferData = RHILockIndexBuffer(IndexBuffer.IndexBufferRHI, 0, Indices.Num() * sizeof(int32), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(IndexBufferData, &Indices[0], Indices.Num() * sizeof(int32));
|
||
|
|
RHIUnlockIndexBuffer(IndexBuffer.IndexBufferRHI);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::SetDynamicData_RenderThread(FGeometryCollectionDynamicData* NewDynamicData)
|
||
|
|
{
|
||
|
|
check(IsInRenderingThread());
|
||
|
|
if (GetRequiredVertexCount())
|
||
|
|
{
|
||
|
|
if (DynamicData)
|
||
|
|
{
|
||
|
|
delete DynamicData;
|
||
|
|
DynamicData = nullptr;
|
||
|
|
}
|
||
|
|
DynamicData = NewDynamicData;
|
||
|
|
|
||
|
|
check(VertexBuffers.PositionVertexBuffer.GetNumVertices() == (uint32)ConstantData->Vertices.Num());
|
||
|
|
|
||
|
|
ParallelFor(ConstantData->Vertices.Num(), [&](int32 i)
|
||
|
|
{
|
||
|
|
VertexBuffers.PositionVertexBuffer.VertexPosition(i) = DynamicData->Transforms[ConstantData->BoneMap[i]].TransformPosition(ConstantData->Vertices[i]);
|
||
|
|
});
|
||
|
|
|
||
|
|
{
|
||
|
|
auto& VertexBuffer = VertexBuffers.PositionVertexBuffer;
|
||
|
|
void* VertexBufferData = RHILockVertexBuffer(VertexBuffer.VertexBufferRHI, 0, VertexBuffer.GetNumVertices() * VertexBuffer.GetStride(), RLM_WriteOnly);
|
||
|
|
FMemory::Memcpy(VertexBufferData, VertexBuffer.GetVertexData(), VertexBuffer.GetNumVertices() * VertexBuffer.GetStride());
|
||
|
|
RHIUnlockVertexBuffer(VertexBuffer.VertexBufferRHI);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void FGeometryCollectionSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
|
||
|
|
{
|
||
|
|
QUICK_SCOPE_CYCLE_COUNTER(STAT_GeometryCollectionSceneProxy_GetDynamicMeshElements);
|
||
|
|
if (GetRequiredVertexCount())
|
||
|
|
{
|
||
|
|
const bool bWireframe = AllowDebugViewmodes() && ViewFamily.EngineShowFlags.Wireframe;
|
||
|
|
|
||
|
|
auto WireframeMaterialInstance = new FColoredMaterialRenderProxy(
|
||
|
|
GEngine->WireframeMaterial ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : nullptr,
|
||
|
|
FLinearColor(0, 0.5f, 1.f)
|
||
|
|
);
|
||
|
|
|
||
|
|
Collector.RegisterOneFrameMaterialProxy(WireframeMaterialInstance);
|
||
|
|
|
||
|
|
FMaterialRenderProxy* MaterialProxy = nullptr;
|
||
|
|
if (bWireframe)
|
||
|
|
{
|
||
|
|
MaterialProxy = WireframeMaterialInstance;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
MaterialProxy = Material->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 = &IndexBuffer;
|
||
|
|
Mesh.bWireframe = bWireframe;
|
||
|
|
Mesh.VertexFactory = &VertexFactory;
|
||
|
|
Mesh.MaterialRenderProxy = MaterialProxy;
|
||
|
|
BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest());
|
||
|
|
BatchElement.FirstIndex = 0;
|
||
|
|
BatchElement.NumPrimitives = GetRequiredIndexCount() / 3;
|
||
|
|
BatchElement.MinVertexIndex = 0;
|
||
|
|
BatchElement.MaxVertexIndex = GetRequiredVertexCount();
|
||
|
|
Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
|
||
|
|
Mesh.Type = PT_TriangleList;
|
||
|
|
Mesh.DepthPriorityGroup = SDPG_World;
|
||
|
|
Mesh.bCanApplyViewModeOverrides = false;
|
||
|
|
Collector.AddMesh(ViewIndex, Mesh);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
FPrimitiveViewRelevance FGeometryCollectionSceneProxy::GetViewRelevance(const FSceneView* View) const
|
||
|
|
{
|
||
|
|
FPrimitiveViewRelevance Result;
|
||
|
|
Result.bDrawRelevance = IsShown(View);
|
||
|
|
Result.bShadowRelevance = IsShadowCast(View);
|
||
|
|
Result.bDynamicRelevance = true;
|
||
|
|
MaterialRelevance.SetPrimitiveViewRelevance(Result);
|
||
|
|
return Result;
|
||
|
|
}
|