public void CopyBone(int boneListIdx, int boneIdx) { odfBoneList boneList = Parser.EnvelopeSection[boneListIdx]; odfBone bone = boneList[boneIdx]; boneList.AddChild(bone.Clone()); }
private float[][] ConvertVertexWeights(List <odfVertex> vertexList, odfBoneList boneList) { int numBones = boneList != null ? boneList.Count : 0; float[][] vertexWeights = new float[vertexList.Count][]; for (int j = 0; j < vertexList.Count; j++) { vertexWeights[j] = new float[4]; int weightIdx = 0; for (int k = 0; k < numBones; k++) { odfBone bone = boneList[k]; for (int l = 0; l < bone.NumberIndices; l++) { if (bone.VertexIndexArray[l] == j) { vertexList[j].BoneIndices[weightIdx] = (byte)k; if (weightIdx < 3) { vertexWeights[j][weightIdx++] = bone.WeightArray[l]; } else { vertexWeights[j][3] = 1f - vertexWeights[j][0] - vertexWeights[j][1] - vertexWeights[j][2]; } break; } } } } return(vertexWeights); }
public static void RemoveSubmesh(odfParser parser, odfSubmesh submesh, bool deleteMorphs) { odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { parser.EnvelopeSection.RemoveChild(boneList); parser.UsedIDs.Remove((int)boneList.Id); } if (parser.MorphSection != null && deleteMorphs) { for (int i = 0; i < parser.MorphSection.Count; i++) { odfMorphObject morphObj = parser.MorphSection[i]; if (morphObj.SubmeshId == submesh.Id) { parser.MorphSection.RemoveChild(i); --i; } } } ((odfMesh)submesh.Parent).RemoveChild(submesh); }
public static odfBoneList ParseBoneList(BinaryReader reader, int formatType) { ObjectName name = new ObjectName(reader.ReadBytes(64)); ObjectID id = new ObjectID(reader.ReadBytes(4)); ObjectID frameId = new ObjectID(reader.ReadBytes(4)); ObjectID meshObjId = new ObjectID(reader.ReadBytes(4)); int numBones = reader.ReadInt32(); odfBoneList boneList = new odfBoneList(name, id, numBones); boneList.MeshFrameId = frameId; boneList.SubmeshId = meshObjId; if (formatType >= 10) { boneList.AlwaysZero4 = reader.ReadBytes(4); } for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { id = new ObjectID(reader.ReadBytes(4)); odfBone bone = new odfBone(id); int numberIndices = reader.ReadInt32(); bone.AlwaysZero24perIndex = reader.ReadBytes(24 * numberIndices); bone.VertexIndexArray = reader.ReadInt32Array(numberIndices); bone.WeightArray = reader.ReadSingleArray(numberIndices); bone.Matrix = reader.ReadMatrix(); boneList.AddChild(bone); } return(boneList); }
public void HighlightBone(odfParser parser, int meshIdx, int submeshIdx, int boneIdx) { const int boneObjSize = 16; odfSubmesh submesh = parser.MeshSection[meshIdx][submeshIdx]; odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); string boneFrameName = null; if (boneIdx >= 0) { odfBone bone = boneList[boneIdx]; boneFrameName = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; } AnimationMeshContainer mesh = (AnimationMeshContainer)meshFrames[0].MeshContainer; for (int i = 0; mesh != null; i++) { if (i == submeshIdx && (mesh.MeshData != null) && (mesh.MeshData.Mesh != null)) { List <odfVertex> vertexList = submesh.VertexList; float[][] vertexWeights = ConvertVertexWeights(vertexList, boneList); FillVertexBuffer(mesh.MeshData.Mesh, vertexList, vertexWeights, boneIdx); // break; } if (boneIdx >= 0) { for (int idx = 0; idx < mesh.BoneLines.Length / boneObjSize; idx++) { if (mesh.BoneNames[idx] == boneFrameName) { for (int j = 0; j < boneObjSize; j++) { mesh.BoneLines[idx * boneObjSize + j].Color = Color.Crimson.ToArgb(); } break; } } } else { for (int idx = 0; idx < mesh.BoneLines.Length / boneObjSize; idx++) { for (int j = 0; j < boneObjSize; j++) { mesh.BoneLines[idx * boneObjSize + j].Color = Color.CornflowerBlue.ToArgb(); } } } mesh = (AnimationMeshContainer)mesh.NextMeshContainer; } }
public void MergeFrame(odfFrame srcFrame, odfParser srcParser, int destParentIdx) { List <ObjectID> newMeshIDs = new List <ObjectID>(); odfFrame newFrame = srcFrame.Clone(true, newMeshIDs, true); List <odfMesh> newMeshes = new List <odfMesh>(newMeshIDs.Count); List <odfBoneList> newBoneLists = new List <odfBoneList>(srcParser.EnvelopeSection != null ? srcParser.EnvelopeSection.Count : 0); string boneWarning = String.Empty; foreach (ObjectID meshID in newMeshIDs) { odfMesh srcMesh = odf.FindMeshListSome(meshID, srcParser.MeshSection); odfMesh mesh = srcMesh.Clone(); newMeshes.Add(mesh); if (srcParser.EnvelopeSection != null) { foreach (odfSubmesh submesh in mesh) { odfBoneList boneList = odf.FindBoneList(submesh.Id, srcParser.EnvelopeSection); if (boneList != null) { if (Parser.EnvelopeSection != null) { odfBoneList copy = boneList.Clone(); newBoneLists.Add(copy); } else { boneWarning += (boneWarning != String.Empty ? ", " : "") + mesh.ToString(); break; } } } } } MergeFrame(newFrame, destParentIdx); foreach (odfMesh mesh in newMeshes) { Parser.MeshSection.AddChild(mesh); } if (Parser.EnvelopeSection != null) { foreach (odfBoneList boneList in newBoneLists) { Parser.EnvelopeSection.AddChild(boneList); } } Parser.CollectObjectIDs(); if (boneWarning != String.Empty) { Report.ReportLog("Warning! Bones of " + boneWarning + " dropped because the destination had no Envelope section."); } }
public bool RemoveBone(int boneListIdx, int boneIdx) { odfBoneList boneList = Parser.EnvelopeSection[boneListIdx]; if (boneList.Count == 1) { Parser.EnvelopeSection.RemoveChild(boneList); return(true); } else { boneList.RemoveChild(boneIdx); return(false); } }
public static void MergeBoneLists(odfMesh mesh, Dictionary <ObjectID, ObjectID> submeshIDtrans, odfParser parser) { foreach (odfSubmesh submesh in mesh) { ObjectID baseSubmeshId = submeshIDtrans[submesh.Id]; for (int i = 0; i < parser.EnvelopeSection.Count; i++) { odfBoneList boneList = parser.EnvelopeSection[i]; if (boneList.SubmeshId == baseSubmeshId) { Dictionary <int, int> boneDic = new Dictionary <int, int>(boneList.Count); for (int j = 0; j < boneList.Count; j++) { odfBone bone = boneList[j]; boneDic.Add((int)bone.FrameId, j); } for (int j = i + 1; j < parser.EnvelopeSection.Count; j++) { odfBoneList boneList2 = parser.EnvelopeSection[j]; if (boneList2.SubmeshId == submesh.Id) { foreach (odfBone bone in boneList2) { int boneIdx; if (boneDic.TryGetValue((int)bone.FrameId, out boneIdx)) { boneList.RemoveChild(boneIdx); boneList.InsertChild(boneIdx, bone); } else { boneList.AddChild(bone); boneDic.Add((int)bone.FrameId, boneDic.Count); } } parser.EnvelopeSection.RemoveChild(boneList2); } } break; } else { Report.ReportLog("wrong"); } } } }
public odfBoneList Clone() { odfBoneList boneList = new odfBoneList(Name, Id, Count); boneList.MeshFrameId = new ObjectID(MeshFrameId); boneList.SubmeshId = new ObjectID(SubmeshId); if (AlwaysZero4 != null) { boneList.AlwaysZero4 = (byte[])AlwaysZero4.Clone(); } foreach (odfBone bone in this) { odfBone newBone = bone.Clone(); boneList.AddChild(newBone); } return(boneList); }
private new void listViewAnimationTrack_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { List <DockContent> formODFList; if (!Gui.Docking.DockContents.TryGetValue(typeof(FormMeshView), out formODFList)) { return; } foreach (FormMeshView formMesh in formODFList) { odfFrame boneFrame = odf.FindFrame(e.Item.Text, formMesh.Editor.Parser.FrameSection.RootFrame); if (boneFrame == null) { continue; } for (int i = 0; i < formMesh.renderObjectMeshes.Count; i++) { RenderObjectODF mesh = formMesh.renderObjectMeshes[i]; if (mesh != null && formMesh.renderObjectIds[i] > -1) { odfMesh odfMesh = formMesh.Editor.Parser.MeshSection[i]; for (int j = 0; j < odfMesh.Count; j++) { odfSubmesh submesh = odfMesh[j]; odfBoneList bones = odf.FindBoneList(submesh.Id, formMesh.Editor.Parser.EnvelopeSection); if (bones == null) { continue; } for (int k = 0; k < bones.Count; k++) { if (bones[k].FrameId == boneFrame.Id) { mesh.HighlightBone(formMesh.Editor.Parser, i, j, e.IsSelected ? k : -1); Gui.Renderer.Render(); break; } } } } } } }
public static HashSet <int> SearchHierarchy(odfParser parser, HashSet <int> meshIDs) { HashSet <int> exportFrames = new HashSet <int>(); SearchHierarchy(parser.FrameSection.RootFrame, parser.FrameSection.RootFrame, meshIDs, exportFrames); if (parser.EnvelopeSection != null) { for (int meshIdx = 0; meshIdx < parser.MeshSection.Count; meshIdx++) { odfMesh mesh = parser.MeshSection[meshIdx]; if (!meshIDs.Contains((int)mesh.Id)) { continue; } for (int meshObjIdx = 0; meshObjIdx < mesh.Count; meshObjIdx++) { odfSubmesh meshObj = mesh[meshObjIdx]; for (int envIdx = 0; envIdx < parser.EnvelopeSection.Count; envIdx++) { odfBoneList boneList = parser.EnvelopeSection[envIdx]; if (meshObj.Id != boneList.SubmeshId) { continue; } for (int i = 0; i < boneList.Count; i++) { ObjectID boneID = boneList[i].FrameId; if (!exportFrames.Contains((int)boneID)) { odfFrame boneParent = FindFrame(boneID, parser.FrameSection.RootFrame); while (boneParent != null && exportFrames.Add((int)boneParent.Id)) { boneParent = boneParent.Parent as odfFrame; } } } } } } } return(exportFrames); }
private bool loadENVL(BinaryReader reader, odfFileSection fileSec) { ObjectID id = new ObjectID(reader.ReadBytes(4)); byte[] alwaysZero = reader.ReadBytes(64); int numEnvelopes = reader.ReadInt32(); odfEnvelopeSection envSection = new odfEnvelopeSection(numEnvelopes); envSection.Id = id; envSection.AlwaysZero64 = alwaysZero; envSection._FormatType = MeshSection != null ? MeshSection._FormatType : -1; for (int envIdx = 0; envIdx < numEnvelopes; envIdx++) { odfBoneList boneList = ParseBoneList(reader, envSection._FormatType); envSection.AddChild(boneList); } fileSec.Section = envSection; EnvelopeSection = envSection; return(true); }
public void ReplaceFrame(odfFrame srcFrame, odfParser srcParser, int destParentIdx, bool deleteMorphs) { List <ObjectID> meshIDs = new List <ObjectID>(); odfFrame newFrame = srcFrame.Clone(true, meshIDs, true); ReplaceFrame(newFrame, destParentIdx, deleteMorphs); string boneWarning = String.Empty; foreach (ObjectID meshID in meshIDs) { odfMesh srcMesh = odf.FindMeshListSome(meshID, srcParser.MeshSection); odfMesh mesh = srcMesh.Clone(); Parser.MeshSection.AddChild(mesh); if (srcParser.EnvelopeSection != null) { foreach (odfSubmesh submesh in mesh) { odfBoneList boneList = odf.FindBoneList(submesh.Id, srcParser.EnvelopeSection); if (boneList != null) { if (Parser.EnvelopeSection != null) { odfBoneList copy = boneList.Clone(); Parser.EnvelopeSection.AddChild(copy); } else { boneWarning += (boneWarning != String.Empty ? ", " : "") + mesh.ToString(); break; } } } } } Parser.CollectObjectIDs(); if (boneWarning != String.Empty) { Report.ReportLog("Warning! Bones of " + boneWarning + " dropped because the destination had no Envelope section."); } }
void DeleteReferringBones(odfFrame frame) { for (int i = 0; i < Parser.EnvelopeSection.Count; i++) { odfBoneList boneList = Parser.EnvelopeSection[i]; for (int j = 0; j < boneList.Count; j++) { odfBone bone = boneList[j]; if (bone.FrameId == frame.Id) { if (RemoveBone(Parser.EnvelopeSection.IndexOf(boneList), j)) { i--; } break; } } } foreach (odfFrame child in frame) { DeleteReferringBones(child); } }
public static odfBoneList CreateBoneList(ObjectID id, ObjectID meshFrameId, odfSubmesh submesh, List <ImportedBone> boneList, Matrix lMeshMatrixInv, odfFrame rootFrame) { if (boneList == null || boneList.Count == 0) { return(null); } Dictionary <byte, Tuple <byte, odfBone> > boneDic = new Dictionary <byte, Tuple <byte, odfBone> >(boneList.Count); Tuple <List <int>, List <float> >[] newBoneListComponents = new Tuple <List <int>, List <float> > [boneList.Count]; int boneframeNotFound = 0; for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { byte boneIdx = vert.BoneIndices[j]; if (boneIdx == 0xFF) { continue; } Tuple <byte, odfBone> boneDesc; odfBone newBone; if (!boneDic.TryGetValue(boneIdx, out boneDesc)) { odfFrame boneFrame = odf.FindFrame(boneList[boneIdx].Name, rootFrame); if (boneFrame == null) { boneframeNotFound++; continue; } newBone = new odfBone(boneFrame.Id); newBone.Matrix = boneList[boneIdx].Matrix; boneDesc = new Tuple <byte, odfBone>((byte)boneDic.Count, newBone); boneDic.Add(boneIdx, boneDesc); newBoneListComponents[boneDesc.Item1] = new Tuple <List <int>, List <float> >(new List <int>(200), new List <float>(200)); } else { newBone = boneDesc.Item2; } byte newBoneIdx = boneDesc.Item1; List <int> newBoneIdxList = newBoneListComponents[newBoneIdx].Item1; newBoneIdxList.Add(i); List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2; newBoneWeightList.Add(vert.Weights[j]); } } if (boneDic.Count == 0) { Report.ReportLog(submesh.ToString() + ": all bones dropped because of missing skeleton."); return(null); } odfBoneList newBoneList = new odfBoneList(new ObjectName(String.Empty, null), id, boneDic.Count); newBoneList.MeshFrameId = meshFrameId; newBoneList.SubmeshId = submesh.Id; newBoneList.AlwaysZero4 = new byte[4]; foreach (Tuple <byte, odfBone> boneDesc in boneDic.Values) { byte newBoneIdx = boneDesc.Item1; List <int> newBoneIdxList = newBoneListComponents[newBoneIdx].Item1; List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2; odfBone newBone = boneDesc.Item2; newBone.AlwaysZero24perIndex = new byte[24 * newBoneIdxList.Count]; newBone.VertexIndexArray = newBoneIdxList.ToArray(); newBone.WeightArray = newBoneWeightList.ToArray(); Matrix lMatrix = Matrix.Invert(newBone.Matrix); newBone.Matrix = Matrix.Invert(lMatrix * lMeshMatrixInv); newBoneList.AddChild(newBone); } if (boneframeNotFound > 0) { Report.ReportLog(submesh.ToString() + ": " + boneframeNotFound + " bone(s) because of missing boneframe(s) dropped."); } return(newBoneList); }
private AnimationFrame CreateFrame(odfFrame frame, odfParser parser, HashSet <int> extractFrames, HashSet <int> meshIDs, Device device, Matrix combinedParent, List <AnimationFrame> meshFrames) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.Name; animationFrame.TransformationMatrix = frame.Matrix; animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix; if ((int)frame.MeshId != 0 && meshIDs.Contains((int)frame.MeshId)) { odfMesh mesh = odf.FindMeshListSome(frame.MeshId, parser.MeshSection); ExtendedMaterial[] materials = new ExtendedMaterial[mesh.Count]; AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < mesh.Count; i++) { odfSubmesh submesh = mesh[i]; List <odfFace> faceList = submesh.FaceList; List <odfVertex> vertexList = submesh.VertexList; odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); bool skinned = boneList != null; int numBones = skinned ? boneList.Count : 0; string[] boneNames = new string[numBones]; Matrix[] boneOffsets = new Matrix[numBones]; for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { odfBone bone = boneList[boneIdx]; boneNames[boneIdx] = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; Matrix mirrored; if (!BoneMatrixDic.TryGetValue(boneNames[boneIdx], out mirrored)) { #if !DONT_MIRROR Vector3 translate, scale; Quaternion rotate; bone.Matrix.Decompose(out scale, out rotate, out translate); mirrored = Matrix.Scaling(scale.X, scale.Y, -scale.Z) * Matrix.RotationQuaternion(rotate) * Matrix.Translation(translate); #else mirrored = bone.Matrix; #endif BoneMatrixDic.Add(boneNames[boneIdx], mirrored); } boneOffsets[boneIdx] = mirrored; } Mesh animationMesh = new Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format); using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None)) { for (int j = 0; j < faceList.Count; j++) { ushort[] indices = faceList[j].VertexIndices; indexStream.Write(indices[0]); indexStream.Write(indices[1]); indexStream.Write(indices[2]); } animationMesh.UnlockIndexBuffer(); } float[][] vertexWeights = ConvertVertexWeights(vertexList, boneList); FillVertexBuffer(animationMesh, vertexList, vertexWeights, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { odfVertex vertex = vertexList[j]; #if !DONT_MIRROR Vector3 position = new Vector3(vertex.Position.X, vertex.Position.Y, -vertex.Position.Z); Vector3 normal = new Vector3(vertex.Normal.X, vertex.Normal.Y, -vertex.Normal.Z); #else Vector3 position = vertex.Position; Vector3 normal = vertex.Normal; #endif float[] boneWeights = vertexWeights[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(position, boneWeights, vertex.BoneIndices, Color.Yellow.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + (normal / 11), boneWeights, vertex.BoneIndices, Color.Blue.ToArgb()); min = Vector3.Minimize(min, position); max = Vector3.Maximize(max, position); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; meshContainer.BoneNames = boneNames; meshContainer.BoneOffsets = boneOffsets; meshContainers[i] = meshContainer; odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { Material material3D = new Material(); material3D.Ambient = mat.Ambient; material3D.Diffuse = mat.Diffuse; material3D.Emissive = mat.Emissive; material3D.Specular = mat.Specular; material3D.Power = mat.SpecularPower; int matIdx = parser.MaterialSection.IndexOf(mat); Materials[matIdx] = material3D; meshContainer.MaterialIndex = matIdx; int texIdx = -1; if ((int)submesh.TextureIds[0] != 0 && !TextureDic.TryGetValue((int)submesh.TextureIds[0], out texIdx)) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[0], parser.TextureSection); if (tex != null) { try { odfTextureFile texFile = new odfTextureFile(null, Path.GetDirectoryName(parser.ODFPath) + Path.DirectorySeparatorChar + tex.TextureFile); int fileSize = 0; ImportedTexture impTex = new ImportedTexture(texFile.DecryptFile(ref fileSize).BaseStream, tex.TextureFile); Texture memTex = impTex.ToTexture(device); texIdx = TextureDic.Count; TextureDic.Add((int)submesh.TextureIds[0], texIdx); Textures[texIdx] = memTex; } catch (SlimDXException ex) { Utility.ReportException(ex); Report.ReportLog("Please check " + tex.TextureFile + ". It may have an unsupported format."); } catch (Exception ex) { Utility.ReportException(ex); } } } meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } for (int i = 0; i < frame.Count; i++) { odfFrame child = frame[i]; if (extractFrames.Contains((int)child.Id)) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, meshIDs, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return(animationFrame); }
public static void ReplaceMesh(odfFrame frame, odfParser parser, WorkspaceMesh mesh, List <ImportedMaterial> materials, List <ImportedTexture> textures, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod) { Matrix transform = Matrix.Identity; odfFrame transformFrame = frame; while (transformFrame != null) { transform *= transformFrame.Matrix; transformFrame = transformFrame.Parent as odfFrame; } transform.Invert(); string[] materialNames; int[] indices; bool[] worldCoords; bool[] replaceSubmeshesOption; odfMesh newMesh = CreateMesh(mesh, parser.MeshSection._FormatType, out materialNames, out indices, out worldCoords, out replaceSubmeshesOption); odfMesh frameMesh = odf.FindMeshListSome(frame.MeshId, parser.MeshSection); if (frameMesh != null) { if (parser.UsedIDs == null) // prevent misleading error message { parser.CollectObjectIDs(); } newMesh.Id = frameMesh.Id; newMesh.Name = frameMesh.Name; parser.MeshSection.InsertChild(parser.MeshSection.IndexOf(frameMesh), newMesh); } else { newMesh.Id = parser.GetNewID(typeof(odfMesh)); frame.MeshId = newMesh.Id; parser.MeshSection.AddChild(newMesh); } Dictionary <ObjectID, ObjectID> submeshIDtranslation = new Dictionary <ObjectID, ObjectID>(newMesh.Count); odfSubmesh[] replaceSubmeshes = frameMesh != null ? new odfSubmesh[frameMesh.Count] : null; List <odfSubmesh> addSubmeshes = new List <odfSubmesh>(newMesh.Count); for (int i = 0; i < newMesh.Count; i++) { ObjectID[] texIDs = new ObjectID[4] { ObjectID.INVALID, ObjectID.INVALID, ObjectID.INVALID, ObjectID.INVALID }; odfMaterial mat = odf.FindMaterialInfo(materialNames[i], parser.MaterialSection); if (materials != null && mat == null) { ImportedMaterial impMat = ImportedHelpers.FindMaterial(materialNames[i], materials); if (impMat != null) { mat = CreateMaterial(impMat, parser.GetNewID(typeof(odfMaterial))); parser.MaterialSection.AddChild(mat); for (int j = 0; j < impMat.Textures.Length; j++) { string texName = impMat.Textures[j]; odfTexture tex = odf.FindTextureInfo(texName, parser.TextureSection); if (tex == null) { ImportedTexture impTex = ImportedHelpers.FindTexture(texName, textures); if (impTex != null) { tex = CreateTexture(impTex, parser.GetNewID(typeof(odfTexture)), parser.TextureSection._FormatType, Path.GetDirectoryName(parser.ODFPath)); parser.TextureSection.AddChild(tex); texIDs[j] = tex.Id; } } else { texIDs[j] = tex.Id; } } } } odfSubmesh newSubmesh = newMesh[i]; newSubmesh.Id = parser.GetNewID(typeof(odfSubmesh)); newSubmesh.MaterialId = mat != null ? mat.Id : ObjectID.INVALID; newSubmesh.TextureIds = texIDs; List <odfVertex> newVertexList = newSubmesh.VertexList; if (worldCoords[i]) { for (int j = 0; j < newVertexList.Count; j++) { newVertexList[j].Position = Vector3.TransformCoordinate(newVertexList[j].Position, transform); } } odfSubmesh baseSubmesh = null; odfBoneList newBones = null; int newBonesIdx = -1; int idx = indices[i]; if ((frameMesh != null) && (idx >= 0) && (idx < frameMesh.Count)) { baseSubmesh = frameMesh[idx]; submeshIDtranslation.Add(newSubmesh.Id, baseSubmesh.Id); for (int j = 0; j < baseSubmesh.TextureIds.Length; j++) { ObjectID texID = baseSubmesh.TextureIds[j]; newSubmesh.TextureIds[j] = texID; } newSubmesh.Name = new ObjectName(baseSubmesh.Name.Name, baseSubmesh.Name.Info); CopyUnknowns(baseSubmesh, newSubmesh, parser.MeshSection._FormatType); if ((bonesMethod == CopyMeshMethod.CopyOrder) || (bonesMethod == CopyMeshMethod.CopyNear)) { odfBoneList baseBones = odf.FindBoneList(baseSubmesh.Id, parser.EnvelopeSection); if (baseBones != null) { newBones = baseBones.Clone(); newBones.Id = ObjectID.INVALID; // parser.GetNewID(typeof(odfBoneList)); newBones.SubmeshId = newSubmesh.Id; newBonesIdx = parser.EnvelopeSection.IndexOf(baseBones); } } else if (bonesMethod == CopyMeshMethod.Replace) { newBones = CreateBoneList(ObjectID.INVALID /*parser.GetNewID(typeof(odfBoneList))*/, frame.Id, newSubmesh, mesh.BoneList, transform, parser.FrameSection.RootFrame); newBonesIdx = parser.EnvelopeSection.Count; } } else { CreateUnknowns(newSubmesh, parser.MeshSection._FormatType); newBones = CreateBoneList(ObjectID.INVALID /*parser.GetNewID(typeof(odfBoneList))*/, frame.Id, newSubmesh, mesh.BoneList, transform, parser.FrameSection.RootFrame); newBonesIdx = parser.EnvelopeSection.Count; } if (newBones != null) { parser.EnvelopeSection.InsertChild(newBonesIdx, newBones); } if (baseSubmesh != null) { if (normalsMethod == CopyMeshMethod.CopyOrder) { odf.CopyNormalsOrder(baseSubmesh.VertexList, newSubmesh.VertexList); } else if (normalsMethod == CopyMeshMethod.CopyNear) { odf.CopyNormalsNear(baseSubmesh.VertexList, newSubmesh.VertexList); } if (bonesMethod == CopyMeshMethod.CopyOrder) { odf.CopyBonesOrder(baseSubmesh.VertexList, newSubmesh.VertexList, newBones); } else if (bonesMethod == CopyMeshMethod.CopyNear) { odf.CopyBonesNear(baseSubmesh.VertexList, newSubmesh.VertexList, newBones); } } if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i]) { replaceSubmeshes[idx] = newSubmesh; } else { addSubmeshes.Add(newSubmesh); } } if ((frameMesh != null) && merge) { newMesh.Clear(); newMesh.Capacity = replaceSubmeshes.Length + addSubmeshes.Count; for (int i = 0, submeshesRemoved = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] == null) { odfSubmesh newSubmesh = frameMesh[i - submeshesRemoved++]; frameMesh.RemoveChild(newSubmesh); // save the bone list from being deleted in RemoveMesh newMesh.AddChild(newSubmesh); } else { newMesh.AddChild(replaceSubmeshes[i]); } } newMesh.AddRange(addSubmeshes); } if (frameMesh != null) { RemoveMesh(parser, frameMesh, frame, false); parser.UsedIDs.Add((int)newMesh.Id, typeof(odfMesh)); frame.MeshId = newMesh.Id; List <ObjectID> removeKeyList = new List <ObjectID>(); foreach (odfSubmesh submesh in newMesh) { ObjectID newSubmeshID = submesh.Id; ObjectID baseSubmeshID; if (submeshIDtranslation.TryGetValue(newSubmeshID, out baseSubmeshID)) { if (odf.FindBoneList(baseSubmeshID, parser.EnvelopeSection) == null) { odfBoneList boneList = odf.FindBoneList(newSubmeshID, parser.EnvelopeSection); if (boneList != null) { boneList.SubmeshId = baseSubmeshID; } submesh.Id = baseSubmeshID; parser.UsedIDs.Remove((int)newSubmeshID); } foreach (KeyValuePair <ObjectID, ObjectID> pair in submeshIDtranslation) { if (pair.Value == baseSubmeshID) { removeKeyList.Add(pair.Key); } } foreach (ObjectID removeId in removeKeyList) { submeshIDtranslation.Remove(removeId); } removeKeyList.Clear(); } } } }
private void CollectObjectIDs(IObjInfo obj) { ObjectID id = null; if (obj is odfMaterial) { id = ((odfMaterial)obj).Id; } else if (obj is odfTexture) { id = ((odfTexture)obj).Id; } else if (obj is odfMesh) { odfMesh mesh = (odfMesh)obj; for (int i = 0; i < mesh.Count; i++) { odfSubmesh submesh = mesh[i]; CollectObjectIDs(submesh); } id = ((odfMesh)obj).Id; } else if (obj is odfSubmesh) { id = ((odfSubmesh)obj).Id; } else if (obj is odfFrame) { odfFrame frame = (odfFrame)obj; for (int i = 0; i < frame.Count; i++) { odfFrame childFrame = frame[i]; CollectObjectIDs(childFrame); } id = frame.Id; } else if (obj is odfMaterialSection) { odfMaterialSection matSec = (odfMaterialSection)obj; foreach (odfMaterial mat in matSec) { CollectObjectIDs(mat); } } else if (obj is odfTextureSection) { odfTextureSection texSec = (odfTextureSection)obj; foreach (odfTexture tex in texSec) { CollectObjectIDs(tex); } } else if (obj is odfMeshSection) { odfMeshSection meshSec = (odfMeshSection)obj; foreach (odfMesh mesh in meshSec) { CollectObjectIDs(mesh); } } else if (obj is odfFrameSection) { odfFrameSection frameSec = (odfFrameSection)obj; foreach (odfFrame frame in frameSec) { CollectObjectIDs(frame); } } else if (obj is odfEnvelopeSection) { odfEnvelopeSection envSec = (odfEnvelopeSection)obj; foreach (odfBoneList boneList in envSec.ChildList) { CollectObjectIDs(boneList); } id = envSec.Id; } else if (obj is odfBoneList) { odfBoneList boneList = (odfBoneList)obj; foreach (odfBone bone in boneList) { CollectObjectIDs(bone); } id = boneList.Id; } else if (obj is odfMorphSection) { id = ((odfMorphSection)obj).Id; } else if (obj is odfTXPTSection) { id = ((odfTXPTSection)obj).Id; } else if (obj is odfMATASection) { id = ((odfMATASection)obj).Id; } else if (obj is odfANIMSection) { id = ((odfANIMSection)obj).Id; } else if (obj is odfBANMSection) { id = ((odfBANMSection)obj).Id; } if (id != null) { int idVal = (int)id; if (idVal != 0) { try { this.UsedIDs.Add(idVal, obj.GetType()); } catch (ArgumentException argEx) { Type typeInDic; this.UsedIDs.TryGetValue(idVal, out typeInDic); Report.ReportLog(obj.GetType() + " ID: " + id + " - " + argEx.Message + " - " + typeInDic); } catch (Exception ex) { Report.ReportLog(obj.GetType() + " ID: " + id + " - " + ex.Message); } } else if (!(obj is odfBoneList)) { Report.ReportLog("Invalid ID used by " + obj.GetType().Name); } } }
public static void CopyBonesOrder(List <odfVertex> src, List <odfVertex> dest, odfBoneList destBones) { if (src.Count > dest.Count) { int invalidIndex = dest.Count; foreach (odfBone bone in destBones) { List <int> idxList = new List <int>(bone.NumberIndices); List <float> weightList = new List <float>(bone.NumberIndices); for (int i = 0; i < bone.NumberIndices; i++) { if (bone.VertexIndexArray[i] < invalidIndex) { idxList.Add(bone.VertexIndexArray[i]); weightList.Add(bone.WeightArray[i]); } } if (idxList.Count != bone.NumberIndices) { int oldLength = bone.VertexIndexArray.Length; bone.VertexIndexArray = idxList.ToArray(); bone.WeightArray = weightList.ToArray(); if (bone.VertexIndexArray.Length != oldLength) { bone.AlwaysZero24perIndex = new byte[24 * bone.VertexIndexArray.Length]; } } } } }
public static void CopyBonesNear(List <odfVertex> src, List <odfVertex> dest, odfBoneList destBones) { Dictionary <odfBone, Tuple <List <int>, List <float> > > boneTranslation = new Dictionary <odfBone, Tuple <List <int>, List <float> > >(destBones.Count); for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; int nearestVertIdx = -1; for (int j = 0; j < src.Count; j++) { odfVertex srcVert = src[j]; var srcPos = srcVert.Position; float[] diff = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] }; float distSq = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]); if (distSq < minDistSq) { minDistSq = distSq; nearestVertIdx = j; } } int numInfluences = 0; foreach (odfBone srcBone in destBones) { for (int k = 0; k < srcBone.NumberIndices; k++) { if (srcBone.VertexIndexArray[k] == nearestVertIdx) { List <int> idxList; List <float> weightList; Tuple <List <int>, List <float> > destLists; if (!boneTranslation.TryGetValue(srcBone, out destLists)) { idxList = new List <int>(); weightList = new List <float>(); destLists = new Tuple <List <int>, List <float> >(idxList, weightList); boneTranslation.Add(srcBone, destLists); } else { idxList = destLists.Item1; weightList = destLists.Item2; } idxList.Add(i); weightList.Add(srcBone.WeightArray[k]); numInfluences++; break; } } if (numInfluences == 4) { break; } } } foreach (var boneListPair in boneTranslation) { odfBone srcBone = boneListPair.Key; int oldLength = srcBone.VertexIndexArray.Length; Tuple <List <int>, List <float> > destLists = boneListPair.Value; srcBone.VertexIndexArray = destLists.Item1.ToArray(); srcBone.WeightArray = destLists.Item2.ToArray(); if (srcBone.VertexIndexArray.Length != oldLength) { srcBone.AlwaysZero24perIndex = new byte[24 * srcBone.VertexIndexArray.Length]; } } }
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]; } } } } }