/// <summary> /// Parses the complete Mesh Section /// </summary> /// <param name="grps"></param> /// <param name="ct"></param> void ParseBonesSection(ImportedGroups grps, int ct) { SimPe.IntArrayList sort = Gmdc.SortJoints(); for (int i = 0; i < ct; i++) { ImportedBone b = new ImportedBone(Gmdc); b.TargetIndex = sort[i]; b.Action = GmdcImporterAction.Replace; //Read the Bones Data ReadJointDescription(b); ReadJointData(b); int poscount = ReadCount(); for (int k = 0; k < poscount; k++) { ReadJointPosPhase(b, k, poscount); } int rotcount = ReadCount(); for (int k = 0; k < rotcount; k++) { ReadJointRotPhase(b, k, rotcount); } bones.Add(b); } }
void ReadJointRotPhase(ImportedBone b, int index, int count) { string[] linetoks = GetNonEmptyTokens(); if (linetoks.Length < 4) { lineerror = "Unable to read JointRotation Line."; return; } try { float t = Convert.ToSingle(linetoks[0], AbstractGmdcImporter.DefaultCulture); bool isscaled = (t == -1); t = Math.Max(0, t - 1); Vector3f rot = new Vector3f( ToDouble(linetoks[1]), ToDouble(linetoks[2]), ToDouble(linetoks[3]) ); Quaternion q = Quaternion.FromEulerAngles(rot); rot = q.Axis; rot = Component.InverseTransform(rot); q = Quaternion.FromAxisAngle(rot, q.Angle); rot = q.GetEulerAngles(); if (currotblock != null) { //Brand this Block as Rotation (ignoring all Translation!) if (currotblock.TransformationType == FrameType.Unknown) { currotblock.TransformationType = FrameType.Rotation; } //only process if the Block Type is Rotation if (currotblock.TransformationType == FrameType.Rotation) { if (isscaled && index == 0) { for (int i = 0; i < currotblock.AxisCount; i++) { currotblock.AxisSet[i].Locked = true; } } currotblock.AddFrame((short)t, rot, false); } } } catch { lineerror = "Unable to Convert to Number (ReadJointRotPhase)"; } }
void ReadJointData(ImportedBone b) { string[] linetoks = GetNonEmptyTokens(); if (linetoks.Length < 7) { lineerror = "Unable to read Joint Line."; return; } try { Vector3f trans = new Vector3f( ToDouble(linetoks[1]), ToDouble(linetoks[2]), ToDouble(linetoks[3]) ); trans = Component.InverseTransformScaled(trans); Vector3f rot = new Vector3f( ToDouble(linetoks[4]), ToDouble(linetoks[5]), ToDouble(linetoks[6]) ); Quaternion q = Quaternion.FromEulerAngles(rot); rot = Component.InverseTransform(q.Axis); //Quaternion from Euler Angles b.Transformation.Translation = trans; b.Transformation.Rotation = SimPe.Geometry.Quaternion.FromAxisAngle(rot, q.Angle); } catch { lineerror = "Unable to Convert to Number(ReadJointData)"; } }
void ReadJointDescription(ImportedBone b) { string[] linetoks = GetNonEmptyTokens(); if (linetoks.Length < 1) { lineerror = "Unable to read Joint Description."; return; } linetoks[0] = linetoks[0].Replace("\"", ""); b.ImportedName = linetoks[0]; linetoks = GetNonEmptyTokens(); if (linetoks.Length < 1) { lineerror = "Unable to read Joint Description."; return; } linetoks[0] = linetoks[0].Replace("\"", ""); b.ParentName = linetoks[0]; //Animations if (this.AnimationBlocks != null && Gmdc.LinkedAnimation != null) { curtransblock = null; currotblock = null; ImportedFrameBlock ifb = new ImportedFrameBlock(new AnimationFrameBlock(Gmdc.LinkedAnimation)); ifb.FrameBlock.Name = b.ImportedName; ifb.FindTarget(Gmdc.LinkedAnimation); if (ifb.Target != null) { ifb.FrameBlock.TransformationType = ifb.Target.TransformationType; if (ifb.FrameBlock.TransformationType == FrameType.Translation) { curtransblock = ifb.FrameBlock; } else { currotblock = ifb.FrameBlock; } } else { ifb.FrameBlock.TransformationType = FrameType.Rotation; if (b.ImportedName.EndsWith("_rot")) { ifb.FrameBlock.TransformationType = FrameType.Rotation; currotblock = ifb.FrameBlock; } else if (b.ImportedName.EndsWith("_trans")) { ifb.FrameBlock.TransformationType = FrameType.Translation; curtransblock = ifb.FrameBlock; } else { currotblock = ifb.FrameBlock; ifb.FrameBlock.CreateBaseAxisSet(AnimationTokenType.SixByte); this.AnimationBlocks.Add(ifb); ifb = new ImportedFrameBlock(new AnimationFrameBlock(Gmdc.LinkedAnimation)); ifb.FrameBlock.TransformationType = FrameType.Translation; ifb.FrameBlock.Name = b.ImportedName; curtransblock = ifb.FrameBlock; } } ifb.FrameBlock.CreateBaseAxisSet(AnimationTokenType.SixByte); this.AnimationBlocks.Add(ifb); } //if (curanimblock==null) curanimblock = new SimPe.Plugin.AnimBlock2(); }
private ImportedFrame ImportNode(Document.Node node) { ImportedFrame frame = new ImportedFrame(); try { frame.Name = DecodeName(node.id); frame.Matrix = ProcessNodeMatrix(node); ImportedMesh meshList = new ImportedMesh(); meshList.Name = frame.Name; meshList.SubmeshList = new List<ImportedSubmesh>(); List<string> boneNames = new List<string>(255); List<Matrix> boneMatrices = new List<Matrix>(255); List<Document.InstanceGeometry> geometries = new List<Document.InstanceGeometry>(); List<Document.InstanceController> controllers = new List<Document.InstanceController>(); List<Document.InstanceNode> instanceNodes; ProcessNodeInstances(node, geometries, controllers, out instanceNodes); for (int i = 0; i < instanceNodes.Count; i++) { List<Document.InstanceNode> dummy; Document.Node instanceNode = (Document.Node)colladaDoc.dic[instanceNodes[i].url.Fragment]; if (ProcessNodeInstances(instanceNode, geometries, controllers, out dummy)) { ImportedFrame child = ImportNode(instanceNode); if (child != null) { frame.AddChild(child); } } for (int j = 0; j < dummy.Count; j++) { Report.ReportLog("Warning: instance node " + dummy[j].name + " wasn't processed"); } } if (node.children != null) { for (int i = 0; i < node.children.Count; i++) { List<Document.InstanceNode> dummy; if (ProcessNodeInstances(node.children[i], geometries, controllers, out dummy)) { ImportedFrame child = ImportNode(node.children[i]); if (child != null) { frame.AddChild(child); } } for (int j = 0; j < dummy.Count; j++) { Report.ReportLog("Warning: instance node " + dummy[j].name + " wasn't processed"); } } } int vertInfoIdx = 0; for (int i = 0; i < controllers.Count; i++) { ImportedSubmesh submesh = ImportController((Document.Controller)colladaDoc.dic[controllers[i].url.Fragment], boneNames, boneMatrices, ref vertInfoIdx); if (submesh != null) { SetMaterial(controllers[i], submesh); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); } } for (int i = 0; i < geometries.Count; i++) { ImportedSubmesh submesh = ImportGeometry((Document.Geometry)colladaDoc.dic[geometries[i].url.Fragment], ref vertInfoIdx); if (submesh != null) { SetMaterial(geometries[i], submesh); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); foreach (ImportedVertex vert in submesh.VertexList) { if (boneNames.Count > 0) { vert.BoneIndices = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; vert.Weights = new float[] { 1, 0, 0, 0 }; } else { vert.BoneIndices = new byte[4]; vert.Weights = new float[4]; } } } } if (meshList.SubmeshList.Count > 0) { meshList.BoneList = new List<ImportedBone>(boneNames.Count); for (int i = 0; i < boneNames.Count; i++) { string name = boneNames[i]; ImportedBone bone = new ImportedBone(); bone.Name = DecodeName(name); bone.Matrix = boneMatrices[i]; meshList.BoneList.Add(bone); } MeshList.Add(meshList); } } catch (Exception e) { Report.ReportLog("Error importing node " + node.id + ": " + e.Message); frame = null; } return frame; }
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 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); } }
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); } }
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]; } } } } }