I’ve been working on a neat project trying to use UE as the front-end for a 3D slicer ( for 3D Printing ).
So far my rendering procedure has been:
- Read in an *.stl file
- Create ProceduralMesh
- Recreate the ProceduralMesh for every duplicate/clone.
This was getting ridiculously slow at scale so I implemented the code below ( inspired by this post from newohrim [ many many thanks!! ] ) to generate static meshes that could be instantiated more efficiently.
#include "STLActor.h"
#include "ProceduralMeshComponent.h"
#include "ProceduralMeshConversion.h"
#include "StaticMeshDescription.h"
#include "Engine/StaticMesh.h"
#include "Components/StaticMeshComponent.h"
UStaticMesh* ASTLActor::BuildStaticMesh(UProceduralMeshComponent* ProcMesh)
{
if (!ProcMesh)
return nullptr;
FMeshDescription MeshDescription = BuildMeshDescription(ProcMesh);
// If we got some valid data.
if (MeshDescription.Polygons().Num() > 0)
{
// Create StaticMesh object
UStaticMesh* StaticMesh = NewObject<UStaticMesh>(ProcMesh/*Package, MeshName, RF_Public | RF_Standalone*/);
StaticMesh->InitResources();
StaticMesh->SetLightingGuid();
// Add source to new StaticMesh
auto Desc = StaticMesh->CreateStaticMeshDescription();
Desc->SetMeshDescription(MeshDescription);
// buildSimpleCol = false, cause it creates box collision based on mesh bounds or whatever :(
StaticMesh->BuildFromStaticMeshDescriptions({ Desc }, false);
//// SIMPLE COLLISION
if (!ProcMesh->bUseComplexAsSimpleCollision)
{
StaticMesh->CreateBodySetup();
UBodySetup* NewBodySetup = StaticMesh->GetBodySetup();
NewBodySetup->BodySetupGuid = FGuid::NewGuid();
NewBodySetup->AggGeom.ConvexElems = ProcMesh->ProcMeshBodySetup->AggGeom.ConvexElems;
NewBodySetup->bGenerateMirroredCollision = false;
NewBodySetup->bDoubleSidedGeometry = false;
// Play around with the flag below if you struggle with collision not working
NewBodySetup->CollisionTraceFlag = CTF_UseDefault;
NewBodySetup->CreatePhysicsMeshes();
}
//// MATERIALS
TSet<UMaterialInterface*> UniqueMaterials;
const int32 NumSections = ProcMesh->GetNumSections();
for (int32 SectionIdx = 0; SectionIdx < NumSections; SectionIdx++)
{
FProcMeshSection *ProcSection =
ProcMesh->GetProcMeshSection(SectionIdx);
UMaterialInterface *Material = ProcMesh->GetMaterial(SectionIdx);
UniqueMaterials.Add(Material);
}
// Copy materials to new mesh
for (auto* Material : UniqueMaterials)
{
StaticMesh->GetStaticMaterials().Add(FStaticMaterial(Material));
StaticMesh->AddMaterial(Material);
StaticMesh->SetMaterial(0, Material);
}
// Uncallable in game runtime
// StaticMesh->Build(false);
return StaticMesh;
}
return nullptr;
}
This code succeeds in creating a static mesh, but I have been unable to set its material so it just renders with the default material even after trying to set the material in blueprints.
-
In Level
-
In Mesh Editor
Does anyone know if I’m missing something, or what’s going on here?
Is there a way to set what material gets set by default?
Thanks for any help or suggestions!
P.S. I’m considering making this project opensource if there is interest in collaborating. Cheers!