136 lines
4.0 KiB
Markdown
Raw Permalink Normal View History

2024-09-12 16:09:05 +08:00
---
title: Mass扩展笔记
date: 2024-09-12 15:32:15
excerpt:
tags:
rating: ⭐
---
#
1. 创建 UMassEntityTraitBase UMassVisualizationTrait
2. 相关的渲染设置逻辑位于UMassVisualizationComponent。
# UMassVisualizationComponent
```c++
void UMassVisualizationComponent::ConstructStaticMeshComponents()
{
AActor* ActorOwner = GetOwner();
check(ActorOwner);
UE_MT_SCOPED_WRITE_ACCESS(InstancedStaticMeshInfosDetector);
for (FMassInstancedStaticMeshInfo& Info : InstancedStaticMeshInfos)
{
// Check if it is already created
if (!Info.InstancedStaticMeshComponents.IsEmpty())
{
continue;
}
// Check if there are any specified meshes for this visual type
if(Info.Desc.Meshes.Num() == 0)
{
UE_LOG(LogMassRepresentation, Error, TEXT("No associated meshes for this intanced static mesh type"));
continue;
}
for (const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc : Info.Desc.Meshes)
{
FISMCSharedData* SharedData = ISMCSharedData.Find(MeshDesc);
UInstancedStaticMeshComponent* ISMC = SharedData ? SharedData->ISMC : nullptr;
if (SharedData)
{
SharedData->RefCount += 1;
}
else
{
ISMC = NewObject<UInstancedStaticMeshComponent>(ActorOwner);
ISMC->SetStaticMesh(MeshDesc.Mesh);
for (int32 ElementIndex = 0; ElementIndex < MeshDesc.MaterialOverrides.Num(); ++ElementIndex)
{
if (UMaterialInterface* MaterialOverride = MeshDesc.MaterialOverrides[ElementIndex])
{
ISMC->SetMaterial(ElementIndex, MaterialOverride);
}
}
ISMC->SetCullDistances(0, 1000000); // @todo: Need to figure out what to do here, either LOD or cull distances.
ISMC->SetupAttachment(ActorOwner->GetRootComponent());
ISMC->SetCanEverAffectNavigation(false);
ISMC->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
ISMC->SetCastShadow(MeshDesc.bCastShadows);
ISMC->Mobility = MeshDesc.Mobility;
ISMC->SetReceivesDecals(false);
ISMC->RegisterComponent();
ISMCSharedData.Emplace(MeshDesc, FISMCSharedData(ISMC));
}
Info.InstancedStaticMeshComponents.Add(ISMC);
}
// Build the LOD significance ranges
TArray<float> AllLODSignificances;
auto UniqueInsertOrdered = [&AllLODSignificances](const float Significance)
{
int i = 0;
for (; i < AllLODSignificances.Num(); ++i)
{
// I did not use epsilon check here on purpose, because it will make it hard later meshes inside.
if (Significance == AllLODSignificances[i])
{
return;
}
if (AllLODSignificances[i] > Significance)
{
break;
}
}
AllLODSignificances.Insert(Significance, i);
};
for (const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc : Info.Desc.Meshes)
{
UniqueInsertOrdered(MeshDesc.MinLODSignificance);
UniqueInsertOrdered(MeshDesc.MaxLODSignificance);
}
Info.LODSignificanceRanges.SetNum(AllLODSignificances.Num() - 1);
for (int i = 0; i < Info.LODSignificanceRanges.Num(); ++i)
{
FMassLODSignificanceRange& Range = Info.LODSignificanceRanges[i];
Range.MinSignificance = AllLODSignificances[i];
Range.MaxSignificance = AllLODSignificances[i+1];
Range.ISMCSharedDataPtr = &ISMCSharedData;
for (int j = 0; j < Info.Desc.Meshes.Num(); ++j)
{
const FStaticMeshInstanceVisualizationMeshDesc& MeshDesc = Info.Desc.Meshes[j];
const bool bAddMeshInRange = (Range.MinSignificance >= MeshDesc.MinLODSignificance && Range.MinSignificance < MeshDesc.MaxLODSignificance);
if (bAddMeshInRange)
{
Range.StaticMeshRefs.Add(MeshDesc);
}
}
}
}
}
```
设置灯光通道:
```c++
void UPrimitiveComponent::SetLightingChannels(bool bChannel0, bool bChannel1, bool bChannel2)
{
if (bChannel0 != LightingChannels.bChannel0 ||
bChannel1 != LightingChannels.bChannel1 ||
bChannel2 != LightingChannels.bChannel2)
{
LightingChannels.bChannel0 = bChannel0;
LightingChannels.bChannel1 = bChannel1;
LightingChannels.bChannel2 = bChannel2;
if (SceneProxy)
{
SceneProxy->SetLightingChannels_GameThread(LightingChannels);
}
MarkRenderStateDirty();
}
}
```