diff --git a/AssetStudio/IImported.cs b/AssetStudio/IImported.cs index 7122c26..c207b17 100644 --- a/AssetStudio/IImported.cs +++ b/AssetStudio/IImported.cs @@ -132,6 +132,7 @@ namespace AssetStudio public class ImportedMesh { public string Path { get; set; } + public List VertexList { get; set; } public List SubmeshList { get; set; } public List BoneList { get; set; } public bool hasNormal { get; set; } @@ -142,9 +143,9 @@ namespace AssetStudio public class ImportedSubmesh { - public List VertexList { get; set; } public List FaceList { get; set; } public string Material { get; set; } + public int BaseVertex { get; set; } } public class ImportedVertex diff --git a/AssetStudioFBXWrapper/FbxExporterContext.cs b/AssetStudioFBXWrapper/FbxExporterContext.cs index d18beb3..03036ec 100644 --- a/AssetStudioFBXWrapper/FbxExporterContext.cs +++ b/AssetStudioFBXWrapper/FbxExporterContext.cs @@ -246,14 +246,7 @@ namespace AssetStudio.FbxInterop var mesh = AsFbxMeshCreateMesh(_pContext, frameNode); - var totalVertexCount = 0; - - foreach (var m in importedMesh.SubmeshList) - { - totalVertexCount += m.VertexList.Count; - } - - AsFbxMeshInitControlPoints(mesh, totalVertexCount); + AsFbxMeshInitControlPoints(mesh, importedMesh.VertexList.Count); if (importedMesh.hasNormal) { @@ -282,8 +275,6 @@ namespace AssetStudio.FbxInterop AsFbxMeshCreateElementMaterial(mesh); - var firstVertex = 0; - foreach (var meshObj in importedMesh.SubmeshList) { var materialIndex = 0; @@ -345,71 +336,70 @@ namespace AssetStudio.FbxInterop } } - 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; + var index0 = face.VertexIndices[0] + meshObj.BaseVertex; + var index1 = face.VertexIndices[1] + meshObj.BaseVertex; + var index2 = face.VertexIndices[2] + meshObj.BaseVertex; AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2); } - - firstVertex += vertexCount; } + var vertexList = importedMesh.VertexList; + + var vertexCount = vertexList.Count; + + for (var j = 0; j < vertexCount; j += 1) + { + var importedVertex = vertexList[j]; + + var vertex = importedVertex.Vertex; + AsFbxMeshSetControlPoint(mesh, j, 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, boneWeights[k]); + } + } + } + } + + if (hasBones) { IntPtr pSkinContext = IntPtr.Zero; @@ -646,4 +636,4 @@ namespace AssetStudio.FbxInterop } } -} \ No newline at end of file +} diff --git a/AssetStudioUtility/ModelConverter.cs b/AssetStudioUtility/ModelConverter.cs index 3006696..e757dcf 100644 --- a/AssetStudioUtility/ModelConverter.cs +++ b/AssetStudioUtility/ModelConverter.cs @@ -319,79 +319,8 @@ namespace AssetStudio } ImportedMaterial iMat = ConvertMaterial(mat); iSubmesh.Material = iMat.Name; - iSubmesh.VertexList = new List((int)submesh.vertexCount); - for (var j = mesh.m_SubMeshes[i].firstVertex; j < mesh.m_SubMeshes[i].firstVertex + mesh.m_SubMeshes[i].vertexCount; j++) - { - var iVertex = new ImportedVertex(); - //Vertices - int c = 3; - if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4) - { - c = 4; - } - iVertex.Vertex = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]); - //Normals - if (iMesh.hasNormal) - { - if (mesh.m_Normals.Length == mesh.m_VertexCount * 3) - { - c = 3; - } - else if (mesh.m_Normals.Length == mesh.m_VertexCount * 4) - { - c = 4; - } - iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]); - } - //UV - iVertex.UV = new float[8][]; - for (int uv = 0; uv < 8; uv++) - { - if (iMesh.hasUV[uv]) - { - var m_UV = mesh.GetUV(uv); - if (m_UV.Length == mesh.m_VertexCount * 2) - { - c = 2; - } - else if (m_UV.Length == mesh.m_VertexCount * 3) - { - c = 3; - } - iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] }; - } - } - //Tangent - if (iMesh.hasTangent) - { - iVertex.Tangent = new Vector4(-mesh.m_Tangents[j * 4], mesh.m_Tangents[j * 4 + 1], mesh.m_Tangents[j * 4 + 2], mesh.m_Tangents[j * 4 + 3]); - } - //Colors - if (iMesh.hasColor) - { - if (mesh.m_Colors.Length == mesh.m_VertexCount * 3) - { - iVertex.Color = new Color(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f); - } - else - { - iVertex.Color = new Color(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]); - } - } - //BoneInfluence - if (mesh.m_Skin?.Length > 0) - { - var inf = mesh.m_Skin[j]; - iVertex.BoneIndices = new int[4]; - iVertex.Weights = new float[4]; - for (var k = 0; k < 4; k++) - { - iVertex.BoneIndices[k] = inf.boneIndex[k]; - iVertex.Weights[k] = inf.weight[k]; - } - } - iSubmesh.VertexList.Add(iVertex); - } + iSubmesh.BaseVertex = (int) mesh.m_SubMeshes[i].firstVertex; + //Face iSubmesh.FaceList = new List(numFaces); var end = firstFace + numFaces; @@ -405,9 +334,85 @@ namespace AssetStudio iSubmesh.FaceList.Add(face); } firstFace = end; + iMesh.SubmeshList.Add(iSubmesh); } + // Shared vertex list + iMesh.VertexList = new List((int)mesh.m_VertexCount); + for (var j = 0; j < mesh.m_VertexCount; j++) + { + var iVertex = new ImportedVertex(); + //Vertices + int c = 3; + if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4) + { + c = 4; + } + iVertex.Vertex = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]); + //Normals + if (iMesh.hasNormal) + { + if (mesh.m_Normals.Length == mesh.m_VertexCount * 3) + { + c = 3; + } + else if (mesh.m_Normals.Length == mesh.m_VertexCount * 4) + { + c = 4; + } + iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]); + } + //UV + iVertex.UV = new float[8][]; + for (int uv = 0; uv < 8; uv++) + { + if (iMesh.hasUV[uv]) + { + var m_UV = mesh.GetUV(uv); + if (m_UV.Length == mesh.m_VertexCount * 2) + { + c = 2; + } + else if (m_UV.Length == mesh.m_VertexCount * 3) + { + c = 3; + } + iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] }; + } + } + //Tangent + if (iMesh.hasTangent) + { + iVertex.Tangent = new Vector4(-mesh.m_Tangents[j * 4], mesh.m_Tangents[j * 4 + 1], mesh.m_Tangents[j * 4 + 2], mesh.m_Tangents[j * 4 + 3]); + } + //Colors + if (iMesh.hasColor) + { + if (mesh.m_Colors.Length == mesh.m_VertexCount * 3) + { + iVertex.Color = new Color(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f); + } + else + { + iVertex.Color = new Color(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]); + } + } + //BoneInfluence + if (mesh.m_Skin?.Length > 0) + { + var inf = mesh.m_Skin[j]; + iVertex.BoneIndices = new int[4]; + iVertex.Weights = new float[4]; + for (var k = 0; k < 4; k++) + { + iVertex.BoneIndices[k] = inf.boneIndex[k]; + iVertex.Weights[k] = inf.weight[k]; + } + } + iMesh.VertexList.Add(iVertex); + } + if (meshR is SkinnedMeshRenderer sMesh) { //Bone @@ -524,7 +529,7 @@ namespace AssetStudio keyframe.VertexList.Add(destVertex); var morphVertex = mesh.m_Shapes.vertices[j]; destVertex.Index = morphVertex.index; - var sourceVertex = GetSourceVertex(iMesh.SubmeshList, (int)morphVertex.index); + var sourceVertex = iMesh.VertexList[(int)morphVertex.index]; destVertex.Vertex = new ImportedVertex(); var morphPos = morphVertex.vertex; destVertex.Vertex.Vertex = sourceVertex.Vertex + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z); @@ -1014,20 +1019,6 @@ namespace AssetStudio return boneName; } - private static ImportedVertex GetSourceVertex(List submeshList, int morphVertIndex) - { - foreach (var submesh in submeshList) - { - var vertList = submesh.VertexList; - if (morphVertIndex < vertList.Count) - { - return vertList[morphVertIndex]; - } - morphVertIndex -= vertList.Count; - } - return null; - } - private void CreateBonePathHash(Transform m_Transform) { var name = GetTransformPathByFather(m_Transform);