private void ConvertMeshRenderer(MeshRenderer meshR) { var mesh = GetMesh(meshR); if (mesh == null) { return; } var iMesh = new ImportedMesh(); assetsfileList.TryGetGameObject(meshR.m_GameObject, out var m_GameObject2); assetsfileList.TryGetTransform(m_GameObject2.m_Transform, out var meshTransform); iMesh.Name = GetTransformPath(meshTransform); iMesh.SubmeshList = new List <ImportedSubmesh>(); var subHashSet = new HashSet <int>(); var combine = false; int firstSubMesh = 0; if (meshR.m_StaticBatchInfo?.subMeshCount > 0) { firstSubMesh = meshR.m_StaticBatchInfo.firstSubMesh; var finalSubMesh = meshR.m_StaticBatchInfo.firstSubMesh + meshR.m_StaticBatchInfo.subMeshCount; for (int i = meshR.m_StaticBatchInfo.firstSubMesh; i < finalSubMesh; i++) { subHashSet.Add(i); } combine = true; } else if (meshR.m_SubsetIndices?.Length > 0) { firstSubMesh = (int)meshR.m_SubsetIndices.Min(x => x); foreach (var index in meshR.m_SubsetIndices) { subHashSet.Add((int)index); } combine = true; } int firstFace = 0; for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { int numFaces = (int)mesh.m_SubMeshes[i].indexCount / 3; if (subHashSet.Count > 0 && !subHashSet.Contains(i)) { firstFace += numFaces; continue; } var submesh = mesh.m_SubMeshes[i]; var iSubmesh = new ImportedSubmesh(); Material mat = null; if (i - firstSubMesh < meshR.m_Materials.Length) { if (assetsfileList.TryGetPD(meshR.m_Materials[i - firstSubMesh], out var MaterialPD)) { mat = new Material(MaterialPD); } } ImportedMaterial iMat = ConvertMaterial(mat); iSubmesh.Material = iMat.Name; iSubmesh.VertexList = new List <ImportedVertex>((int)submesh.vertexCount); var vertexColours = mesh.m_Colors != null && (mesh.m_Colors.Length == mesh.m_VertexCount * 3 || mesh.m_Colors.Length == mesh.m_VertexCount * 4); for (var j = mesh.m_SubMeshes[i].firstVertex; j < mesh.m_SubMeshes[i].firstVertex + mesh.m_SubMeshes[i].vertexCount; j++) { var iVertex = vertexColours ? new ImportedVertexWithColour() : new ImportedVertex(); //Vertices int c = 3; if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4) { c = 4; } iVertex.Position = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]); //Normals if (mesh.m_Normals?.Length > 0) { 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]); } //Colors if (vertexColours) { if (mesh.m_Colors.Length == mesh.m_VertexCount * 3) { ((ImportedVertexWithColour)iVertex).Colour = new Color4(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f); } else { ((ImportedVertexWithColour)iVertex).Colour = new Color4(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]); } } //UV if (mesh.m_UV1 != null && mesh.m_UV1.Length == mesh.m_VertexCount * 2) { iVertex.UV = new[] { mesh.m_UV1[j * 2], -mesh.m_UV1[j * 2 + 1] }; } else if (mesh.m_UV2 != null && mesh.m_UV2.Length == mesh.m_VertexCount * 2) { iVertex.UV = new[] { mesh.m_UV2[j * 2], -mesh.m_UV2[j * 2 + 1] }; } //Tangent if (mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4) { 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]); } //BoneInfluence if (mesh.m_Skin.Length > 0) { var inf = mesh.m_Skin[j]; iVertex.BoneIndices = new byte[inf.Count]; iVertex.Weights = new float[inf.Count]; for (var k = 0; k < inf.Count; k++) { iVertex.BoneIndices[k] = (byte)inf[k].boneIndex; iVertex.Weights[k] = inf[k].weight; } } iSubmesh.VertexList.Add(iVertex); } //Face iSubmesh.FaceList = new List <ImportedFace>(numFaces); var end = firstFace + numFaces; for (int f = firstFace; f < end; f++) { var face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = (int)(mesh.m_Indices[f * 3 + 2] - submesh.firstVertex); face.VertexIndices[1] = (int)(mesh.m_Indices[f * 3 + 1] - submesh.firstVertex); face.VertexIndices[2] = (int)(mesh.m_Indices[f * 3] - submesh.firstVertex); iSubmesh.FaceList.Add(face); } firstFace = end; iMesh.SubmeshList.Add(iSubmesh); } if (meshR is SkinnedMeshRenderer sMesh) { //Bone iMesh.BoneList = new List <ImportedBone>(sMesh.m_Bones.Length); /*if (sMesh.m_Bones.Length >= 256) * { * throw new Exception("Too many bones (" + mesh.m_BindPose.Length + ")"); * }*/ for (int i = 0; i < sMesh.m_Bones.Length; i++) { var bone = new ImportedBone(); if (assetsfileList.TryGetTransform(sMesh.m_Bones[i], out var m_Transform)) { if (assetsfileList.TryGetGameObject(m_Transform.m_GameObject, out var m_GameObject)) { bone.Name = m_GameObject.m_Name; } } //No first use m_BoneNameHashes, because it may be wrong if (string.IsNullOrEmpty(bone.Name)) { var boneHash = mesh.m_BoneNameHashes[i]; bone.Name = GetNameFromBonePathHashes(boneHash); if (string.IsNullOrEmpty(bone.Name)) { bone.Name = avatar?.FindBoneName(boneHash); } if (string.IsNullOrEmpty(bone.Name)) { //throw new Exception("A Bone could neither be found by hash in Avatar nor by index in SkinnedMeshRenderer."); continue; } } var om = new float[4, 4]; var m = mesh.m_BindPose[i]; om[0, 0] = m[0, 0]; om[0, 1] = -m[1, 0]; om[0, 2] = -m[2, 0]; om[0, 3] = m[3, 0]; om[1, 0] = -m[0, 1]; om[1, 1] = m[1, 1]; om[1, 2] = m[2, 1]; om[1, 3] = m[3, 1]; om[2, 0] = -m[0, 2]; om[2, 1] = m[1, 2]; om[2, 2] = m[2, 2]; om[2, 3] = m[3, 2]; om[3, 0] = -m[0, 3]; om[3, 1] = m[1, 3]; om[3, 2] = m[2, 3]; om[3, 3] = m[3, 3]; bone.Matrix = om; iMesh.BoneList.Add(bone); } //Morphs if (mesh.m_Shapes != null) { foreach (var channel in mesh.m_Shapes.channels) { morphChannelInfo[channel.nameHash] = channel.name; } if (mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = null; string lastGroup = ""; for (int i = 0; i < mesh.m_Shapes.channels.Count; i++) { string group = BlendShapeNameGroup(mesh, i); if (group != lastGroup) { morph = new ImportedMorph(); MorphList.Add(morph); morph.Name = iMesh.Name; morph.ClipName = group; morph.Channels = new List <Tuple <float, int, int> >(mesh.m_Shapes.channels.Count); morph.KeyframeList = new List <ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); lastGroup = group; } morph.Channels.Add(new Tuple <float, int, int>(i < sMesh.m_BlendShapeWeights.Count ? sMesh.m_BlendShapeWeights[i] : 0f, morph.KeyframeList.Count, mesh.m_Shapes.channels[i].frameCount)); for (int frameIdx = 0; frameIdx < mesh.m_Shapes.channels[i].frameCount; frameIdx++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = BlendShapeNameExtension(mesh, i) + "_" + frameIdx; int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx; keyframe.VertexList = new List <ImportedVertex>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); keyframe.MorphedVertexIndices = new List <ushort>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); keyframe.Weight = shapeIdx < mesh.m_Shapes.fullWeights.Count ? mesh.m_Shapes.fullWeights[shapeIdx] : 100f; int lastVertIndex = (int)(mesh.m_Shapes.shapes[shapeIdx].firstVertex + mesh.m_Shapes.shapes[shapeIdx].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[shapeIdx].firstVertex; j < lastVertIndex; j++) { var morphVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); ImportedVertex destVert = new ImportedVertex(); Vector3 morphPos = morphVert.vertex; morphPos.X *= -1; destVert.Position = vert.Position + morphPos; Vector3 morphNormal = morphVert.normal; morphNormal.X *= -1; destVert.Normal = morphNormal; Vector4 morphTangent = new Vector4(morphVert.tangent, 0); morphTangent.X *= -1; destVert.Tangent = morphTangent; keyframe.VertexList.Add(destVert); keyframe.MorphedVertexIndices.Add((ushort)morphVert.index); } morph.KeyframeList.Add(keyframe); } } } } } //TODO if (combine) { assetsfileList.TryGetGameObject(meshR.m_GameObject, out var m_GameObject); foreach (var root in FrameList) { var frame = ImportedHelpers.FindFrame(m_GameObject.m_Name, root); if (frame?.Parent != null) { var parent = frame; while (true) { if (parent.Parent != null) { parent = parent.Parent; } else { frame.LocalRotation = parent.LocalRotation; frame.LocalScale = parent.LocalScale; frame.LocalPosition = parent.LocalPosition; break; } } } break; } } MeshList.Add(iMesh); }
private void ConvertMeshRenderer(MeshRenderer meshR) { var mesh = GetMesh(meshR); if (mesh == null) { return; } var iMesh = new ImportedMesh(); assetsfileList.TryGetGameObject(meshR.m_GameObject, out var m_GameObject2); assetsfileList.TryGetTransform(m_GameObject2.m_Transform, out var meshTransform); iMesh.Name = GetTransformPath(meshTransform); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.m_SubMeshes.Count); int sum = 0; for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { var submesh = mesh.m_SubMeshes[i]; var iSubmesh = new ImportedSubmesh(); iSubmesh.Index = i; iSubmesh.Visible = true; Material mat = null; if (i < meshR.m_Materials.Length) { if (assetsfileList.TryGetPD(meshR.m_Materials[i], out var MaterialPD)) { mat = new Material(MaterialPD); } } ImportedMaterial iMat = ConvertMaterial(mat); iSubmesh.Material = iMat.Name; iSubmesh.VertexList = new List <ImportedVertex>((int)submesh.vertexCount); var vertexColours = mesh.m_Colors != null && mesh.m_Colors.Length > 0; for (var j = mesh.m_SubMeshes[i].firstVertex; j < mesh.m_SubMeshes[i].firstVertex + mesh.m_SubMeshes[i].vertexCount; j++) { var iVertex = vertexColours ? new ImportedVertexWithColour() : new ImportedVertex(); //Vertices int c = 3; if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4) { c = 4; } iVertex.Position = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]); //Normals if (mesh.m_Normals != null && mesh.m_Normals.Length > 0) { 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]); } //Colors if (vertexColours) { if (mesh.m_Colors.Length == mesh.m_VertexCount * 3) { ((ImportedVertexWithColour)iVertex).Colour = new Color4(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f); } else { ((ImportedVertexWithColour)iVertex).Colour = new Color4(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]); } } //UV if (mesh.m_UV1 != null && mesh.m_UV1.Length == mesh.m_VertexCount * 2) { iVertex.UV = new[] { mesh.m_UV1[j * 2], -mesh.m_UV1[j * 2 + 1] }; } else if (mesh.m_UV2 != null && mesh.m_UV2.Length == mesh.m_VertexCount * 2) { iVertex.UV = new[] { mesh.m_UV2[j * 2], -mesh.m_UV2[j * 2 + 1] }; } //Tangent if (mesh.m_Tangents != null) { 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]); } //BoneInfluence if (mesh.m_Skin.Length > 0) { var inf = mesh.m_Skin[j]; iVertex.BoneIndices = new byte[inf.Count]; iVertex.Weights = new float[inf.Count]; for (var k = 0; k < inf.Count; k++) { iVertex.BoneIndices[k] = (byte)inf[k].boneIndex; iVertex.Weights[k] = inf[k].weight; } } iSubmesh.VertexList.Add(iVertex); } //Face int numFaces = (int)mesh.m_SubMeshes[i].indexCount / 3; iSubmesh.FaceList = new List <ImportedFace>(numFaces); var end = sum + numFaces; for (int f = sum; f < end; f++) { var face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = (int)(mesh.m_Indices[f * 3 + 2] - submesh.firstVertex); face.VertexIndices[1] = (int)(mesh.m_Indices[f * 3 + 1] - submesh.firstVertex); face.VertexIndices[2] = (int)(mesh.m_Indices[f * 3] - submesh.firstVertex); iSubmesh.FaceList.Add(face); } sum = end; iMesh.SubmeshList.Add(iSubmesh); } if (meshR is SkinnedMeshRenderer sMesh) { //Bone iMesh.BoneList = new List <ImportedBone>(sMesh.m_Bones.Length); /*if (sMesh.m_Bones.Length >= 256) * { * throw new Exception("Too many bones (" + mesh.m_BindPose.Length + ")"); * }*/ for (int i = 0; i < sMesh.m_Bones.Length; i++) { var bone = new ImportedBone(); if (assetsfileList.TryGetTransform(sMesh.m_Bones[i], out var m_Transform)) { if (assetsfileList.TryGetGameObject(m_Transform.m_GameObject, out var m_GameObject)) { bone.Name = m_GameObject.m_Name; } } //No first use m_BoneNameHashes, because it may be wrong if (string.IsNullOrEmpty(bone.Name)) { var boneHash = mesh.m_BoneNameHashes[i]; bone.Name = GetNameFromBonePathHashes(boneHash); if (string.IsNullOrEmpty(bone.Name)) { bone.Name = avatar?.FindBoneName(boneHash); } if (string.IsNullOrEmpty(bone.Name)) { throw new Exception("A Bone could neither be found by hash in Avatar nor by index in SkinnedMeshRenderer."); } } var om = new Matrix(); for (int x = 0; x < 4; x++) { for (int y = 0; y < 4; y++) { om[x, y] = mesh.m_BindPose[i][x, y]; } } var m = Matrix.Transpose(om); m.Decompose(out var s, out var q, out var t); t.X *= -1; q.Y *= -1; q.Z *= -1; bone.Matrix = Matrix.Scaling(s) * Matrix.RotationQuaternion(q) * Matrix.Translation(t); iMesh.BoneList.Add(bone); } //Morphs foreach (var channel in mesh.m_Shapes.channels) { morphChannelInfo.Add(channel.nameHash, channel.name); } if (mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = null; string lastGroup = ""; for (int i = 0; i < mesh.m_Shapes.channels.Count; i++) { string group = BlendShapeNameGroup(mesh, i); if (group != lastGroup) { morph = new ImportedMorph(); MorphList.Add(morph); morph.Name = iMesh.Name; morph.ClipName = group; morph.Channels = new List <Tuple <float, int, int> >(mesh.m_Shapes.channels.Count); morph.KeyframeList = new List <ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); lastGroup = group; } morph.Channels.Add(new Tuple <float, int, int>(i < sMesh.m_BlendShapeWeights.Count ? sMesh.m_BlendShapeWeights[i] : 0f, morph.KeyframeList.Count, mesh.m_Shapes.channels[i].frameCount)); for (int frameIdx = 0; frameIdx < mesh.m_Shapes.channels[i].frameCount; frameIdx++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = BlendShapeNameExtension(mesh, i) + "_" + frameIdx; int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx; keyframe.VertexList = new List <ImportedVertex>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); keyframe.MorphedVertexIndices = new List <ushort>((int)mesh.m_Shapes.shapes[shapeIdx].vertexCount); keyframe.Weight = shapeIdx < mesh.m_Shapes.fullWeights.Count ? mesh.m_Shapes.fullWeights[shapeIdx] : 100f; int lastVertIndex = (int)(mesh.m_Shapes.shapes[shapeIdx].firstVertex + mesh.m_Shapes.shapes[shapeIdx].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[shapeIdx].firstVertex; j < lastVertIndex; j++) { var morphVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); ImportedVertex destVert = new ImportedVertex(); Vector3 morphPos = morphVert.vertex; morphPos.X *= -1; destVert.Position = vert.Position + morphPos; Vector3 morphNormal = morphVert.normal; morphNormal.X *= -1; destVert.Normal = morphNormal; Vector4 morphTangent = new Vector4(morphVert.tangent, 0); morphTangent.X *= -1; destVert.Tangent = morphTangent; keyframe.VertexList.Add(destVert); keyframe.MorphedVertexIndices.Add((ushort)morphVert.index); } morph.KeyframeList.Add(keyframe); } } } } MeshList.Add(iMesh); }