我有一个包含 FBX 网格日期的类
其中 VertexData 具有顶点数据,例如位置、uv、颜色...等
材质有这个网格的材质
VertexIndices 是三角形面索引
MaterialIndices 是每个三角形的材质索引
我希望能够通过 bolygon 材质将 FBXMeshData 拆分为列表
public class FBXMeshData
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Vector3 Rotation { get; set; }
public Vector3 Scale { get; set; }
private List<FBXVertexData> VertexData { get; set; }
public List<FBXMaterialData> Materials { get; set; } = new List<FBXMaterialData>();
private List<int> VertexIndices { get; set; }
public List<int> MaterialIndices { get; set; }
public FBXMeshData(FBXMeshData meshData)
{
Name = meshData.Name;
Position = meshData.Position;
Rotation = meshData.Rotation;
Scale = meshData.Scale;
VertexData = meshData.VertexData.Select(x =>
new FBXVertexData(x.Position, x.Normal, x.Tangents, x.UVs, x.Colors, x.BoneNames.ToArray(),
x.BoneWeights.ToArray()))
.ToList();
VertexIndices = meshData.VertexIndices;
MaterialIndices = meshData.MaterialIndices;
if (meshData.MaterialIndices != null)
{
for (int i = 0; i < meshData.Materials.Count; i++)
{
Materials.Add(meshData.Materials[i]);
}
}
}
public FBXMeshData(FbxMeshData meshData)
{
Name = meshData.Name;
Position = MySF.ToVector3(meshData.Position);
Rotation = MySF.QToYawPitchRoll(meshData.Rotation);
Scale = MySF.ToVector3(meshData.Scale);
VertexData = meshData.VertexData.Select(x =>
new FBXVertexData(x.Position, x.Normal, x.Tangents, x.UVs, x.Colors, x.BoneNames.ToArray(),
x.BoneWeights.ToArray()))
.ToList();
VertexIndices = meshData.VertexIndices;
MaterialIndices = meshData.MaterialIndices;
if (meshData.MaterialIndices != null)
{
for (int i = 0; i < meshData.MaterialData.Count; i++)
{
Materials.Add(new FBXMaterialData(meshData.MaterialData[i]));
}
}
}
}
我的想法:MaterialIndices中的每个materialindex都指向由VertexIndices中的三个整数组成的多边形,每个整数是VertexData中一个Vertex的索引首先我检查网格是否有材质或没有材质,然后按原样返回网格 如果不 按材质索引按多边形索引对顶点进行分组 字典
>>>materialToFacetoVertex = 新字典
public static List<FBXMeshData> SplitByMaterial(FBXMeshData meshData)
{
if (meshData.Materials.Count == 0 || meshData.Materials.Count == 1)
{
return new List<FBXMeshData> { meshData };
}
// Group vertices by polygon index and material index
var materialToFaceToVertex = new Dictionary<int, Dictionary<int, List<FBXVertexData>>>();
//int faceindex = 0;
for (int i = 0; i < meshData.MaterialIndices.Count; i++)
{
int materialIndex = meshData.MaterialIndices[i];
FBXVertexData vertex = meshData.VertexData[meshData.VertexIndices[i]];
FBXVertexData vertex1 = meshData.VertexData[meshData.VertexIndices[i+1]];
FBXVertexData vertex2 = meshData.VertexData[meshData.VertexIndices[i+2]];
int faceindex =i;
if (!materialToFaceToVertex.TryGetValue(materialIndex, out var faceToVertex))
{
faceToVertex = new Dictionary<int, List<FBXVertexData>>();
materialToFaceToVertex[materialIndex] = faceToVertex;
}
if (!faceToVertex.TryGetValue(faceindex, out var vertexList))
{
vertexList = new List<FBXVertexData>();
faceToVertex[faceindex] = vertexList;
}
vertexList.Add(vertex);
vertexList.Add(vertex1);
vertexList.Add(vertex2);
}
// Create separate mesh data for each material group
var meshList = new List<FBXMeshData>();
foreach (var kvp in materialToFaceToVertex)
{
var materialIndex = kvp.Key;
var faceToVertex = kvp.Value;
FBXMaterialData materialData = meshData.Materials[kvp.Key];
string materialName = materialData.Name;
var newMeshData = new FBXMeshData(meshData)
{
Name = materialName,
Materials = new List<FBXMaterialData> { materialData },
VertexData = new List<FBXVertexData>(),
VertexIndices = new List<int>(),
MaterialIndices = new List<int> { 0 },
};
int currentvertindex = 0;
foreach (var faceVertices in faceToVertex.Values)
{
newMeshData.VertexData.AddRange(faceVertices);
// Add indices for the current triangle (assuming triangles)
newMeshData.VertexIndices.Add(currentvertindex);
newMeshData.VertexIndices.Add(currentvertindex + 1);
newMeshData.VertexIndices.Add(currentvertindex + 2);
currentvertindex += 3; // Increment by 3 for each triangle's vertices
}
meshList.Add(newMeshData);
}
StringBuilder sb = new StringBuilder();
foreach (var mes in meshList)
{
sb.AppendLine(mes.ToString());
}
MainWindow.debug.texView.Text = sb.ToString();
return meshList;
}
但是此方法的输出有重复的顶点且索引错误有人可以帮我吗?
图像显示了一个简单立方体的结果,其中每两个三角形(四边形)都有单独的材质
List<int>^ FbxSceneData::GetMaterialIndices(FbxMesh* fbxMesh)
{
List<int>^ materialIndices = gcnew List<int>();
FbxLayerElementMaterial* materialLayer = fbxMesh->GetLayer(0)->GetMaterials();
if (materialLayer)
{
FbxLayerElement::EMappingMode mappingMode = materialLayer->GetMappingMode();
if (mappingMode == FbxLayerElement::eByPolygon)
{
int polygonCount = fbxMesh->GetPolygonCount();
for (int p = 0; p < polygonCount; p++)
{
int materialIndex = materialLayer->GetIndexArray().GetAt(p);
materialIndices->Add(materialIndex);
// Now you have the material index for this polygon
// You can use it to retrieve the material for further processing
// FbxSurfaceMaterial* material = mesh->GetNode()->GetMaterial(materialIndex);
// ... (do something with the material index)
}
}
else if (mappingMode == FbxLayerElement::eAllSame)
{
// In this case, all polygons share the same material, and the material index is 0
int materialIndex = materialLayer->GetIndexArray().GetAt(0);
materialIndices->Add(materialIndex);
}
else
{
// Other mapping modes are not supported in this example
}
}
else
{
// The mesh does not have any material information
}
return materialIndices;
}
public class FBXMeshData
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Vector3 Rotation { get; set; }
public Vector3 Scale { get; set; }
private List<FBXVertexData> VertexData { get; set; }
}
public class FBXMaterialData
{
}
public class FBXVertexData
{
FBXMaterialData material { get; set; }
}