4.0 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
Mass扩展笔记 2024-09-12 15:32:15

  1. 创建 UMassEntityTraitBase UMassVisualizationTrait
  2. 相关的渲染设置逻辑位于UMassVisualizationComponent。

UMassVisualizationComponent


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

	}
}

设置灯光通道:

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();
	}
}