public static remBone CreateFrame(ImportedFrame frame) { remBone remFrame = new remBone(frame.Count); remFrame.matrix = frame.Matrix; remFrame.name = new remId(frame.Name); for (int i = 0; i < frame.Count; i++) { remFrame.AddChild(CreateFrame(frame[i])); } return remFrame; }
public void AddFrame(remBone srcFrame, remParser srcParser, int destParentIdx) { List<remMaterial> materialClones = new List<remMaterial>(srcParser.MATC.Count); List<remMesh> meshClones = new List<remMesh>(srcParser.MESC.Count); List<remSkin> skinClones = new List<remSkin>(srcParser.SKIC.Count); if (srcFrame == null) { srcFrame = srcParser.BONC.rootFrame; } var newFrame = srcFrame.Clone(true, true, srcParser, materialClones, meshClones, skinClones); AddFrame(newFrame, destParentIdx); PullNewMaterials(materialClones); Parser.MESC.ChildList.AddRange(meshClones); Parser.SKIC.ChildList.AddRange(skinClones); }
public static void ReplaceMesh(remBone frame, remParser parser, WorkspaceMesh mesh, List<ImportedMaterial> materials, List<ImportedTexture> textures, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod, bool meshFrameCorrection) { remMesh frameREMMesh = rem.FindMesh(frame, parser.MESC); int startPos = 0; if (meshFrameCorrection) { // frame.matrix = Matrix.Scaling(-1f, 1f, 1f) * Matrix.RotationYawPitchRoll(0f, (float)(Math.PI / 2), (float)Math.PI); frame.matrix = Matrix.Identity; frame.matrix.M22 = frame.matrix.M33 = 0f; frame.matrix.M23 = frame.matrix.M32 = 1f; startPos = mesh.Name.IndexOf("(Scale"); if (startPos > 0) { int endPos = mesh.Name.IndexOf(')'); float scale; if (Single.TryParse(mesh.Name.Substring(startPos + 7, endPos - startPos - 7), out scale)) { frame.matrix *= Matrix.Scaling(new Vector3(scale)); } remId newFrameName = new remId(mesh.Name.Substring(0, startPos)); if (newFrameName != frame.name) { if (rem.FindFrame(newFrameName, parser.BONC.rootFrame) == null) { frame.name = newFrameName; } else { Report.ReportLog("Warning! Cant rename frame (and mesh) " + mesh.Name + " automatically to " + newFrameName + "."); } } } } Matrix transform = Matrix.Scaling(-1f, 1f, 1f); remBone transformFrame = frame; while (transformFrame != parser.BONC.rootFrame) { transform *= transformFrame.matrix; transformFrame = transformFrame.Parent as remBone; } transform.Invert(); string[] materialNames; int[] indices; bool[] worldCoords; bool[] replaceSubmeshesOption; remMesh newREMMesh = CreateMesh(mesh, out materialNames, out indices, out worldCoords, out replaceSubmeshesOption); if (startPos > 0) { newREMMesh.name = frame.name; } Mesh newMesh = new Mesh(newREMMesh, CreateBoneList(mesh, transform)); remSkin frameMeshSkin = null; Mesh frameMesh = null; if (frameREMMesh != null) { newMesh.name = frameREMMesh.name; frameMeshSkin = rem.FindSkin(frameREMMesh.name, parser.SKIC); frameMesh = new Mesh(frameREMMesh, frameMeshSkin); } Submesh[] replaceSubmeshes = frameMesh != null ? new Submesh[frameMesh.Count] : null; List<Submesh> addSubmeshes = new List<Submesh>(newMesh.Count); for (int i = 0; i < newMesh.Count; i++) { remMaterial mat = rem.FindMaterial(new remId(materialNames[i]), parser.MATC); if (materials != null) { if (mat == null) { mat = CreateMaterial(ImportedHelpers.FindMaterial(materialNames[i], materials)); parser.MATC.AddChild(mat); } /* if (textures != null) { string texName = materials[i].Textures[0]; remMaterial texMat = rem.FindMaterial(parser.MATC, new remId(texName)); if (texMat == null) { for (int k = 0; k < textures.Count; k++) { if (textures[k].Name == texName) { // texMat = CreateTexture(textures[k], Path.GetDirectoryName(parser.ODFPath)); break; } } } }*/ } Submesh newSubmesh = newMesh[i]; if (mat != null) { newSubmesh.MaterialName = mat.name; } if (worldCoords[i]) { List<remVertex> newVertexList = newSubmesh.VertexList; for (int j = 0; j < newVertexList.Count; j++) { newVertexList[j].Position = Vector3.TransformCoordinate(newVertexList[j].Position, transform); } } Submesh baseSubmesh = null; List<remBoneWeights> newBones = null; int idx = indices[i]; if ((frameMesh != null) && (idx >= 0) && (idx < frameMesh.Count)) { baseSubmesh = frameMesh[idx]; if ((bonesMethod == CopyMeshMethod.CopyOrder) || (bonesMethod == CopyMeshMethod.CopyNear)) { List<remBoneWeights> baseBones = baseSubmesh.BoneList; if (baseBones != null) { newBones = new List<remBoneWeights>(baseBones.Count); foreach (remBoneWeights boneWeights in baseBones) { remBoneWeights copy = boneWeights.Clone(); newBones.Add(copy); } newSubmesh.BoneList = newBones; } } else if (bonesMethod == CopyMeshMethod.Replace) newBones = newSubmesh.BoneList; } else { newBones = newSubmesh.BoneList; } if (baseSubmesh != null) { if (normalsMethod == CopyMeshMethod.CopyOrder) { rem.CopyNormalsOrder(baseSubmesh.VertexList, newSubmesh.VertexList); } else if (normalsMethod == CopyMeshMethod.CopyNear) { rem.CopyNormalsNear(baseSubmesh.VertexList, newSubmesh.VertexList); } if (bonesMethod == CopyMeshMethod.CopyOrder) { rem.CopyBonesOrder(baseSubmesh.VertexList, newSubmesh.VertexList, newBones); } else if (bonesMethod == CopyMeshMethod.CopyNear) { rem.CopyBonesNear(baseSubmesh.VertexList, newSubmesh.VertexList, newBones); } } if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i]) { replaceSubmeshes[idx] = newSubmesh; } else { addSubmeshes.Add(newSubmesh); } } if ((frameMesh != null) && merge) { newMesh.ChildList.Clear(); newMesh.ChildList.Capacity = replaceSubmeshes.Length + addSubmeshes.Count; for (int i = 0, submeshesRemoved = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] == null) { Submesh newSubmesh = frameMesh[i - submeshesRemoved++]; newMesh.AddChild(newSubmesh); } else { newMesh.AddChild(replaceSubmeshes[i]); } } newMesh.ChildList.AddRange(addSubmeshes); } remSkin skin; newREMMesh = newMesh.CreateMesh(out skin); newREMMesh.frame = frame.name; if (frameREMMesh != null) { CopyUnknowns(frameREMMesh, newREMMesh); parser.MESC.InsertChild(parser.MESC.IndexOf(frameREMMesh), newREMMesh); RemoveMesh(parser, frameREMMesh); } else { CreateUnknowns(newREMMesh); parser.MESC.AddChild(newREMMesh); } if (skin.Count > 0) { parser.SKIC.AddChild(skin); } }
private AnimationFrame CreateFrame(remBone frame, remParser parser, HashSet<string> extractFrames, remMesh mesh, Device device, Matrix combinedParent, List<AnimationFrame> meshFrames) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.name.ToString(); animationFrame.TransformationMatrix = frame.matrix; animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix; if (frame.name == mesh.frame) { ExtendedMaterial[] materials = new ExtendedMaterial[mesh.numMats]; List<List<remVertex>> submeshVertLists = new List<List<remVertex>>(mesh.numMats); List<List<ushort>> submeshFaceLists = new List<List<ushort>>(mesh.numMats); List<int[]> submeshVertIndices = new List<int[]>(mesh.numMats); SplitMesh(mesh, submeshVertLists, submeshFaceLists, submeshVertIndices); remSkin boneList = rem.FindSkin(mesh.name, parser.SKIC); bool skinned = boneList != null; int numBones = skinned ? boneList.Count : 0; List<string> boneNamesList = new List<string>(numBones); List<Matrix> boneOffsetsList = new List<Matrix>(numBones); for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { boneNamesList.Add(boneList[boneIdx].bone.ToString()); boneOffsetsList.Add(boneList[boneIdx].matrix); } List<string> boneFrameParentNames = new List<string>(numBones); List<Matrix> boneFrameParentMatrices = new List<Matrix>(numBones); for (int boneIdx = 0; boneIdx < numBones; boneIdx++) { remBone boneFrame = rem.FindFrame(boneList[boneIdx].bone, parser.BONC.rootFrame); if (boneFrame == null) { continue; } remBone boneFrameParent = boneFrame.Parent; if (!boneNamesList.Contains(boneFrameParent.name) && !boneFrameParentNames.Contains(boneFrameParent.name)) { boneFrameParentNames.Add(boneFrameParent.name); Matrix incompleteMeshFrameCorrection = Matrix.Invert(frame.matrix); boneFrameParentMatrices.Add(incompleteMeshFrameCorrection * Matrix.Invert(boneFrame.matrix) * boneList[boneIdx].matrix); } } boneNamesList.AddRange(boneFrameParentNames); string[] boneNames = boneNamesList.ToArray(); boneOffsetsList.AddRange(boneFrameParentMatrices); Matrix[] boneOffsets = boneOffsetsList.ToArray(); AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[submeshFaceLists.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < submeshFaceLists.Count; i++) { List<ushort> faceList = submeshFaceLists[i]; List<remVertex> vertexList = submeshVertLists[i]; 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++) { indexStream.Write(faceList[j]); } animationMesh.UnlockIndexBuffer(); } byte[][] vertexBoneIndices = null; float[][] vertexWeights = ConvertVertexWeights(vertexList, submeshVertIndices[i], boneList, out vertexBoneIndices); FillVertexBuffer(animationMesh, vertexList, vertexWeights, vertexBoneIndices, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { remVertex vertex = vertexList[j]; Vector3 position = vertex.Position; Vector3 normal = vertex.Normal; float[] boneWeights = vertexWeights[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(position, boneWeights, vertexBoneIndices[j], Color.Coral.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + normal, boneWeights, vertexBoneIndices[j], Color.Blue.ToArgb()); #if !DONT_MIRROR position.Z *= -1f; #endif 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; remMaterial mat = rem.FindMaterial(mesh.materials[i], parser.MATC); if (mat != null) { Material material3D = new Material(); material3D.Ambient = new Color4(mat.ambient); material3D.Diffuse = new Color4(mat.diffuse); material3D.Emissive = new Color4(mat.emissive); material3D.Specular = new Color4(mat.specular); material3D.Power = mat.specularPower; int matIdx = parser.MATC.IndexOf(mat); Materials[matIdx] = material3D; meshContainer.MaterialIndex = matIdx; int texIdx = 0; if (mat.texture != null && !TextureDic.TryGetValue(mat.texture.ToString(), out texIdx)) { ImportedTexture importedTex = null; if (!ImportedTextures.TryGetValue(mat.texture.ToString(), out importedTex)) { importedTex = rem.ImportedTexture(mat.texture, parser.RemPath, true); if (importedTex == null) { Report.ReportLog("Export textures of TEXH.FPK!"); continue; } ImportedTextures.Add(mat.texture.ToString(), importedTex); } Texture memTex = Texture.FromMemory(device, importedTex.Data); texIdx = TextureDic.Count; TextureDic.Add(mat.texture.ToString(), texIdx); Textures.Add(memTex); } meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } min = Vector3.TransformCoordinate(min, animationFrame.CombinedTransform); max = Vector3.TransformCoordinate(max, animationFrame.CombinedTransform); animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } for (int i = 0; i < frame.Count; i++) { remBone child = frame[i]; if (extractFrames.Contains(child.name.ToString())) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, mesh, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return animationFrame; }
void ReplaceFrame(remBone newFrame, int destParentIdx) { if (destParentIdx < 0) { Parser.BONC.rootFrame.ChildList.Clear(); foreach (remBone child in newFrame) { Parser.BONC.rootFrame.AddChild(child); } Parser.MESC.ChildList.Clear(); Parser.SKIC.ChildList.Clear(); } else { var destParent = Parser.BONC[destParentIdx]; bool found = false; for (int i = 0; i < destParent.Count; i++) { var dest = destParent[i]; if (dest.name == newFrame.name) { remMesh mesh = rem.FindMesh(dest, Parser.MESC); if (mesh != null) { rem.RemoveMesh(Parser, mesh); } destParent.RemoveChild(i); destParent.InsertChild(i, newFrame); found = true; break; } } if (!found) { destParent.AddChild(newFrame); } } RebuildBONC(); }
void MergeFrame(remBone srcParent, remBone destParent) { for (int i = 0; i < destParent.Count; i++) { var dest = destParent[i]; for (int j = 0; j < srcParent.Count; j++) { var src = srcParent[j]; if (src.name == dest.name) { MergeFrame(src, dest); srcParent.RemoveChild(j); remMesh mesh = rem.FindMesh(dest, Parser.MESC); if (mesh != null) { rem.RemoveMesh(Parser, mesh); } destParent.RemoveChild(i); destParent.InsertChild(i, src); break; } } } if (srcParent.name == destParent.name) { while (destParent.Count > 0) { var dest = destParent[0]; remMesh mesh = rem.FindMesh(dest, Parser.MESC); if (mesh != null) { rem.RemoveMesh(Parser, mesh); } destParent.RemoveChild(0); srcParent.AddChild(dest); } } else { while (srcParent.Count > 0) { var src = srcParent[0]; srcParent.RemoveChild(0); destParent.AddChild(src); } } }
void MergeFrame(remBone newFrame, int destParentIdx) { remBone srcParent = new remBone(1); srcParent.AddChild(newFrame); remBone destParent; if (destParentIdx < 0) { destParent = Parser.BONC.rootFrame; } else { destParent = Parser.BONC[destParentIdx]; } MergeFrame(srcParent, destParent); RebuildBONC(); }
void FindFrames(remBone frame, List<string> duplicates) { foreach (remBone remFrame in Parser.BONC) { if (remFrame.name == frame.name) { duplicates.Add(frame.name); } } foreach (remBone child in frame) { FindFrames(child, duplicates); } }
void DeleteReferringBones(remBone frame) { for (int i = 0; i < Parser.MESC.Count; i++) { remMesh mesh = Parser.MESC[i]; remSkin skin = rem.FindSkin(mesh.name, Parser.SKIC); if (skin != null) { remBoneWeights boneWeights = rem.FindBoneWeights(skin, frame.name); if (boneWeights != null) { RemoveBone(i, skin.IndexOf(boneWeights)); } } } foreach (remBone child in frame) { DeleteReferringBones(child); } }
void DeleteMeshesInSubframes(remBone frame) { remMesh mesh = rem.FindMesh(frame, Parser.MESC); if (mesh != null) { rem.RemoveMesh(Parser, mesh); } foreach (remBone child in frame) { DeleteMeshesInSubframes(child); } }
void ChildsFirst(remBone frame) { foreach (remBone child in frame) { ChildsFirst(child); } Parser.BONC.ChildList.Add(frame); }
void AddFrame(remBone newFrame, int destParentIdx) { List<string> duplicates = new List<string>(); FindFrames(newFrame, duplicates); if (duplicates.Count > 0) { StringBuilder builder = new StringBuilder(1000); for (int i = 0; i < duplicates.Count; i++) { string s = duplicates[i]; builder.AppendFormat(" {0}", s); if (i < duplicates.Count - 1) { builder.Append(','); } } throw new Exception("New hierarchy includes frames with names already present.\n " + builder.ToString()); } if (destParentIdx < 0) { Parser.BONC.rootFrame.AddChild(newFrame); } else { Parser.BONC[destParentIdx].AddChild(newFrame); } RebuildBONC(); }
private static remBONCsection ReadBones(string sectionName, int sectionLength, int numBones, byte[] sectionBuffer) { remBONCsection boneSec = new remBONCsection(numBones); int secBufIdx = 0; for (int subSection = 0; subSection < numBones; subSection++) { byte[] type = new byte[4] { sectionBuffer[secBufIdx+0], sectionBuffer[secBufIdx+1], sectionBuffer[secBufIdx+2], sectionBuffer[secBufIdx+3] }; int length = BitConverter.ToInt32(sectionBuffer, secBufIdx+4); remBone bone = new remBone(length > 256+16*4+4 ? (length - 256+16*4+4) / 256 : 0); Trace.Assert(TypeCheck(remBone.ClassType, type)); bone.name = GetIdentifier(sectionBuffer, secBufIdx+8); Matrix matrix = new Matrix(); for (int i = 0; i < 4; i++) { Vector4 row = new Vector4(); for (int j = 0; j < 4; j++) row[j] = BitConverter.ToSingle(sectionBuffer, secBufIdx+8+256 + (i*4 + j) * 4); matrix.set_Rows(i, row); } bone.matrix = matrix; int numChilds = BitConverter.ToInt32(sectionBuffer, secBufIdx+8+256 + 16*4); List<remId> childNames = new List<remId>(numChilds); for (int i = 0; i < numChilds; i++) childNames.Add(GetIdentifier(sectionBuffer, secBufIdx+8+256 + 16*4 + 4 + i*256)); AddParentBone(boneSec, bone, childNames); secBufIdx += length; } for (int i = 0; i < numBones; i++) { if (boneSec[i].Parent == null) { boneSec[i].Parent = boneSec.rootFrame; boneSec.rootFrame.AddChild(boneSec[i]); } } if (secBufIdx != sectionLength) Report.ReportLog("Warning! BONC section has wrong length."); return boneSec; }
private static void AddParentBone(remBONCsection sec, remBone parent, List<remId> childNames) { for (int i = 0; i < childNames.Count; i++) { remId child = childNames[i]; for (int j = 0; j < sec.Count; j++) { if (sec[j].name == child) { parent.AddChild(sec[j]); break; } } } sec.ChildList.Add(parent); }