Files
UnrealEngineUWP/Engine/Plugins/Experimental/GeometryCollectionPlugin/Source/GeometryCollectionComponent/Private/GeometryCollectionSceneProxy.cpp

251 lines
8.8 KiB
C++
Raw Normal View History

// 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;
}