// Copyright Epic Games, Inc. All Rights Reserved. #if WITH_EDITOR #include "RenderMesh_Editor.h" #include "CoreMesh.h" #include "MeshInfo.h" #include "KismetProceduralMeshLibrary.h" #include "../Helper/MathUtils.h" #include #include RenderMesh_Editor::RenderMesh_Editor() { _isPlane = false; } RenderMesh_Editor::RenderMesh_Editor(RenderMesh* parent, TArray meshes, MaterialInfoPtr matInfo) : RenderMesh(parent, meshes, matInfo) { } RenderMesh_Editor::RenderMesh_Editor(UStaticMeshComponent* staticMeshComponent, UWorld* world) { World = world; if (staticMeshComponent) MeshComponents.Add(staticMeshComponent); } void RenderMesh_Editor::PrepareForRendering(UWorld* world, FVector scale) { if (_parentMesh) _parentMesh->SetViewScale(scale); _viewScale = scale; } AsyncActionResultPtr RenderMesh_Editor::Load() { // Need to figure out how we are going to support MTS and UDIM meshes. _meshSplitType = MeshSplitType::Single; //_meshActor->GetComponents(MeshComponents); if (MeshComponents.Num() <= 0) return cti::make_ready_continuable(std::make_shared()); return cti::make_continuable([this](auto&& promise) { AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [this, promise = std::forward(promise)]() mutable { try { LoadInternal(); promise.set_value(std::make_shared()); } catch (cti::exception_t ex) { promise.set_exception(ex); } }); }); } void RenderMesh_Editor::SetMaterial(UMaterialInterface* material) { for (int MeshIndex = 0; MeshIndex < MeshComponents.Num(); MeshIndex++) { UStaticMeshComponent* MeshComponent = MeshComponents[MeshIndex]; if (MeshComponent->IsValidLowLevel()) { MeshInfoPtr MeshInfo = _meshes[MeshIndex]; MeshComponent->SetMaterial(MeshInfo->GetMaterialIndex(), material); } } } void RenderMesh_Editor::LoadInternal() { for (UStaticMeshComponent* MeshComponent : MeshComponents) { LoadSingleMeshComponent(*MeshComponent); } } void RenderMesh_Editor::LoadSingleMeshComponent(const UStaticMeshComponent& MeshComponent) { UStaticMesh* StaticMesh = MeshComponent.GetStaticMesh(); //Set bAllowCPUAccess to true as it is required to use GetSectionFromStaticMesh StaticMesh->bAllowCPUAccess = true; const int32 LODindex = 0; int32 numSections = StaticMesh->GetNumSections(LODindex); // Return if RenderData is invalid if (!StaticMesh->GetRenderData()) return; // No valid mesh data on lod 0 (shouldn't happen) if (!StaticMesh->GetRenderData()->LODResources.IsValidIndex(LODindex)) return; // load materials //const TArray materialInterfaces = MeshComponent.GetMaterials(); for (int32 materialIndex = 0; materialIndex < MeshComponent.GetNumMaterials(); ++materialIndex) { UMaterialInterface* MaterialInterface = MeshComponent.GetMaterial(materialIndex); if (MaterialInterface) { FString MatName; MaterialInterface->GetName(MatName); AddMaterialInfo(materialIndex, MatName); } } _currentMaterials.Empty(); _currentMaterials.Append(_originalMaterials); TArray Vertices; TArray Triangles; TArray Normals; TArray UVs; TArray Tangents; _originalBounds.Init(); for (int32 sectionIndex = 0; sectionIndex < numSections; sectionIndex++) { CoreMesh* cmesh = new CoreMesh(); CoreMeshPtr cmeshPtr = CoreMeshPtr(cmesh); MeshInfoPtr MeshInfo = std::make_shared<::MeshInfo>(cmeshPtr); cmesh->bounds = StaticMesh->GetBoundingBox(); MeshComponent.GetName(cmesh->name); FMeshSectionInfo sectionInfo = StaticMesh->GetSectionInfoMap().Get(LODindex, sectionIndex); UKismetProceduralMeshLibrary::GetSectionFromStaticMesh(StaticMesh, LODindex, sectionIndex, cmesh->vertices, cmesh->triangles, cmesh->normals, cmesh->uvs, cmesh->tangents); cmesh->materialIndex = sectionInfo.MaterialIndex; MathUtils::EncapsulateBound(_originalBounds, cmeshPtr->bounds); _meshes.Add(MeshInfo); } } #endif // WITH_EDITOR