private static void SearchHierarchy(ImportedFrame rootFrame, List <ImportedMesh> meshList, HashSet <string> exportFrames) { var frameStack = new Stack <ImportedFrame>(); frameStack.Push(rootFrame); while (frameStack.Count > 0) { var frame = frameStack.Pop(); var meshListSome = ImportedHelpers.FindMesh(frame.Path, meshList); if (meshListSome != null) { var parent = frame; while (parent != null) { exportFrames.Add(parent.Path); parent = parent.Parent; } var boneList = meshListSome.BoneList; if (boneList != null) { foreach (var bone in boneList) { if (!exportFrames.Contains(bone.Path)) { var boneParent = rootFrame.FindFrameByPath(bone.Path); while (boneParent != null) { exportFrames.Add(boneParent.Path); boneParent = boneParent.Parent; } } } } } for (var i = frame.Count - 1; i >= 0; i -= 1) { frameStack.Push(frame[i]); } } }
private void ExportMesh(ImportedFrame rootFrame, List <ImportedMaterial> materialList, List <ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins) { var boneList = importedMesh.BoneList; var totalBoneCount = 0; var hasBones = false; if (exportSkins && boneList?.Count > 0) { totalBoneCount = boneList.Count; hasBones = true; } var pClusterArray = IntPtr.Zero; try { if (hasBones) { pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount); foreach (var bone in boneList) { if (bone.Path != null) { var frame = rootFrame.FindFrameByPath(bone.Path); var boneNode = _frameToNode[frame]; var cluster = AsFbxMeshCreateCluster(_pContext, boneNode); AsFbxMeshAddCluster(pClusterArray, cluster); } else { AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero); } } } var mesh = AsFbxMeshCreateMesh(_pContext, frameNode); var totalVertexCount = 0; foreach (var m in importedMesh.SubmeshList) { totalVertexCount += m.VertexList.Count; } AsFbxMeshInitControlPoints(mesh, totalVertexCount); if (importedMesh.hasNormal) { AsFbxMeshCreateElementNormal(mesh); } if (importedMesh.hasUV[0]) { AsFbxMeshCreateDiffuseUV(mesh, 0); } if (importedMesh.hasUV[1]) { AsFbxMeshCreateNormalMapUV(mesh, 1); } if (importedMesh.hasTangent) { AsFbxMeshCreateElementTangent(mesh); } if (importedMesh.hasColor) { AsFbxMeshCreateElementVertexColor(mesh); } AsFbxMeshCreateElementMaterial(mesh); var firstVertex = 0; foreach (var meshObj in importedMesh.SubmeshList) { var materialIndex = 0; var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList); if (mat != null) { var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name); IntPtr pMat; if (foundMat >= 0) { pMat = _createdMaterials[foundMat].Value; } else { var diffuse = mat.Diffuse; var ambient = mat.Ambient; var emissive = mat.Emissive; var specular = mat.Specular; var reflection = mat.Reflection; pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency); _createdMaterials.Add(new KeyValuePair <string, IntPtr>(mat.Name, pMat)); } materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat); var hasTexture = false; foreach (var texture in mat.Textures) { var tex = ImportedHelpers.FindTexture(texture.Name, textureList); var pTexture = ExportTexture(tex); if (pTexture != IntPtr.Zero) { switch (texture.Dest) { case 0: case 1: case 2: case 3: { AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y); hasTexture = true; break; } default: break; } } } if (hasTexture) { AsFbxSetFrameShadingModeToTextureShading(frameNode); } } var vertexList = meshObj.VertexList; var vertexCount = vertexList.Count; for (var j = 0; j < vertexCount; j += 1) { var importedVertex = vertexList[j]; var vertex = importedVertex.Vertex; AsFbxMeshSetControlPoint(mesh, j + firstVertex, vertex.X, vertex.Y, vertex.Z); if (importedMesh.hasNormal) { var normal = importedVertex.Normal; AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z); } for (var uvIndex = 0; uvIndex < 2; uvIndex += 1) { if (importedMesh.hasUV[uvIndex]) { var uv = importedVertex.UV[uvIndex]; AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]); } } if (importedMesh.hasTangent) { var tangent = importedVertex.Tangent; AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W); } if (importedMesh.hasColor) { var color = importedVertex.Color; AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A); } if (hasBones && importedVertex.BoneIndices != null) { var boneIndices = importedVertex.BoneIndices; var boneWeights = importedVertex.Weights; for (var k = 0; k < 4; k += 1) { if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0) { AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j + firstVertex, boneWeights[k]); } } } } foreach (var face in meshObj.FaceList) { var index0 = face.VertexIndices[0] + firstVertex; var index1 = face.VertexIndices[1] + firstVertex; var index2 = face.VertexIndices[2] + firstVertex; AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2); } firstVertex += vertexCount; } if (hasBones) { IntPtr pSkinContext = IntPtr.Zero; try { pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode); unsafe { var boneMatrix = stackalloc float[16]; for (var j = 0; j < totalBoneCount; j += 1) { if (!FbxClusterArray_HasItemAt(pClusterArray, j)) { continue; } var m = boneList[j].Matrix; CopyMatrix4x4(in m, boneMatrix); AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix); } } AsFbxMeshAddDeformer(pSkinContext, mesh); } finally { AsFbxMeshDisposeSkinContext(ref pSkinContext); } } } finally { AsFbxMeshDisposeClusterArray(ref pClusterArray); } }