public void HighlightBone(remParser parser, remMesh remMesh, int boneIdx, bool show) { List <List <remVertex> > submeshVertLists = new List <List <remVertex> >(remMesh.numMats); List <List <ushort> > submeshFaceLists = new List <List <ushort> >(remMesh.numMats); List <int[]> submeshVertIndices = new List <int[]>(remMesh.numMats); SplitMesh(remMesh, submeshVertLists, submeshFaceLists, submeshVertIndices); remSkin boneList = rem.FindSkin(remMesh.name, parser.SKIC); int submeshIdx = 0; for (AnimationMeshContainer mesh = (AnimationMeshContainer)meshFrames[0].MeshContainer; mesh != null; mesh = (AnimationMeshContainer)mesh.NextMeshContainer, submeshIdx++) { if (mesh.MeshData != null && mesh.MeshData.Mesh != null) { List <remVertex> vertexList = submeshVertLists[submeshIdx]; byte[][] vertexBoneIndices = null; float[][] vertexWeights = ConvertVertexWeights(vertexList, submeshVertIndices[submeshIdx], boneList, out vertexBoneIndices); FillVertexBuffer(mesh.MeshData.Mesh, vertexList, vertexWeights, vertexBoneIndices, show ? boneIdx : -1); } if (mesh.BoneLines != null) { for (int j = 0; j < BoneObjSize; j++) { mesh.BoneLines[boneIdx * BoneObjSize + j].Color = show ? Color.Crimson.ToArgb(): Color.CornflowerBlue.ToArgb(); } } } }
public remMesh Clone(bool submeshes, bool boneList, remParser parser, List <remSkin> clonedSkins) { remMesh mesh = new remMesh(numMats); mesh.name = new remId(name); rem.CopyUnknowns(this, mesh); if (submeshes) { for (int i = 0; i < numMats; i++) { mesh.AddMaterial(new remId(materials[i])); } mesh.vertices = new remVertex[numVertices]; for (int i = 0; i < numVertices; i++) { mesh.vertices[i] = vertices[i].Clone(); } mesh.faces = (int[])faces.Clone(); mesh.faceMarks = (int[])faceMarks.Clone(); } remSkin skin = rem.FindSkin(name, parser.SKIC); if (skin != null) { skin = skin.Clone(); skin.mesh = mesh.name; clonedSkins.Add(skin); } return(mesh); }
public static HashSet <string> SearchHierarchy(remParser parser, remMesh mesh) { HashSet <string> exportFrames = new HashSet <string>(); SearchHierarchy(parser.BONC.rootFrame, mesh, exportFrames); remSkin boneList = FindSkin(mesh.name, parser.SKIC); if (boneList != null) { for (int i = 0; i < boneList.Count; i++) { if (!exportFrames.Contains(boneList[i].bone.ToString())) { remBone boneParent = FindFrame(boneList[i].bone, parser.BONC.rootFrame); if (boneParent == null) { Report.ReportLog("Missing bone frame " + boneList[i].bone); continue; } while (boneParent.Parent != null && exportFrames.Add(boneParent.name.ToString())) { boneParent = (remBone)boneParent.Parent; } } } } return(exportFrames); }
public void SetBoneMatrix(int meshIdx, int boneIdx, double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44) { remMesh mesh = Parser.MESC[meshIdx]; remSkin skin = rem.FindSkin(mesh.name, Parser.SKIC); remBoneWeights boneWeights = skin[boneIdx]; Matrix m = new Matrix(); m.M11 = (float)m11; m.M12 = (float)m12; m.M13 = (float)m13; m.M14 = (float)m14; m.M21 = (float)m21; m.M22 = (float)m22; m.M23 = (float)m23; m.M24 = (float)m24; m.M31 = (float)m31; m.M32 = (float)m32; m.M33 = (float)m33; m.M34 = (float)m34; m.M41 = (float)m41; m.M42 = (float)m42; m.M43 = (float)m43; m.M44 = (float)m44; boneWeights.matrix = m; }
private void listViewAnimationTrack_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { List <DockContent> formREMList; if (!Gui.Docking.DockContents.TryGetValue(typeof(FormREM), out formREMList)) { return; } foreach (FormREM formMesh in formREMList) { for (int i = 0; i < formMesh.renderObjectMeshes.Count; i++) { RenderObjectREM mesh = formMesh.renderObjectMeshes[i]; if (mesh != null && formMesh.renderObjectIds[i] > -1) { remMesh remMesh = formMesh.Editor.Parser.MESC[i]; remSkin skin = rem.FindSkin(remMesh.name, formMesh.Editor.Parser.SKIC); if (skin == null) { continue; } remBoneWeights boneWeights = rem.FindBoneWeights(skin, new remId(e.Item.Text)); if (boneWeights == null) { continue; } mesh.HighlightBone(formMesh.Editor.Parser, remMesh, skin.IndexOf(boneWeights), e.IsSelected); Gui.Renderer.Render(); } } } }
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); }
public void CopyBoneWeights(int meshIdx, int boneIdx) { remMesh mesh = Parser.MESC[meshIdx]; remSkin skin = rem.FindSkin(mesh.name, Parser.SKIC); remBoneWeights boneWeights = skin[boneIdx]; skin.AddChild(boneWeights.Clone()); }
public void SetBoneSRT(int meshIdx, int boneIdx, double sX, double sY, double sZ, double rX, double rY, double rZ, double tX, double tY, double tZ) { remMesh mesh = Parser.MESC[meshIdx]; remSkin skin = rem.FindSkin(mesh.name, Parser.SKIC); remBoneWeights boneWeights = skin[boneIdx]; boneWeights.matrix = FbxUtility.SRTToMatrix(new Vector3((float)sX, (float)sY, (float)sZ), new Vector3((float)rX, (float)rY, (float)rZ), new Vector3((float)tX, (float)tY, (float)tZ)); }
public Mesh(remMesh mesh, remSkin skin) { name = mesh.name; InitChildren(mesh.numMats); for (int i = 0; i < mesh.numMats; i++) { Submesh submesh = new Submesh(mesh, skin, i); AddChild(submesh); } }
public remSkin Clone() { remSkin skin = new remSkin(Count); foreach (remBoneWeights boneWeights in this) { skin.AddChild(boneWeights.Clone()); } return(skin); }
public void SetMeshName(int idx, string name) { remId newName = new remId(name); remMesh mesh = Parser.MESC[idx]; remSkin skin = rem.FindSkin(mesh.name, Parser.SKIC); if (skin != null) { skin.mesh = newName; } Parser.MESC[idx].name = newName; }
public static void RemoveMesh(remParser parser, remMesh mesh) { parser.MESC.RemoveChild(mesh); mesh.frame = null; remSkin skin = FindSkin(mesh.name, parser.SKIC); if (skin != null) { parser.SKIC.RemoveChild(skin); } }
public static remBoneWeights FindBoneWeights(remSkin skin, remId boneFrame) { for (int i = 0; i < skin.Count; i++) { remBoneWeights boneWeights = skin[i]; if (boneWeights.bone == boneFrame) { return(boneWeights); } } return(null); }
public void SetBoneFrame(int meshIdx, int boneIdx, string frame) { remId newBoneFrameId = new remId(frame); remBone boneFrame = rem.FindFrame(newBoneFrameId, Parser.BONC.rootFrame); if (boneFrame == null) { throw new FormatException("Frame not found"); } remSkin skin = rem.FindSkin(Parser.MESC[meshIdx].name, Parser.SKIC); remBoneWeights boneWeights = skin[boneIdx]; boneWeights.bone = boneFrame.name; }
public bool RemoveBone(int meshIdx, int boneIdx) { remMesh mesh = Parser.MESC[meshIdx]; remSkin boneList = rem.FindSkin(mesh.name, Parser.SKIC); if (boneList.Count == 1 && boneIdx == 0) { Parser.SKIC.RemoveChild(boneList); return(true); } else { boneList.RemoveChild(boneIdx); return(false); } }
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); } }
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 static remSKICsection ReadSkin(string sectionName, int sectionLength, int numSkins, byte[] sectionBuffer) { remSKICsection skinSec = new remSKICsection(numSkins); int secBufIdx = 0; for (int subSection = 0; subSection < numSkins; 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); remId mesh = GetIdentifier(sectionBuffer, secBufIdx + 8); int numWeights = BitConverter.ToInt32(sectionBuffer, secBufIdx + 8 + 256); remSkin skin = new remSkin(numWeights); Trace.Assert(TypeCheck(remSkin.ClassType, type)); skin.mesh = mesh; int weightBufIdx = secBufIdx + 8 + 256 + 4; for (int weightIdx = 0; weightIdx < numWeights; weightIdx++) { remBoneWeights weights = new remBoneWeights(); weights.bone = GetIdentifier(sectionBuffer, weightBufIdx); weightBufIdx += 256; int numVertIdxWts = BitConverter.ToInt32(sectionBuffer, weightBufIdx); weightBufIdx += 4; 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, weightBufIdx); weightBufIdx += 4; } matrix.set_Rows(i, row); } weights.matrix = matrix; weights.vertexIndices = new int[numVertIdxWts]; for (int i = 0; i < numVertIdxWts; i++) { weights.vertexIndices[i] = BitConverter.ToInt32(sectionBuffer, weightBufIdx); weightBufIdx += 4; } weights.vertexWeights = new float[weights.numVertIdxWts]; for (int i = 0; i < numVertIdxWts; i++) { weights.vertexWeights[i] = BitConverter.ToSingle(sectionBuffer, weightBufIdx); weightBufIdx += 4; } skin.AddChild(weights); } skinSec.AddChild(skin); secBufIdx += length; } if (secBufIdx != sectionLength) { Report.ReportLog("Warning! SKIC section has wrong length."); } return(skinSec); }
public Submesh(remMesh mesh, remSkin skin, int submeshIdx) { MaterialName = mesh.materials[submeshIdx]; VertexList = new List <remVertex>(mesh.numVertices); FaceList = new List <int>(mesh.numFaces * 3); int[] vertIndices = new int[mesh.numVertices]; for (int i = 0; i < mesh.numVertices; i++) { vertIndices[i] = -1; } for (int i = 0; i < mesh.numFaces; i++) { if (mesh.faceMarks[i] != submeshIdx) { continue; } for (int j = 0; j < 3; j++) { int vertIdx = mesh.faces[i * 3 + j]; if (vertIndices[vertIdx] < 0) { vertIndices[vertIdx] = VertexList.Count; VertexList.Add(mesh.vertices[vertIdx]); } FaceList.Add(vertIndices[vertIdx]); } } VertexList.TrimExcess(); FaceList.TrimExcess(); if (skin == null) { return; } BoneList = new List <remBoneWeights>(skin.Count); foreach (remBoneWeights boneWeights in skin) { Dictionary <int, float> boneDic = new Dictionary <int, float>(boneWeights.numVertIdxWts); for (int i = 0; i < boneWeights.numVertIdxWts; i++) { int oldVertIdx = boneWeights.vertexIndices[i]; int newVertIdx = vertIndices[oldVertIdx]; if (newVertIdx >= 0) { boneDic.Add(newVertIdx, boneWeights.vertexWeights[i]); } } if (boneDic.Count == 0) { continue; } remBoneWeights newBoneWeights = new remBoneWeights(); newBoneWeights.bone = boneWeights.bone; newBoneWeights.matrix = boneWeights.matrix; newBoneWeights.vertexIndices = new int[boneDic.Count]; boneDic.Keys.CopyTo(newBoneWeights.vertexIndices, 0); newBoneWeights.vertexWeights = new float[boneDic.Count]; boneDic.Values.CopyTo(newBoneWeights.vertexWeights, 0); BoneList.Add(newBoneWeights); } }
public remMesh CreateMesh(out remSkin skin) { remMesh mesh = new remMesh(Count); skin = new remSkin(0); skin.mesh = mesh.name = name; List <remVertex> newVertices = new List <remVertex>(); List <int> newFaces = new List <int>(); List <int> newFaceMarks = new List <int>(); Dictionary <remId, Tuple <Matrix, List <int>, List <float> > > boneDic = new Dictionary <remId, Tuple <Matrix, List <int>, List <float> > >(); for (int i = 0; i < Count; i++) { Submesh submesh = this[i]; mesh.AddMaterial(submesh.MaterialName); newFaces.Capacity += submesh.FaceList.Count; foreach (int vertexIdx in submesh.FaceList) { newFaces.Add(newVertices.Count + vertexIdx); } int[] faceMarks = new int[submesh.numFaces]; for (int j = 0; j < submesh.numFaces; j++) { faceMarks[j] = i; } newFaceMarks.AddRange(faceMarks); if (submesh.BoneList != null) { foreach (remBoneWeights boneWeights in submesh.BoneList) { Tuple <Matrix, List <int>, List <float> > newBone = null; if (!boneDic.TryGetValue(boneWeights.bone, out newBone)) { newBone = new Tuple <Matrix, List <int>, List <float> >(boneWeights.matrix, new List <int>(boneWeights.numVertIdxWts), new List <float>(boneWeights.numVertIdxWts)); boneDic.Add(boneWeights.bone, newBone); } List <int> vertIdxs = newBone.Item2; vertIdxs.Capacity += boneWeights.vertexIndices.Length; foreach (int vertexIdx in boneWeights.vertexIndices) { vertIdxs.Add(newVertices.Count + vertexIdx); } List <float> weights = newBone.Item3; weights.AddRange(boneWeights.vertexWeights); } } newVertices.AddRange(submesh.VertexList); } mesh.vertices = newVertices.ToArray(); mesh.faces = newFaces.ToArray(); mesh.faceMarks = newFaceMarks.ToArray(); foreach (var pair in boneDic) { remBoneWeights newBoneWeights = new remBoneWeights(); newBoneWeights.bone = pair.Key; newBoneWeights.matrix = pair.Value.Item1; newBoneWeights.vertexIndices = pair.Value.Item2.ToArray(); newBoneWeights.vertexWeights = pair.Value.Item3.ToArray(); skin.AddChild(newBoneWeights); } return(mesh); }
private float[][] ConvertVertexWeights(List <remVertex> vertexList, int[] vertexIndices, remSkin boneList, out byte[][] vertexBoneIndices) { int numBones = boneList != null ? boneList.Count : 0; float[][] vertexWeights = new float[vertexList.Count][]; vertexBoneIndices = new byte[vertexList.Count][]; for (int j = 0; j < vertexList.Count; j++) { int meshVertIdx = -1; for (int k = 0; k < vertexIndices.Length; k++) { if (vertexIndices[k] == j) { meshVertIdx = k; break; } } if (meshVertIdx < 0) { throw new Exception("ConvertVertexWeights : index not found"); } vertexWeights[j] = new float[4]; vertexBoneIndices[j] = new byte[4]; int weightIdx = 0; for (int k = 0; k < numBones; k++) { remBoneWeights bone = boneList[k]; for (int l = 0; l < bone.numVertIdxWts; l++) { if (bone.vertexIndices[l] == meshVertIdx) { vertexBoneIndices[j][weightIdx] = (byte)k; if (weightIdx < 3) { vertexWeights[j][weightIdx++] = bone.vertexWeights[l]; } else { vertexWeights[j][3] = 1f - vertexWeights[j][0] - vertexWeights[j][1] - vertexWeights[j][2]; } break; } } } } return(vertexWeights); }
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); }
public static void RemoveSubmesh(remParser parser, remMesh mesh, int submeshIdx) { List <int> newFaces = new List <int>(mesh.numFaces * 3); List <int> newFaceMarks = new List <int>(mesh.numFaces); bool[] usedVertices = new bool[mesh.numVertices]; for (int i = 0; i < mesh.faceMarks.Length; i++) { if (mesh.faceMarks[i] != submeshIdx) { newFaceMarks.Add(mesh.faceMarks[i] < submeshIdx ? mesh.faceMarks[i] : mesh.faceMarks[i] - 1); for (int j = i * 3; j < i * 3 + 3; j++) { int vertIdx = mesh.faces[j]; newFaces.Add(vertIdx); usedVertices[vertIdx] = true; } } } int[] vertIdxMap = new int[mesh.numVertices]; List <remVertex> vertList = new List <remVertex>(mesh.numVertices); int numNewVerts = 0; for (int i = 0; i < mesh.numVertices; i++) { if (usedVertices[i]) { vertIdxMap[i] = numNewVerts++; vertList.Add(mesh.vertices[i]); } } mesh.vertices = vertList.ToArray(); for (int i = 0; i < newFaces.Count; i++) { newFaces[i] = vertIdxMap[newFaces[i]]; } mesh.faces = newFaces.ToArray(); mesh.faceMarks = newFaceMarks.ToArray(); mesh.materials.RemoveAt(submeshIdx); remSkin skin = rem.FindSkin(mesh.name, parser.SKIC); if (skin != null) { for (int i = 0; i < skin.Count; i++) { remBoneWeights bw = skin[i]; Dictionary <int, float> newBoneWeights = new Dictionary <int, float>(); for (int j = 0; j < bw.numVertIdxWts; j++) { int oldVertIdx = bw.vertexIndices[j]; if (usedVertices[oldVertIdx]) { newBoneWeights.Add(vertIdxMap[oldVertIdx], bw.vertexWeights[j]); } } if (newBoneWeights.Count > 0) { bw.vertexIndices = new int[newBoneWeights.Count]; bw.vertexWeights = new float[newBoneWeights.Count]; newBoneWeights.Keys.CopyTo(bw.vertexIndices, 0); newBoneWeights.Values.CopyTo(bw.vertexWeights, 0); } else { skin.RemoveChild(i); i--; } } } }
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); } } }