OpenCTM Mesh 转换为UE4 静态资源
将CTM
Mesh顶点数据转换为UE4编辑器中的StaticMesh
。
RawMesh
生成UE4 静态资源使用的重要类FRawMesh
。
Raw mesh data used to construct optimized runtime rendering streams.
用于构建优化的运行时渲染流的原始网格数据。
生成 StaticMesh 本地资源文件
void DesBlockToMesh(const FString& blockId, BYTE* blockContent)
{
//二进制ctm解析顶点、索引等信息
CTMGeometry* geometry = new CTMGeometry(CTMGeometry::ECTMMode::IMPORT);
if (geometry->LoadStream(blockContent))
{
auto vertices = geometry->GetVertices();
auto indices = geometry->GetIndices();
auto uv0s = geometry->GetUVs(CTMGeometry::UV0);
auto normals = geometry->CalculateNormals(vertices, indices);
auto tangents = geometry->CalculateTangents(vertices, indices, uv0s);
FString PathName = FString(TEXT("/Game/Mesh/"));
FString PackageName = PathName+blockId;
//Raw mesh data we are filling in
FRawMesh RawMesh;
// Materials to apply to new mesh
TArray<UMaterialInterface*> MeshMaterials;
MeshMaterials.Add(UMaterial::GetDefaultMaterial(MD_Surface));
//Material'/Game/mat/red.red'
//UMaterial* Material1 = (UMaterial*)StaticLoadObject(UMaterial::StaticClass(), nullptr, TEXT("Material'/Game/Materials/M_BaseMaterial.M_BaseMaterial'"));
//MeshMaterials.Add(Material1);
// Copy verts
for (FVector& Vert : vertices)
{
RawMesh.VertexPositions.Add(Vert);
}
// Copy 'wedge' info
for (uint32& Idx : indices)
{
RawMesh.WedgeIndices.Add(Idx);
FVector TangentX = tangents[Idx];
FVector TangentZ = normals[Idx];
FVector TangentY = (TangentX ^ TangentZ).GetSafeNormal();
RawMesh.WedgeTangentX.Add(TangentX);
RawMesh.WedgeTangentY.Add(TangentY);
RawMesh.WedgeTangentZ.Add(TangentZ);
RawMesh.WedgeTexCoords[0].Add(uv0s[Idx]);
RawMesh.WedgeColors.Add(FColor());
}
// copy face info
int32 NumTris = indices.Num() / 3;
for (int32 TriIdx = 0; TriIdx < NumTris; TriIdx++)
{
RawMesh.FaceMaterialIndices.Add(0);
RawMesh.FaceSmoothingMasks.Add(0); // Assume this is ignored as bRecomputeNormals is false
}
// If we got some valid data.
if (RawMesh.VertexPositions.Num() > 3 && RawMesh.WedgeIndices.Num() > 3)
{
// Then find/create it.
UPackage* Package = CreatePackage(NULL, *PackageName);
// Create StaticMesh object
UStaticMesh* StaticMesh = NewObject<UStaticMesh>(Package, FName(*blockId), RF_Public | RF_Standalone);
StaticMesh->PreEditChange(nullptr);
// Add source to new StaticMesh
FStaticMeshSourceModel& SrcModel = StaticMesh->AddSourceModel();
SrcModel.SaveRawMesh(RawMesh);
// Copy materials to new mesh
for (UMaterialInterface* Material : MeshMaterials)
{
StaticMesh->StaticMaterials.Add(FStaticMaterial(Material));
}
// Build mesh from source
TArray< FText > BuildErrors;
StaticMesh->Build(true, &BuildErrors);
StaticMesh->PostEditChange();
// Notify asset registry of new asset
FAssetRegistryModule::AssetCreated(StaticMesh);
}
}
delete geometry;
geometry = nullptr;
}