public static remSkin CreateBoneList(ImportedMesh mesh, Matrix lMeshMatrixInv) { if (mesh.BoneList == null || mesh.BoneList.Count == 0) { return(null); } Dictionary <int, float>[] boneDic = new Dictionary <int, float> [mesh.BoneList.Count]; for (int i = 0; i < mesh.BoneList.Count; i++) { boneDic[i] = new Dictionary <int, float>(); } int vertexOffset = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { List <ImportedVertex> vertices = submesh.VertexList; for (int i = 0; i < vertices.Count; i++) { ImportedVertex vert = vertices[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { if (vert.BoneIndices[j] == 0xFF) { continue; } boneDic[vert.BoneIndices[j]].Add(vertexOffset + i, vert.Weights[j]); } } vertexOffset += vertices.Count; } remSkin remBoneList = new remSkin(mesh.BoneList.Count); remBoneList.mesh = new remId(mesh.Name); Vector3 scale, translate; Quaternion rotate; lMeshMatrixInv.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); Matrix combinedCorrection = Matrix.Scaling(-1f / scale.X, 1f / scale.Y, -1f / scale.Z) * lMeshMatrixInv; for (int i = 0; i < mesh.BoneList.Count; i++) { remBoneWeights boneWeights = new remBoneWeights(); boneWeights.bone = new remId(mesh.BoneList[i].Name); Matrix lMatrix = Matrix.Invert(mesh.BoneList[i].Matrix); boneWeights.matrix = Matrix.Invert(lMatrix * combinedCorrection); boneWeights.vertexIndices = new int[boneDic[i].Count]; boneDic[i].Keys.CopyTo(boneWeights.vertexIndices, 0); boneWeights.vertexWeights = new float[boneDic[i].Count]; boneDic[i].Values.CopyTo(boneWeights.vertexWeights, 0); remBoneList.AddChild(boneWeights); } return(remBoneList); }
private void Export(DirectoryInfo dir) { try { List <MeshRenderer> meshList = new List <MeshRenderer>(1); meshList.Add(morphObj); Mesh mesh = Operations.GetMesh(morphObj); colorLists = new bool[mesh.m_Shapes.shapes.Count][]; vertLists = new List <ImportedVertex> [mesh.m_Shapes.shapes.Count]; for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { Plugins.UnityConverter conv = new Plugins.UnityConverter(parser, meshList, false, false); ImportedMesh meshObjBase = conv.MeshList[0]; if (faceList == null) { faceList = meshObjBase.SubmeshList[0].FaceList; } List <ImportedVertex> vertList = conv.MeshList[0].SubmeshList[0].VertexList; vertLists[i] = vertList; colorLists[i] = new bool[meshObjBase.SubmeshList[0].VertexList.Count]; int lastVertIndex = (int)(mesh.m_Shapes.shapes[i].firstVertex + mesh.m_Shapes.shapes[i].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[i].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex srcVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = vertList[(int)srcVert.index]; vert.Position += srcVert.vertex; colorLists[i][(int)srcVert.index] = true; } } string dest = Utility.GetDestFile(dir, morphObj.m_GameObject.instance.m_Name + "-" + mesh.m_Name + "-", ".morph.mqo"); Material mat = morphObj.m_Materials[0].instance; Export(dest, mat, mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance); foreach (Texture2D tex in usedTextures) { try { tex.Export(dir.FullName); } catch (Exception ex) { Utility.ReportException(ex); } } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }
public static List <ImportedVertex> ImportedVertexListUnskinned(List <odfVertex> vertList) { List <ImportedVertex> importedList = new List <ImportedVertex>(vertList.Count); for (int i = 0; i < vertList.Count; i++) { ImportedVertex importedVert = new ImportedVertex(); importedList.Add(importedVert); importedVert.Position = vertList[i].Position; importedVert.Normal = vertList[i].Normal; importedVert.UV = new float[] { vertList[i].UV[0], vertList[i].UV[1] }; } return(importedList); }
public static List <ImportedVertex> ImportedVertexListUnskinned(List <remVertex> vertList, float scale) { List <ImportedVertex> importedList = new List <ImportedVertex>(vertList.Count); for (int i = 0; i < vertList.Count; i++) { ImportedVertex importedVert = new ImportedVertex(); importedList.Add(importedVert); importedVert.Position = new Vector3(vertList[i].Position.X, vertList[i].Position.Z, -vertList[i].Position.Y) * scale; importedVert.Normal = new Vector3(vertList[i].Normal.X, vertList[i].Position.Z, -vertList[i].Position.Y); importedVert.UV = new float[] { vertList[i].UV[0], vertList[i].UV[1] }; } return(importedList); }
public static List <ImportedVertex> ImportedVertexListUnskinnedWorld(List <remVertex> vertList, Matrix transform) { List <ImportedVertex> importedList = new List <ImportedVertex>(vertList.Count); for (int i = 0; i < vertList.Count; i++) { ImportedVertex importedVert = new ImportedVertex(); importedList.Add(importedVert); importedVert.Position = Vector3.TransformCoordinate(vertList[i].Position, transform); importedVert.Normal = vertList[i].Normal; importedVert.UV = new float[] { vertList[i].UV[0], vertList[i].UV[1] }; } return(importedList); }
private void Export(DirectoryInfo dir) { try { List <MeshRenderer> meshList = new List <MeshRenderer>(1); meshList.Add(morphObj); Mesh mesh = Operations.GetMesh(morphObj); ImageFileFormat preferredUncompressedFormat = (string)Properties.Settings.Default["ExportUncompressedAs"] == "BMP" ? ImageFileFormat.Bmp : (ImageFileFormat)(-1); colorLists = new List <bool[]>(mesh.m_Shapes.shapes.Count); vertLists = new List <List <ImportedVertex> >(mesh.m_Shapes.shapes.Count); HashSet <int> morphIndices = morphList != null && morphList[0] != null ? new HashSet <int>(morphList[0]) : null; for (int i = 0; i < mesh.m_Shapes.channels.Count; i++) { if (morphIndices != null && !morphIndices.Contains(i)) { continue; } for (int frameIdx = 0; frameIdx < mesh.m_Shapes.channels[i].frameCount; frameIdx++) { int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx; Operations.UnityConverter conv = new Operations.UnityConverter(parser, meshList, false, null, false, preferredUncompressedFormat, false); ImportedMesh meshObjBase = conv.MeshList[0]; if (faceList == null) { faceList = meshObjBase.SubmeshList[0].FaceList; } List <ImportedVertex> vertList = conv.MeshList[0].SubmeshList[0].VertexList; vertLists.Add(vertList); bool[] colours = new bool[meshObjBase.SubmeshList[0].VertexList.Count]; colorLists.Add(colours); 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++) { BlendShapeVertex srcVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = vertList[(int)srcVert.index]; vert.Position = new Vector3 ( vert.Position.X - srcVert.vertex.X, vert.Position.Y + srcVert.vertex.Y, vert.Position.Z + srcVert.vertex.Z ); colours[(int)srcVert.index] = true; } } } string dest = Utility.GetDestFile(dir, morphObj.m_GameObject.instance.m_Name + "-" + mesh.m_Name + "-", ".morph.mqo"); Material mat = null; Texture2D matTex = null; if (morphObj.m_Materials.Count > 0) { mat = morphObj.m_Materials[0].instance; if (mat != null && mat.m_SavedProperties.m_TexEnvs.Count > 0) { matTex = mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance; for (int i = 1; i < mat.m_SavedProperties.m_TexEnvs.Count; i++) { var texProp = mat.m_SavedProperties.m_TexEnvs[i]; if (texProp.Key.name == "_MainTex") { matTex = texProp.Value.m_Texture.instance; break; } } } } Export(dest, mat, matTex); foreach (Texture2D tex in usedTextures) { try { tex.Export(dir.FullName, preferredUncompressedFormat); } catch (Exception ex) { Utility.ReportException(ex); } } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }
private ImportedSubmesh ImportGeometry(Document.Geometry geo, ref int vertInfoIdx) { ImportedSubmesh submesh = null; try { bool hasNormalInput = false; Document.Input positionInput = null; Document.Input normalInput = null; Document.Input texcoordInput = null; for (int i = 0; i < geo.mesh.vertices.inputs.Count; i++) { switch (geo.mesh.vertices.inputs[i].semantic) { case "POSITION": positionInput = geo.mesh.vertices.inputs[i]; break; case "NORMAL": normalInput = geo.mesh.vertices.inputs[i]; break; case "TEXCOORD": texcoordInput = geo.mesh.vertices.inputs[i]; break; } } if (positionInput == null) { throw new Exception("No POSITION vertex input in " + geo.id); } int numVerts = ((Document.Source)positionInput.source).accessor.count; List<ImportedVertex> vertList = new List<ImportedVertex>(numVerts); for (int i = 0; i < numVerts; i++) { ImportedVertex vert = new ImportedVertex(); vertList.Add(vert); vert.Normal = new Vector3(0, 0, 0); vert.UV = new float[] { 0, 0 }; vert.BoneIndices = new byte[] { 0, 0, 0, 0 }; vert.Weights = new float[] { 0, 0, 0, 0 }; if (Z_UP) { vert.Position = new Vector3( GetSourceValue(positionInput, 0, i), GetSourceValue(positionInput, 2, i), -GetSourceValue(positionInput, 1, i)); } else { vert.Position = new Vector3( GetSourceValue(positionInput, 0, i), GetSourceValue(positionInput, 1, i), GetSourceValue(positionInput, 2, i)); } if (normalInput != null) { hasNormalInput = true; if (Z_UP) { vert.Normal = new Vector3( GetSourceValue(normalInput, 0, i), GetSourceValue(normalInput, 2, i), -GetSourceValue(normalInput, 1, i)); } else { vert.Normal = new Vector3( GetSourceValue(normalInput, 0, i), GetSourceValue(normalInput, 1, i), GetSourceValue(normalInput, 2, i)); } } if (texcoordInput == null) { vert.UV = new float[2]; } else { if (IsBlender) { vert.UV = new float[] { GetSourceValue(texcoordInput, 0, i), -GetSourceValue(texcoordInput, 1, i) }; } else { vert.UV = new float[] { GetSourceValue(texcoordInput, 0, i), 1.0f - GetSourceValue(texcoordInput, 1, i) }; } } vertInfoIdx++; } List<ImportedFace> faceList = new List<ImportedFace>(); foreach (Document.Primitive primitive in geo.mesh.primitives) { if (primitive is Document.Triangle) { Document.Input vertexInput = null; List<Document.Input> normalInputs = new List<Document.Input>(); List<Document.Input> textureInputs = new List<Document.Input>(); foreach (Document.Input input in primitive.Inputs) { switch (input.semantic) { case "VERTEX": vertexInput = input; break; case "NORMAL": hasNormalInput = true; normalInputs.Add(input); break; case "TEXCOORD": textureInputs.Add(input); break; } } if (vertexInput != null) { for (int faceIdx = 0; faceIdx < primitive.count; faceIdx++) { ushort[] faceVerts = new ushort[3]; for (int i = 0; i < 3; i++) { int pIdx = (faceIdx * 3) + i; int vertIdx = GetPValue(vertexInput, primitive, pIdx); faceVerts[i] = (ushort)vertIdx; ImportedVertex vert = vertList[vertIdx]; for (int j = 0; j < normalInputs.Count; j++) { int p = GetPValue(normalInputs[j], primitive, pIdx); if (Z_UP) { vert.Normal = new Vector3( GetSourceValue(normalInputs[j], 0, p), GetSourceValue(normalInputs[j], 2, p), -GetSourceValue(normalInputs[j], 1, p)); } else { vert.Normal = new Vector3( GetSourceValue(normalInputs[j], 0, p), GetSourceValue(normalInputs[j], 1, p), GetSourceValue(normalInputs[j], 2, p)); } } for (int j = 0; j < textureInputs.Count; j++) { int p = GetPValue(textureInputs[j], primitive, pIdx); if (IsBlender) { vert.UV = new float[] { GetSourceValue(textureInputs[j], 0, p), -GetSourceValue(textureInputs[j], 1, p) }; } else { vert.UV = new float[] { GetSourceValue(textureInputs[j], 0, p), 1.0f - GetSourceValue(textureInputs[j], 1, p) }; } } } ImportedFace face = new ImportedFace(); faceList.Add(face); face.VertexIndices = new int[3] { faceVerts[0], faceVerts[1], faceVerts[2] }; } } } } submesh = new ImportedSubmesh(); submesh.VertexList = vertList; submesh.FaceList = faceList; if (!hasNormalInput) { for (int i = 0; i < submesh.VertexList.Count; i++) { submesh.VertexList[i].Normal = new Vector3(); } } } catch (Exception e) { Report.ReportLog("Error importing " + geo.id + ": " + e.Message); } return submesh; }
public static odfMesh CreateMesh(WorkspaceMesh mesh, int subMeshFormat, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; materialNames = new string[numSubmeshes]; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; odfMesh newMesh = new odfMesh(new ObjectName(String.Empty, null), null, numSubmeshes); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } ImportedSubmesh submesh = mesh.SubmeshList[submeshIdx]; odfSubmesh newSubmesh = new odfSubmesh(new ObjectName(String.Empty, null), null, subMeshFormat); newMesh.AddChild(newSubmesh); newSubmesh.MaterialId = ObjectID.INVALID; materialNames[i] = submesh.Material; indices[i] = submesh.Index; worldCoords[i] = submesh.WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(mesh.SubmeshList[submeshIdx]); List <ImportedVertex> vertexList = submesh.VertexList; List <odfVertex> newVertexList = new List <odfVertex>(vertexList.Count); for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; odfVertex newVertex = new odfVertex(); newVertex.Normal = vert.Normal; newVertex.UV = new Vector2(vert.UV[0], vert.UV[1]); newVertex.Weights = (float[])vert.Weights.Clone(); newVertex.BoneIndices = (byte[])vert.BoneIndices.Clone(); newVertex.Position = vert.Position; newVertexList.Add(newVertex); } newSubmesh.VertexList = newVertexList; List <ImportedFace> faceList = submesh.FaceList; List <odfFace> newFaceList = new List <odfFace>(faceList.Count); for (int j = 0; j < faceList.Count; j++) { int[] vertexIndices = faceList[j].VertexIndices; odfFace newFace = new odfFace(); newFace.VertexIndices = new ushort[3] { (ushort)vertexIndices[0], (ushort)vertexIndices[1], (ushort)vertexIndices[2] }; newFaceList.Add(newFace); } newSubmesh.FaceList = newFaceList; } return(newMesh); }
private void ConvertMeshes(List<odfMesh> meshes, odfParser parser) { MeshList = new List<ImportedMesh>(meshes.Count); MaterialList = new List<ImportedMaterial>(meshes.Count); TextureList = new List<ImportedTexture>(parser.TextureSection != null ? parser.TextureSection.Count : 0); foreach (odfMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.Name = odf.FindMeshFrame(mesh.Id, parser.FrameSection.RootFrame).Name; iMesh.BoneList = new List<ImportedBone>(); Dictionary<ObjectID, byte> boneDic = new Dictionary<ObjectID, byte>(); iMesh.SubmeshList = new List<ImportedSubmesh>(mesh.Count); foreach (odfSubmesh submesh in mesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { iSubmesh.Material = mat.Name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = mat.Diffuse; iMat.Ambient = mat.Ambient; iMat.Specular = mat.Specular; iMat.Emissive = mat.Emissive; iMat.Power = mat.SpecularPower; iMat.Textures = new string[4]; for (int i = 0; i < 4; i++) { if (submesh.TextureIds[i] != ObjectID.INVALID) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[i], parser.TextureSection); iMat.Textures[i] = tex.Name; if (ImportedHelpers.FindTexture(iMat.Textures[i], TextureList) == null) { try { odfTextureFile texFile = new odfTextureFile(iMat.Textures[i], Path.GetDirectoryName(parser.ODFPath) + @"\" + iMat.Textures[i]); MemoryStream memStream; int filesize = 0; using (BinaryReader reader = texFile.DecryptFile(ref filesize)) { memStream = new MemoryStream(reader.ReadBytes(filesize)); } ImportedTexture iTex = new ImportedTexture(memStream, iMat.Textures[i]); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[i]); } } } else { iMat.Textures[i] = String.Empty; } } } } List<Tuple<byte, float>>[] skin = new List<Tuple<byte, float>>[submesh.NumVertices]; for (int i = 0; i < submesh.NumVertices; i++) { skin[i] = new List<Tuple<byte, float>>(4); } odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (odfBone bone in boneList) { byte idx; if (!boneDic.TryGetValue(bone.FrameId, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; iBone.Matrix = bone.Matrix; boneDic.Add(bone.FrameId, idx = (byte)boneDic.Count); } for (int i = 0; i < bone.NumberIndices; i++) { skin[bone.VertexIndexArray[i]].Add(new Tuple<byte, float>(idx, bone.WeightArray[i])); } } } iSubmesh.VertexList = new List<ImportedVertex>(submesh.NumVertices); for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = vert.Position; iVert.Normal = vert.Normal; iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < skin[i].Count) { Tuple<byte, float> vertIdxWeight = skin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = new List<ImportedFace>(submesh.NumVertexIndices / 3); foreach (odfFace face in submesh.FaceList) { ImportedFace iFace = new ImportedFace(); iSubmesh.FaceList.Add(iFace); iFace.VertexIndices = new int[3]; for (int i = 0; i < 3; i++) { iFace.VertexIndices[i] = face.VertexIndices[i]; } } } } }
private void ConvertMeshes(List <odfMesh> meshes, odfParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.TextureSection != null ? parser.TextureSection.Count : 0); foreach (odfMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.Name = odf.FindMeshFrame(mesh.Id, parser.FrameSection.RootFrame).Name; iMesh.BoneList = new List <ImportedBone>(); Dictionary <ObjectID, byte> boneDic = new Dictionary <ObjectID, byte>(); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.Count); foreach (odfSubmesh submesh in mesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { iSubmesh.Material = mat.Name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = mat.Diffuse; iMat.Ambient = mat.Ambient; iMat.Specular = mat.Specular; iMat.Emissive = mat.Emissive; iMat.Power = mat.SpecularPower; iMat.Textures = new string[4]; for (int i = 0; i < 4; i++) { if (submesh.TextureIds[i] != ObjectID.INVALID) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[i], parser.TextureSection); iMat.Textures[i] = tex.Name; if (ImportedHelpers.FindTexture(iMat.Textures[i], TextureList) == null) { try { odfTextureFile texFile = new odfTextureFile(iMat.Textures[i], Path.GetDirectoryName(parser.ODFPath) + @"\" + iMat.Textures[i]); MemoryStream memStream; int filesize = 0; using (BinaryReader reader = texFile.DecryptFile(ref filesize)) { memStream = new MemoryStream(reader.ReadBytes(filesize)); } ImportedTexture iTex = new ImportedTexture(memStream, iMat.Textures[i]); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[i]); } } } else { iMat.Textures[i] = String.Empty; } } } } List <Tuple <byte, float> >[] skin = new List <Tuple <byte, float> > [submesh.NumVertices]; for (int i = 0; i < submesh.NumVertices; i++) { skin[i] = new List <Tuple <byte, float> >(4); } odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (odfBone bone in boneList) { byte idx; if (!boneDic.TryGetValue(bone.FrameId, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; iBone.Matrix = bone.Matrix; boneDic.Add(bone.FrameId, idx = (byte)boneDic.Count); } for (int i = 0; i < bone.NumberIndices; i++) { skin[bone.VertexIndexArray[i]].Add(new Tuple <byte, float>(idx, bone.WeightArray[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.NumVertices); for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = vert.Position; iVert.Normal = vert.Normal; iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < skin[i].Count) { Tuple <byte, float> vertIdxWeight = skin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = new List <ImportedFace>(submesh.NumVertexIndices / 3); foreach (odfFace face in submesh.FaceList) { ImportedFace iFace = new ImportedFace(); iSubmesh.FaceList.Add(iFace); iFace.VertexIndices = new int[3]; for (int i = 0; i < 3; i++) { iFace.VertexIndices[i] = face.VertexIndices[i]; } } } } }
private void ConvertMeshRenderers(List <MeshRenderer> meshList, bool skins, bool morphs) { MeshList = new List <ImportedMesh>(meshList.Count); MaterialList = new List <ImportedMaterial>(meshList.Count); TextureList = new List <ImportedTexture>(meshList.Count); MorphList = new List <ImportedMorph>(meshList.Count); foreach (MeshRenderer meshR in meshList) { Mesh mesh = Operations.GetMesh(meshR); if (mesh == null) { Report.ReportLog("skipping " + meshR.m_GameObject.instance.m_Name + " - no mesh"); continue; } ImportedMesh iMesh = new ImportedMesh(); Transform meshTransform = meshR.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); iMesh.Name = meshTransform.GetTransformPath(); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.m_SubMeshes.Count); using (BinaryReader vertReader = new BinaryReader(new MemoryStream(mesh.m_VertexData.m_DataSize)), indexReader = new BinaryReader(new MemoryStream(mesh.m_IndexBuffer))) { for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { SubMesh submesh = mesh.m_SubMeshes[i]; ImportedSubmesh iSubmesh = new ImportedSubmesh(); iSubmesh.Index = i; iSubmesh.Visible = true; Material mat = meshR.m_Materials[i].instance; ConvertMaterial(mat); iSubmesh.Material = mat.m_Name; iSubmesh.VertexList = new List <ImportedVertex>((int)submesh.vertexCount); for (int str = 0; str < mesh.m_VertexData.m_Streams.Count; str++) { StreamInfo sInfo = mesh.m_VertexData.m_Streams[str]; if (sInfo.channelMask == 0) { continue; } for (int j = 0; j < mesh.m_SubMeshes[i].vertexCount; j++) { ImportedVertex iVertex; if (iSubmesh.VertexList.Count < mesh.m_SubMeshes[i].vertexCount) { iVertex = new ImportedVertex(); iSubmesh.VertexList.Add(iVertex); } else { iVertex = iSubmesh.VertexList[j]; } for (int chn = 0; chn < mesh.m_VertexData.m_Channels.Count; chn++) { ChannelInfo cInfo = mesh.m_VertexData.m_Channels[chn]; if ((sInfo.channelMask & (1 << chn)) == 0) { continue; } vertReader.BaseStream.Position = sInfo.offset + (submesh.firstVertex + j) * sInfo.stride + cInfo.offset; switch (chn) { case 0: iVertex.Position = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 1: iVertex.Normal = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 3: iVertex.UV = new float[2] { vertReader.ReadSingle(), vertReader.ReadSingle() }; break; case 5: iVertex.Tangent = new SlimDX.Vector4(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle(), -vertReader.ReadSingle()); break; } } if (skins && iVertex.BoneIndices == null && mesh.m_Skin.Count > 0) { BoneInfluence inf = mesh.m_Skin[(int)submesh.firstVertex + j]; iVertex.BoneIndices = new byte[inf.boneIndex.Length]; for (int k = 0; k < iVertex.BoneIndices.Length; k++) { iVertex.BoneIndices[k] = (byte)inf.boneIndex[k]; } iVertex.Weights = (float[])inf.weight.Clone(); } } } int numFaces = (int)(submesh.indexCount / 3); iSubmesh.FaceList = new List <ImportedFace>(numFaces); indexReader.BaseStream.Position = submesh.firstByte; for (int j = 0; j < numFaces; j++) { ImportedFace face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[2] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[1] = indexReader.ReadUInt16() - (int)submesh.firstVertex; iSubmesh.FaceList.Add(face); } iMesh.SubmeshList.Add(iSubmesh); } } if (skins && meshR is SkinnedMeshRenderer) { SkinnedMeshRenderer sMesh = (SkinnedMeshRenderer)meshR; if (sMesh.m_Bones.Count >= 256) { throw new Exception("Too many bones (" + mesh.m_BindPose.Count + ")"); } if (sMesh.m_Bones.Count != mesh.m_BindPose.Count || sMesh.m_Bones.Count != mesh.m_BoneNameHashes.Count) { throw new Exception("Mismatching number of bones bind pose=" + mesh.m_BindPose.Count + " hashes=" + mesh.m_BoneNameHashes.Count + " numBones=" + sMesh.m_Bones.Count); } iMesh.BoneList = new List <ImportedBone>(sMesh.m_Bones.Count); for (int i = 0; i < sMesh.m_Bones.Count; i++) { ImportedBone bone = new ImportedBone(); uint boneHash = mesh.m_BoneNameHashes[i]; bone.Name = avatar.FindBoneName(boneHash); Matrix m = Matrix.Transpose(mesh.m_BindPose[i]); Vector3 s, t; Quaternion q; m.Decompose(out s, out q, out t); t.X *= -1; Vector3 euler = FbxUtility.QuaternionToEuler(q); euler.Y *= -1; euler.Z *= -1; q = FbxUtility.EulerToQuaternion(euler); bone.Matrix = Matrix.Scaling(s) * Matrix.RotationQuaternion(q) * Matrix.Translation(t); iMesh.BoneList.Add(bone); } } if (morphs && mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = new ImportedMorph(); morph.Name = iMesh.Name; morph.ClipName = Operations.BlendShapeName(mesh); morph.KeyframeList = new List <ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = Operations.BlendShapeKeyframeName(mesh, i); keyframe.VertexList = new List <ImportedVertex>((int)mesh.m_Shapes.shapes[i].vertexCount); keyframe.MorphedVertexIndices = new List <ushort>((int)mesh.m_Shapes.shapes[i].vertexCount); int lastVertIndex = (int)(mesh.m_Shapes.shapes[i].firstVertex + mesh.m_Shapes.shapes[i].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[i].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex 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); } MorphList.Add(morph); } MeshList.Add(iMesh); } }
public static SkinnedMeshRenderer CreateSkinnedMeshRenderer(Animator parser, List <Material> materials, WorkspaceMesh mesh, Matrix meshMatrix, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; List <Matrix> poseMatrices = new List <Matrix>(mesh.BoneList.Count); Transform animatorTransform = parser.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); List <PPtr <Transform> > bones = CreateBoneList(animatorTransform, meshMatrix, mesh.BoneList, poseMatrices); SkinnedMeshRenderer sMesh = new SkinnedMeshRenderer(parser.file); int totVerts = 0, totFaces = 0; sMesh.m_Materials.Capacity = numSubmeshes; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { continue; } Material matFound = materials.Find ( delegate(Material mat) { return(mat.m_Name == submesh.Material); } ); sMesh.m_Materials.Add(new PPtr <Material>(matFound)); totVerts += submesh.VertexList.Count; totFaces += submesh.FaceList.Count; } Mesh uMesh = new Mesh(parser.file); uMesh.m_Name = mesh.Name; sMesh.m_Mesh = new PPtr <Mesh>(uMesh); sMesh.m_Bones = bones; uMesh.m_BindPose = poseMatrices; uMesh.m_BoneNameHashes = new List <uint>(poseMatrices.Count); for (int i = 0; i < mesh.BoneList.Count; i++) { string bone = mesh.BoneList[i].Name; uint hash = parser.m_Avatar.instance.BoneHash(bone); uMesh.m_BoneNameHashes.Add(hash); } uMesh.m_VertexData = new VertexData((uint)totVerts); uMesh.m_Skin = new List <BoneInfluence>(totVerts); uMesh.m_IndexBuffer = new byte[totFaces * 3 * sizeof(ushort)]; using (BinaryWriter vertWriter = new BinaryWriter(new MemoryStream(uMesh.m_VertexData.m_DataSize)), indexWriter = new BinaryWriter(new MemoryStream(uMesh.m_IndexBuffer))) { uMesh.m_LocalAABB.m_Center = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue); uMesh.m_LocalAABB.m_Extend = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue); uMesh.m_SubMeshes = new List <SubMesh>(numSubmeshes); int vertIndex = 0; for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } SubMesh submesh = new SubMesh(); submesh.indexCount = (uint)mesh.SubmeshList[submeshIdx].FaceList.Count * 3; submesh.vertexCount = (uint)mesh.SubmeshList[submeshIdx].VertexList.Count; submesh.firstVertex = (uint)vertIndex; uMesh.m_SubMeshes.Add(submesh); indices[i] = mesh.SubmeshList[submeshIdx].Index; worldCoords[i] = mesh.SubmeshList[submeshIdx].WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(mesh.SubmeshList[submeshIdx]); List <ImportedVertex> vertexList = mesh.SubmeshList[submeshIdx].VertexList; Vector3 min = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue); Vector3 max = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue); for (int str = 0; str < uMesh.m_VertexData.m_Streams.Count; str++) { StreamInfo sInfo = uMesh.m_VertexData.m_Streams[str]; if (sInfo.channelMask == 0) { continue; } for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; for (int chn = 0; chn < uMesh.m_VertexData.m_Channels.Count; chn++) { ChannelInfo cInfo = uMesh.m_VertexData.m_Channels[chn]; if ((sInfo.channelMask & (1 << chn)) == 0) { continue; } vertWriter.BaseStream.Position = sInfo.offset + (j + submesh.firstVertex) * sInfo.stride + cInfo.offset; switch (chn) { case 0: Vector3 pos = vert.Position; pos.X *= -1; vertWriter.Write(pos); min = Vector3.Minimize(min, pos); max = Vector3.Maximize(max, pos); break; case 1: Vector3 normal = vert.Normal; normal.X *= -1; vertWriter.Write(normal); break; case 3: vertWriter.Write(vert.UV); break; case 5: Vector4 tangent = vert.Tangent; tangent.X *= -1; tangent.W *= -1; vertWriter.Write(tangent); break; } } if (sMesh.m_Bones.Count > 0 && sInfo.offset == 0 && uMesh.m_Skin.Count < totVerts) { BoneInfluence item = new BoneInfluence(); for (int k = 0; k < 4; k++) { item.boneIndex[k] = vert.BoneIndices[k] != 0xFF ? vert.BoneIndices[k] : 0; } vert.Weights.CopyTo(item.weight, 0); uMesh.m_Skin.Add(item); } } } vertIndex += (int)submesh.vertexCount; submesh.localAABB.m_Extend = max - min; submesh.localAABB.m_Center = min + submesh.localAABB.m_Extend / 2; uMesh.m_LocalAABB.m_Extend = Vector3.Maximize(uMesh.m_LocalAABB.m_Extend, max); uMesh.m_LocalAABB.m_Center = Vector3.Minimize(uMesh.m_LocalAABB.m_Center, min); List <ImportedFace> faceList = mesh.SubmeshList[submeshIdx].FaceList; submesh.firstByte = (uint)indexWriter.BaseStream.Position; for (int j = 0; j < faceList.Count; j++) { int[] vertexIndices = faceList[j].VertexIndices; indexWriter.Write((ushort)(vertexIndices[0] + submesh.firstVertex)); indexWriter.Write((ushort)(vertexIndices[2] + submesh.firstVertex)); indexWriter.Write((ushort)(vertexIndices[1] + submesh.firstVertex)); } } uMesh.m_LocalAABB.m_Extend -= uMesh.m_LocalAABB.m_Center; uMesh.m_LocalAABB.m_Center += uMesh.m_LocalAABB.m_Extend / 2; } return(sMesh); }
private void ConvertMeshes(List <remMesh> meshes, remParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.MATC.Count); foreach (remMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.BoneList = new List <ImportedBone>(); Dictionary <remId, byte> boneDic = new Dictionary <remId, byte>(); remSkin skin = rem.FindSkin(mesh.name, parser.SKIC); rem.Mesh convertedMesh = new rem.Mesh(mesh, skin); iMesh.SubmeshList = new List <ImportedSubmesh>(convertedMesh.Count); remBone meshFrame = rem.FindFrame(mesh.frame, parser.BONC.rootFrame); ImportedFrame iFrame = ImportedHelpers.FindFrame(mesh.frame, FrameList[0]); float s = (float)Math.Round(Math.Abs(meshFrame.matrix.M11), 5); iFrame.Name = iMesh.Name = mesh.name + (s != 1f ? "(Scale=" + s.ToString() + ")" : String.Empty); foreach (rem.Submesh submesh in convertedMesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); remMaterial mat = rem.FindMaterial(submesh.MaterialName, parser.MATC); if (mat != null) { iSubmesh.Material = mat.name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = new Color4(mat.diffuse); iMat.Ambient = new Color4(mat.ambient); iMat.Specular = new Color4(mat.specular); iMat.Emissive = new Color4(mat.emissive); iMat.Power = mat.specularPower; iMat.Textures = new string[4] { String.Empty, String.Empty, String.Empty, String.Empty }; if (mat.texture != null) { iMat.Textures[0] = mat.texture; if (ImportedHelpers.FindTexture(iMat.Textures[0], TextureList) == null) { try { ImportedTexture iTex = rem.ImportedTexture(mat.texture, parser.RemPath, true); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[0]); } } } } } List <Tuple <byte, float> >[] iSkin = new List <Tuple <byte, float> > [submesh.numVertices]; for (int i = 0; i < submesh.numVertices; i++) { iSkin[i] = new List <Tuple <byte, float> >(4); } List <remBoneWeights> boneList = submesh.BoneList; if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (remBoneWeights boneWeights in boneList) { byte idx; if (!boneDic.TryGetValue(boneWeights.bone, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = boneWeights.bone; Vector3 scale, translate; Quaternion rotate; meshFrame.matrix.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); iBone.Matrix = Matrix.Scaling(1f, 1f, -1f) * Matrix.Invert(meshFrame.matrix) * Matrix.Scaling(scale) * boneWeights.matrix; boneDic.Add(boneWeights.bone, idx = (byte)boneDic.Count); } for (int i = 0; i < boneWeights.numVertIdxWts; i++) { iSkin[boneWeights.vertexIndices[i]].Add(new Tuple <byte, float>(idx, boneWeights.vertexWeights[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.numVertices); for (int i = 0; i < submesh.numVertices; i++) { remVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = new Vector3(vert.Position.X, vert.Position.Z, -vert.Position.Y); iVert.Normal = new Vector3(vert.Normal.X, vert.Normal.Z, -vert.Normal.Y); iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < iSkin[i].Count) { Tuple <byte, float> vertIdxWeight = iSkin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = rem.ImportedFaceList(submesh.FaceList); } } }
private void ConvertMeshRenderers(List<MeshRenderer> meshList, bool skins, bool morphs) { MeshList = new List<ImportedMesh>(meshList.Count); MaterialList = new List<ImportedMaterial>(meshList.Count); TextureList = new List<ImportedTexture>(meshList.Count); MorphList = new List<ImportedMorph>(meshList.Count); foreach (MeshRenderer meshR in meshList) { Mesh mesh = Operations.GetMesh(meshR); if (mesh == null) { Report.ReportLog("skipping " + meshR.m_GameObject.instance.m_Name + " - no mesh"); continue; } ImportedMesh iMesh = new ImportedMesh(); Transform meshTransform = meshR.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); iMesh.Name = meshTransform.GetTransformPath(); iMesh.SubmeshList = new List<ImportedSubmesh>(mesh.m_SubMeshes.Count); using (BinaryReader vertReader = new BinaryReader(new MemoryStream(mesh.m_VertexData.m_DataSize)), indexReader = new BinaryReader(new MemoryStream(mesh.m_IndexBuffer))) { for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { SubMesh submesh = mesh.m_SubMeshes[i]; ImportedSubmesh iSubmesh = new ImportedSubmesh(); iSubmesh.Index = i; iSubmesh.Visible = true; Material mat = meshR.m_Materials[i].instance; ConvertMaterial(mat); iSubmesh.Material = mat.m_Name; iSubmesh.VertexList = new List<ImportedVertex>((int)submesh.vertexCount); for (int str = 0; str < mesh.m_VertexData.m_Streams.Count; str++) { StreamInfo sInfo = mesh.m_VertexData.m_Streams[str]; if (sInfo.channelMask == 0) { continue; } for (int j = 0; j < mesh.m_SubMeshes[i].vertexCount; j++) { ImportedVertex iVertex; if (iSubmesh.VertexList.Count < mesh.m_SubMeshes[i].vertexCount) { iVertex = new ImportedVertex(); iSubmesh.VertexList.Add(iVertex); } else { iVertex = iSubmesh.VertexList[j]; } for (int chn = 0; chn < mesh.m_VertexData.m_Channels.Count; chn++) { ChannelInfo cInfo = mesh.m_VertexData.m_Channels[chn]; if ((sInfo.channelMask & (1 << chn)) == 0) { continue; } vertReader.BaseStream.Position = sInfo.offset + (submesh.firstVertex + j) * sInfo.stride + cInfo.offset; switch (chn) { case 0: iVertex.Position = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 1: iVertex.Normal = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 3: iVertex.UV = new float[2] { vertReader.ReadSingle(), vertReader.ReadSingle() }; break; case 5: iVertex.Tangent = new SlimDX.Vector4(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle(), -vertReader.ReadSingle()); break; } } if (skins && iVertex.BoneIndices == null && mesh.m_Skin.Count > 0) { BoneInfluence inf = mesh.m_Skin[(int)submesh.firstVertex + j]; iVertex.BoneIndices = new byte[inf.boneIndex.Length]; for (int k = 0; k < iVertex.BoneIndices.Length; k++) { iVertex.BoneIndices[k] = (byte)inf.boneIndex[k]; } iVertex.Weights = (float[])inf.weight.Clone(); } } } int numFaces = (int)(submesh.indexCount / 3); iSubmesh.FaceList = new List<ImportedFace>(numFaces); indexReader.BaseStream.Position = submesh.firstByte; for (int j = 0; j < numFaces; j++) { ImportedFace face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[2] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[1] = indexReader.ReadUInt16() - (int)submesh.firstVertex; iSubmesh.FaceList.Add(face); } iMesh.SubmeshList.Add(iSubmesh); } } if (skins && meshR is SkinnedMeshRenderer) { SkinnedMeshRenderer sMesh = (SkinnedMeshRenderer)meshR; if (sMesh.m_Bones.Count >= 256) { throw new Exception("Too many bones (" + mesh.m_BindPose.Count + ")"); } if (sMesh.m_Bones.Count != mesh.m_BindPose.Count || sMesh.m_Bones.Count != mesh.m_BoneNameHashes.Count) { throw new Exception("Mismatching number of bones bind pose=" + mesh.m_BindPose.Count + " hashes=" + mesh.m_BoneNameHashes.Count + " numBones=" + sMesh.m_Bones.Count); } iMesh.BoneList = new List<ImportedBone>(sMesh.m_Bones.Count); for (int i = 0; i < sMesh.m_Bones.Count; i++) { ImportedBone bone = new ImportedBone(); uint boneHash = mesh.m_BoneNameHashes[i]; bone.Name = avatar.FindBoneName(boneHash); Matrix m = Matrix.Transpose(mesh.m_BindPose[i]); Vector3 s, t; Quaternion q; m.Decompose(out s, out q, out t); t.X *= -1; Vector3 euler = FbxUtility.QuaternionToEuler(q); euler.Y *= -1; euler.Z *= -1; q = FbxUtility.EulerToQuaternion(euler); bone.Matrix = Matrix.Scaling(s) * Matrix.RotationQuaternion(q) * Matrix.Translation(t); iMesh.BoneList.Add(bone); } } if (morphs && mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = new ImportedMorph(); morph.Name = iMesh.Name; morph.ClipName = Operations.BlendShapeName(mesh); morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = Operations.BlendShapeKeyframeName(mesh, i); keyframe.VertexList = new List<ImportedVertex>((int)mesh.m_Shapes.shapes[i].vertexCount); keyframe.MorphedVertexIndices = new List<ushort>((int)mesh.m_Shapes.shapes[i].vertexCount); int lastVertIndex = (int)(mesh.m_Shapes.shapes[i].firstVertex + mesh.m_Shapes.shapes[i].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[i].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex 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); } MorphList.Add(morph); } MeshList.Add(iMesh); } }
public static remMesh CreateMesh(WorkspaceMesh mesh, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; materialNames = new string[numSubmeshes]; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; remMesh newMesh = new remMesh(numSubmeshes); newMesh.name = new remId(mesh.Name); List <remVertex> newVertices = new List <remVertex>(); List <int> newFaces = new List <int>(); List <int> newFaceMarks = new List <int>(); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } ImportedSubmesh submesh = mesh.SubmeshList[submeshIdx]; newMesh.AddMaterial(new remId(submesh.Material)); materialNames[i] = submesh.Material; indices[i] = submesh.Index; worldCoords[i] = submesh.WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(submesh); List <ImportedFace> faceList = submesh.FaceList; newFaces.Capacity += faceList.Count * 3; int[] faceMarks = new int[faceList.Count]; for (int j = 0; j < faceList.Count; j++) { ImportedFace face = faceList[j]; for (int k = 0; k < 3; k++) { newFaces.Add(face.VertexIndices[k] + newVertices.Count); } faceMarks[j] = i; } newFaceMarks.AddRange(faceMarks); List <ImportedVertex> vertexList = submesh.VertexList; newVertices.Capacity += vertexList.Count; for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; remVertex newVertex = new remVertex(); if (submesh.WorldCoords) { newVertex.Position = vert.Position; newVertex.Normal = vert.Normal; } else { newVertex.Position = new Vector3(vert.Position.X, -vert.Position.Z, vert.Position.Y); newVertex.Normal = new Vector3(vert.Normal.X, -vert.Normal.Z, vert.Normal.Y); } newVertex.UV = new Vector2(vert.UV[0], vert.UV[1]); newVertices.Add(newVertex); } } newMesh.vertices = newVertices.ToArray(); newMesh.faces = newFaces.ToArray(); newMesh.faceMarks = newFaceMarks.ToArray(); return(newMesh); }
private void ImportMesh(Section section, ImportedMesh meshList, SortedDictionary<string, byte> boneDic, List<bool> hasBonesList) { int vertIdxOffset = 0; foreach (ImportedSubmesh submesh in meshList.SubmeshList) { vertIdxOffset += submesh.VertexList.Count; } LinkedListNode<object> node = section.data.First; int numVertices = ConvertInt32(node.Value); node = node.Next; DXVertex[] vertices = new DXVertex[numVertices]; for (int i = 0; i < numVertices; i++) { vertices[i] = new DXVertex(); float[] pos = new float[3]; for (int j = 0; j < pos.Length; j++) { pos[j] = ConvertFloat(node.Value); node = node.Next; } pos[2] = -pos[2]; vertices[i].position = pos; } int numFaces = ConvertInt32(node.Value); node = node.Next; DXFace[] faces = new DXFace[numFaces]; for (int i = 0; i < numFaces; i++) { int numFaceVerts = ConvertInt32(node.Value); node = node.Next; if (numFaceVerts != 3) { throw new Exception("Meshes must be triangulated"); } faces[i] = new DXFace(); faces[i].vertexIndices[0] = ConvertUInt16(node.Value); node = node.Next; faces[i].vertexIndices[2] = ConvertUInt16(node.Value); node = node.Next; faces[i].vertexIndices[1] = ConvertUInt16(node.Value); node = node.Next; } string[] materials = new string[] { String.Empty }; bool hasNormals = false; bool hasBones = false; bool hasUVs = false; List<KeyValuePair<byte, float>>[] boneAssignments = new List<KeyValuePair<byte, float>>[numVertices]; for (int i = 0; i < boneAssignments.Length; i++) { boneAssignments[i] = new List<KeyValuePair<byte, float>>(); } foreach (Section child in section.children) { if (child.type == "VertexDuplicationIndices") { } else if (child.type == "MeshNormals") { hasNormals = true; LinkedListNode<object> childNode = child.data.First; int numNormals = ConvertInt32(childNode.Value); childNode = childNode.Next; if (numNormals != numVertices) { throw new Exception("Number of normals doesn't match the number of vertices"); } foreach (DXVertex vert in vertices) { float[] norm = new float[3]; for (int i = 0; i < norm.Length; i++) { norm[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } norm[2] = -norm[2]; vert.normal = norm; } } else if (child.type == "MeshTextureCoords") { hasUVs = true; LinkedListNode<object> childNode = child.data.First; int numTexCoords = ConvertInt32(childNode.Value); childNode = childNode.Next; if (numTexCoords != numVertices) { throw new Exception("Number of texture coordinates doesn't match the number of vertices"); } foreach (DXVertex vert in vertices) { float[] uv = new float[2]; for (int i = 0; i < uv.Length; i++) { uv[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } vert.uv = uv; } } else if (child.type == "MeshMaterialList") { materials = ImportMaterials(child, faces); } else if (child.type == "XSkinMeshHeader") { hasBones = true; } else if (child.type == "SkinWeights") { LinkedListNode<object> childNode = child.data.First; string boneName = ConvertString(childNode.Value); childNode = childNode.Next; int numWeights = ConvertInt32(childNode.Value); childNode = childNode.Next; int[] vertIndices = new int[numWeights]; for (int i = 0; i < numWeights; i++) { vertIndices[i] = ConvertInt32(childNode.Value); childNode = childNode.Next; } float[] weights = new float[numWeights]; for (int i = 0; i < numWeights; i++) { weights[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } byte boneIdx; if (!boneDic.TryGetValue(boneName, out boneIdx)) { boneIdx = (byte)boneDic.Count; boneDic.Add(boneName, boneIdx); ImportedBone boneInfo = new ImportedBone(); meshList.BoneList.Add(boneInfo); boneInfo.Name = boneName; Matrix matrix = new Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrix[i, j] = ConvertFloat(childNode.Value); childNode = childNode.Next; } } boneInfo.Matrix = RHToLHMatrix(matrix); } for (int i = 0; i < numWeights; i++) { boneAssignments[vertIndices[i]].Add(new KeyValuePair<byte, float>(boneIdx, weights[i])); } } else { Report.ReportLog("Warning: unexpected section " + child.type); } } if (hasBones) { for (int i = 0; i < boneAssignments.Length; i++) { byte[] boneIndices = new byte[4]; float[] weights4 = new float[4]; for (int j = 0; (j < 4) && (j < boneAssignments[i].Count); j++) { boneIndices[j] = boneAssignments[i][j].Key; weights4[j] = boneAssignments[i][j].Value; } for (int j = boneAssignments[i].Count; j < 4; j++) { boneIndices[j] = 0xFF; weights4[j] = 0; } vertices[i].boneIndices = boneIndices; vertices[i].weights = new float[] { weights4[0], weights4[1], weights4[2], weights4[3] }; } } SortedDictionary<ushort, ushort>[] vertexMaps = new SortedDictionary<ushort, ushort>[materials.Length]; ImportedSubmesh[] submeshes = new ImportedSubmesh[materials.Length]; for (int i = 0; i < materials.Length; i++) { submeshes[i] = new ImportedSubmesh(); submeshes[i].Material = materials[i]; submeshes[i].VertexList = new List<ImportedVertex>(vertices.Length); submeshes[i].FaceList = new List<ImportedFace>(faces.Length); vertexMaps[i] = new SortedDictionary<ushort, ushort>(); } foreach (DXFace dxFace in faces) { ImportedSubmesh submesh = submeshes[dxFace.materialIndex]; ImportedFace face = new ImportedFace(); submesh.FaceList.Add(face); ushort[] foundVertexIndices = new ushort[3]; for (int i = 0; i < dxFace.vertexIndices.Length; i++) { ushort dxVertIdx = dxFace.vertexIndices[i]; SortedDictionary<ushort, ushort> vertexMap = vertexMaps[dxFace.materialIndex]; if (!vertexMap.TryGetValue(dxVertIdx, out foundVertexIndices[i])) { DXVertex dxVert = vertices[dxVertIdx]; ImportedVertex vert = new ImportedVertex(); submesh.VertexList.Add(vert); if (hasNormals) { vert.Normal = new Vector3(dxVert.normal[0], dxVert.normal[1], dxVert.normal[2]); } if (hasUVs) { vert.UV = (float[])dxVert.uv.Clone(); } if (hasBones) { vert.BoneIndices = (byte[])dxVert.boneIndices.Clone(); vert.Weights = (float[])dxVert.weights.Clone(); } vert.Position = new Vector3(dxVert.position[0], dxVert.position[1], dxVert.position[2]); vertIdxOffset++; foundVertexIndices[i] = (ushort)vertexMap.Count; vertexMap.Add(dxVertIdx, foundVertexIndices[i]); } } face.VertexIndices = new int[] { foundVertexIndices[0], foundVertexIndices[1], foundVertexIndices[2] }; } foreach (ImportedSubmesh submesh in submeshes) { if (submesh.VertexList.Count > 0) { submesh.VertexList.TrimExcess(); submesh.FaceList.TrimExcess(); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); hasBonesList.Add(hasBones); if (!hasNormals) { for (int i = 0; i < submesh.VertexList.Count; i++) { submesh.VertexList[i].Normal = new Vector3(); } } } } }
private void Export(DirectoryInfo dir) { try { odfMorphSection morphSection = parser.MorphSection; ushort[] meshIndices = morphObj.MeshIndices; odfSubmesh meshObjBase = odf.FindMeshObject(morphObj.SubmeshId, parser.MeshSection); colorVertex = new bool[meshObjBase.VertexList.Count]; for (int i = 0; i < meshIndices.Length; i++) { colorVertex[meshIndices[i]] = true; } vertLists = new List <List <ImportedVertex> >(morphObj.Count); for (int i = 0; i < morphObj.Count; i++) { if (skipUnusedProfiles) { bool skip = true; for (int j = 0; j < morphObj.SelectorList.Count; j++) { if (morphObj.SelectorList[j].ProfileIndex == i) { skip = false; break; } } if (skip) { continue; } } List <ImportedVertex> vertList = odf.ImportedVertexListUnskinned(meshObjBase.VertexList); vertLists.Add(vertList); for (int j = 0; j < meshIndices.Length; j++) { ImportedVertex vert = vertList[meshIndices[j]]; vert.Position = morphObj[i].VertexList[j].Position; } } faceList = odf.ImportedFaceList(meshObjBase.FaceList); string dest = Utility.GetDestFile(dir, meshObjBase.Parent.Name + "-" + morphObj.Name + "-", ".morph.mqo"); odfMaterial mat = odf.FindMaterialInfo(meshObjBase.MaterialId, parser.MaterialSection); Export(dest, mat, odf.FindTextureInfo(meshObjBase.TextureIds[0], parser.TextureSection)); foreach (odfTexture tex in usedTextures) { String texFilePath = Path.GetDirectoryName(parser.ODFPath) + @"\" + tex.TextureFile; try { odfTextureFile odfTex = new odfTextureFile(tex.Name, texFilePath); odf.ExportTexture(odfTex, dir.FullName + @"\" + tex.TextureFile); } catch (Exception ex) { Utility.ReportException(ex); } } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }