static void SearchHierarchy(xxFrame root, xxFrame frame, HashSet <string> meshNames, HashSet <string> exportFrames) { if (frame.Mesh != null) { if (meshNames.Contains(frame.Name)) { xxFrame parent = frame; while (parent != null) { exportFrames.Add(parent.Name); parent = (xxFrame)parent.Parent; } xxMesh meshListSome = frame.Mesh; List <xxBone> boneList = meshListSome.BoneList; for (int i = 0; i < boneList.Count; i++) { if (!exportFrames.Contains(boneList[i].Name)) { xxFrame boneParent = FindFrame(boneList[i].Name, root); while (boneParent != null) { exportFrames.Add(boneParent.Name); boneParent = (xxFrame)boneParent.Parent; } } } } } for (int i = 0; i < frame.Count; i++) { SearchHierarchy(root, frame[i], meshNames, exportFrames); } }
public xxMesh Clone(bool submeshes, bool vertexListDup, bool boneList) { xxMesh mesh = new xxMesh(); mesh.SubmeshList = new List <xxSubmesh>(SubmeshList.Count); mesh.NumVector2PerVertex = NumVector2PerVertex; mesh.VertexListDuplicateUnknown = (byte[])VertexListDuplicateUnknown.Clone(); mesh.VertexListDuplicate = new List <xxVertex>(VertexListDuplicate.Count); mesh.BoneList = new List <xxBone>(BoneList.Count); if (submeshes) { for (int i = 0; i < SubmeshList.Count; i++) { mesh.SubmeshList.Add(SubmeshList[i].Clone()); } } if (vertexListDup) { for (int i = 0; i < VertexListDuplicate.Count; i++) { mesh.VertexListDuplicate.Add(VertexListDuplicate[i].Clone()); } } if (boneList) { for (int i = 0; i < BoneList.Count; i++) { mesh.BoneList.Add(BoneList[i].Clone()); } } return(mesh); }
public static void CreateUnknowns(xxMesh mesh) { mesh.NumVector2PerVertex = 0; mesh.VertexListDuplicateUnknown = IsSkinned(mesh) ? new byte[] { 0x1C, 0x11, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00 } : new byte[] { 0x12, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 }; }
public static void SetBoundingBox(xxFrame frame) { if (frame.Mesh == null) { frame.Bounds = new BoundingBox(); } else { xxMesh meshList = frame.Mesh; Vector3 min = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue); Vector3 max = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue); for (int i = 0; i < meshList.SubmeshList.Count; i++) { List <xxVertex> vertList = meshList.SubmeshList[i].VertexList; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; Vector3 pos = vert.Position; min = Vector3.Minimize(min, pos); max = Vector3.Maximize(max, pos); } } frame.Bounds = new BoundingBox(min, max); } }
public static int MorphMeshObjIdx(ushort[] meshIndices, xxMesh mesh) { int meshObjIdx = -1; if (mesh.SubmeshList.Count > 0) { if (mesh.SubmeshList.Count == 1) { if (ValidIndices(meshIndices, mesh.SubmeshList[0].VertexList)) { meshObjIdx = 0; } } else { float maxModified = 0; for (int i = 0; i < mesh.SubmeshList.Count; i++) { if (ValidIndices(meshIndices, mesh.SubmeshList[i].VertexList)) { float modified = (float)meshIndices.Length / mesh.SubmeshList[i].VertexList.Count; if (modified > maxModified) { maxModified = modified; meshObjIdx = i; } } } } } return(meshObjIdx); }
public static void SetNumVector2PerVertex(xxMesh mesh, byte value) { int diff = value - mesh.NumVector2PerVertex; if (diff < 0) { if (value == 0) { for (int i = 0; i < mesh.SubmeshList.Count; i++) { mesh.SubmeshList[i].Vector2Lists = null; } } else { diff = Math.Abs(diff); for (int i = 0; i < mesh.SubmeshList.Count; i++) { var submesh = mesh.SubmeshList[i]; for (int j = 0; j < submesh.VertexList.Count; j++) { var vectorList = submesh.Vector2Lists[j]; vectorList.RemoveRange(vectorList.Count - diff, diff); } } } } else if (diff > 0) { for (int i = 0; i < mesh.SubmeshList.Count; i++) { var submesh = mesh.SubmeshList[i]; if (submesh.Vector2Lists == null) { submesh.Vector2Lists = new List <List <Vector2> >(submesh.VertexList.Count); for (int j = 0; j < submesh.VertexList.Count; j++) { submesh.Vector2Lists.Add(new List <Vector2>(value)); for (int k = 0; k < diff; k++) { submesh.Vector2Lists[j].Add(new Vector2()); } } } else { for (int j = 0; j < submesh.VertexList.Count; j++) { for (int k = 0; k < diff; k++) { submesh.Vector2Lists[j].Add(new Vector2()); } } } } } mesh.NumVector2PerVertex = value; }
private void Export(DirectoryInfo dir, xxFrame meshFrame) { try { xaMorphSection morphSection = xaParser.MorphSection; xaMorphIndexSet indexSet = xa.FindMorphIndexSet(clip.Name, morphSection); ushort[] meshIndices = indexSet.MeshIndices; ushort[] morphIndices = indexSet.MorphIndices; xxMesh meshList = meshFrame.Mesh; int meshObjIdx = xa.MorphMeshObjIdx(meshIndices, meshList); if (meshObjIdx < 0) { throw new Exception("no valid mesh object was found for the morph"); } xxSubmesh meshObjBase = meshList.SubmeshList[meshObjIdx]; colorVertex = new bool[meshObjBase.VertexList.Count]; for (int i = 0; i < meshIndices.Length; i++) { colorVertex[meshIndices[i]] = true; } string dest = Utility.GetDestFile(dir, meshFrame.Name + "-" + clip.Name + "-", ".morph.mqo"); List <xaMorphKeyframeRef> refList = clip.KeyframeRefList; morphNames = new List <string>(refList.Count); vertLists = new List <List <ImportedVertex> >(refList.Count); for (int i = 0; i < refList.Count; i++) { if (!morphNames.Contains(refList[i].Name)) { List <ImportedVertex> vertList = xx.ImportedVertexList(meshObjBase.VertexList, xx.IsSkinned(meshList)); vertLists.Add(vertList); xaMorphKeyframe keyframe = xa.FindMorphKeyFrame(refList[i].Name, morphSection); for (int j = 0; j < meshIndices.Length; j++) { ImportedVertex vert = vertList[meshIndices[j]]; vert.Position = keyframe.PositionList[morphIndices[j]]; } morphNames.Add(keyframe.Name); } } faceList = xx.ImportedFaceList(meshObjBase.FaceList); Export(dest, meshObjBase.MaterialIndex); foreach (xxTexture tex in usedTextures) { xx.ExportTexture(tex, dir.FullName + @"\" + Path.GetFileName(tex.Name)); } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }
public void MoveSubmesh(int meshId, int submeshId, int newPosition) { xxMesh mesh = Meshes[meshId].Mesh; xxSubmesh src = mesh.SubmeshList[submeshId]; mesh.SubmeshList.Remove(src); mesh.SubmeshList.Insert(newPosition, src); Changed = true; }
public static bool RemoveUnusedBones(xxMesh mesh) { List <List <xxVertex> > vertexLists = new List <List <xxVertex> >(mesh.SubmeshList.Count); foreach (xxSubmesh submesh in mesh.SubmeshList) { vertexLists.Add(submesh.VertexList); } RemoveUnusedBones(vertexLists, mesh.BoneList); return(mesh.BoneList.Count > 0); }
public void ZeroWeights(int meshId, int boneId) { xxMesh mesh = Meshes[meshId].Mesh; xxBone bone = mesh.BoneList[boneId]; xxFrame parentFrame = xx.FindFrame(bone.Name, Parser.Frame).Parent; xxBone parentBone = xx.FindBone(mesh.BoneList, parentFrame.Name); byte parentBoneIdx = (byte)mesh.BoneList.IndexOf(parentBone); foreach (xxSubmesh submesh in mesh.SubmeshList) { foreach (xxVertex vertex in submesh.VertexList) { int parentIdx = -1; for (int i = 0; i < vertex.BoneIndices.Length; i++) { if (vertex.BoneIndices[i] == parentBoneIdx) { parentIdx = i; break; } } for (int i = 0; i < vertex.BoneIndices.Length; i++) { if (vertex.BoneIndices[i] == boneId) { if (parentIdx >= 0) { float[] w4 = vertex.Weights4(true); w4[parentIdx] += w4[i]; w4[i] = 0; vertex.Weights3[0] = w4[0]; vertex.Weights3[1] = w4[1]; vertex.Weights3[2] = w4[2]; } else { vertex.BoneIndices[i] = parentBoneIdx; } break; } } } } Changed = true; }
public void SnapBorders(object[] editors, object[] numMeshes, object[] meshes, int targetMesh, object[] targetSubmeshes, double tolerance, bool position, bool normal, bool bonesAndWeights, bool uv) { List <xxMesh> srcMeshes = new List <xxMesh>(); xxMesh mesh = Meshes[targetMesh].Mesh; List <xxSubmesh> submeshList = new List <xxSubmesh>(targetSubmeshes != null ? targetSubmeshes.Length : mesh.SubmeshList.Count); if (editors != null && numMeshes != null && meshes != null) { srcMeshes.Capacity = meshes.Length; xxEditor editor = null; int editorIdx = -1; int i = 1; foreach (object id in meshes) { if (--i == 0) { editorIdx++; i = (int)(double)numMeshes[editorIdx]; editor = (xxEditor)editors[editorIdx]; } srcMeshes.Add(editor.Meshes[(int)(double)id].Mesh); } if (targetSubmeshes != null) { foreach (object id in targetSubmeshes) { submeshList.Add(mesh.SubmeshList[(int)(double)id]); } } else { submeshList.AddRange(mesh.SubmeshList); } xx.SnapBorders(srcMeshes, mesh, submeshList, (float)tolerance, position, normal, bonesAndWeights, uv); } else { Report.ReportLog("Snapping inside of one mesh not implemented yet."); return; } }
public void HighlightBone(xxMesh xxMesh, int boneIdx, bool show) { 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 <xxVertex> vertexList = xxMesh.SubmeshList[submeshIdx].VertexList; FillVertexBuffer(mesh.MeshData.Mesh, vertexList, 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(); } } } }
private static void CalculateNormals(xaParser parser, xxFrame meshFrame, xaMorphKeyframe keyframe, xaMorphIndexSet set, float threshold) { xxMesh mesh = meshFrame.Mesh; ushort[] meshIndices = set.MeshIndices; ushort[] morphIndices = set.MorphIndices; int morphSubmeshIdx = MorphMeshObjIdx(meshIndices, mesh); if (morphSubmeshIdx < 0) { throw new Exception("no valid mesh object was found for the morph " + set.Name); } xxSubmesh submesh = mesh.SubmeshList[morphSubmeshIdx]; List <xxVertex> morphedVertices = new List <xxVertex>(submesh.VertexList.Count); for (ushort i = 0; i < submesh.VertexList.Count; i++) { xxVertex vert = new xxVertexUShort(); vert.Index = i; vert.Position = submesh.VertexList[i].Position; vert.Normal = submesh.VertexList[i].Normal; morphedVertices.Add(vert); } for (int i = 0; i < meshIndices.Length; i++) { morphedVertices[meshIndices[i]].Position = keyframe.PositionList[morphIndices[i]]; } var pairList = new List <Tuple <List <xxFace>, List <xxVertex> > >(1); pairList.Add(new Tuple <List <xxFace>, List <xxVertex> >(submesh.FaceList, morphedVertices)); xx.CalculateNormals(pairList, threshold); for (int i = 0; i < meshIndices.Length; i++) { keyframe.NormalList[morphIndices[i]] = morphedVertices[meshIndices[i]].Normal; } }
public void SetTweenFactor(xxFrame meshFrame, xaMorphIndexSet idxSet, float tweenFactor) { foreach (AnimationFrame frame in meshFrames) { if (frame.Name == meshFrame.Name) { xxMesh xxMesh = meshFrame.Mesh; int meshObjIdx = xa.MorphMeshObjIdx(idxSet.MeshIndices, xxMesh); if (meshObjIdx < 0) { Report.ReportLog("no valid mesh object was found for the morph"); return; } MeshContainer animMesh = frame.MeshContainer; for (int i = 1; i < meshObjIdx; i++) { animMesh = animMesh.NextMeshContainer; if (animMesh == null) { break; } } if (animMesh == null) { Report.ReportLog("Bad submesh specified."); return; } MorphMeshContainer morphMesh = (MorphMeshContainer)animMesh; morphMesh.TweenFactor = tweenFactor; return; } } Report.ReportLog("Mesh frame " + meshFrame + " not displayed."); return; }
public static xxMesh CreateMesh(WorkspaceMesh mesh, int xxFormat, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; materialNames = new string[numSubmeshes]; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; xxMesh xxMesh = new xxMesh(); xxMesh.BoneList = CreateBoneList(mesh.BoneList); xxMesh.SubmeshList = new List <xxSubmesh>(mesh.SubmeshList.Count); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } xxSubmesh xxSubmesh = new xxSubmesh(); xxMesh.SubmeshList.Add(xxSubmesh); xxSubmesh.MaterialIndex = -1; materialNames[i] = mesh.SubmeshList[submeshIdx].Material; indices[i] = mesh.SubmeshList[submeshIdx].Index; worldCoords[i] = mesh.SubmeshList[submeshIdx].WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(mesh.SubmeshList[submeshIdx]); List <ImportedVertex> vertexList = mesh.SubmeshList[submeshIdx].VertexList; List <xxVertex> xxVertexList = new List <xxVertex>(vertexList.Count); for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; xxVertex xxVertex; if (xxFormat >= 4) { xxVertex = new xxVertexUShort(); CreateUnknown(xxVertex); } else { xxVertex = new xxVertexInt(); } xxVertex.Index = j; xxVertex.Normal = vert.Normal; xxVertex.UV = (float[])vert.UV.Clone(); xxVertex.Weights3 = new float[3] { vert.Weights[0], vert.Weights[1], vert.Weights[2] }; xxVertex.BoneIndices = (byte[])vert.BoneIndices.Clone(); xxVertex.Position = vert.Position; xxVertexList.Add(xxVertex); } xxSubmesh.VertexList = xxVertexList; List <ImportedFace> faceList = mesh.SubmeshList[submeshIdx].FaceList; List <xxFace> xxFaceList = new List <xxFace>(faceList.Count); for (int j = 0; j < faceList.Count; j++) { int[] vertexIndices = faceList[j].VertexIndices; xxFace xxFace = new xxFace(); xxFace.VertexIndices = new ushort[3] { (ushort)vertexIndices[0], (ushort)vertexIndices[1], (ushort)vertexIndices[2] }; xxFaceList.Add(xxFace); } xxSubmesh.FaceList = xxFaceList; } xxMesh.VertexListDuplicate = CreateVertexListDup(xxMesh.SubmeshList); return(xxMesh); }
public static void ReplaceMesh(xxFrame frame, xxParser parser, WorkspaceMesh mesh, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod, bool targetFullMesh) { Matrix transform = Matrix.Identity; xxFrame transformFrame = frame; while (transformFrame != null) { transform = transformFrame.Matrix * transform; transformFrame = (xxFrame)transformFrame.Parent; } transform.Invert(); string[] materialNames; int[] indices; bool[] worldCoords; bool[] replaceSubmeshesOption; xxMesh xxMesh = CreateMesh(mesh, parser.Format, out materialNames, out indices, out worldCoords, out replaceSubmeshesOption); List <xxVertex> allVertices = null; if (frame.Mesh == null) { CreateUnknowns(xxMesh); } else { CopyUnknowns(frame.Mesh, xxMesh); if ((bonesMethod == CopyMeshMethod.CopyOrder) || (bonesMethod == CopyMeshMethod.CopyNear)) { xxMesh.BoneList = new List <xxBone>(frame.Mesh.BoneList.Count); for (int i = 0; i < frame.Mesh.BoneList.Count; i++) { xxMesh.BoneList.Add(frame.Mesh.BoneList[i].Clone()); } } if (targetFullMesh && (normalsMethod == CopyMeshMethod.CopyNear || bonesMethod == CopyMeshMethod.CopyNear)) { allVertices = new List <xxVertex>(); HashSet <Vector3> posSet = new HashSet <Vector3>(new VertexPositionComparer()); foreach (xxSubmesh submesh in frame.Mesh.SubmeshList) { allVertices.Capacity = allVertices.Count + submesh.VertexList.Count; foreach (xxVertex vertex in submesh.VertexList) { if (!posSet.Contains(vertex.Position)) { posSet.Add(vertex.Position); allVertices.Add(vertex); } } } } } xxSubmesh[] replaceSubmeshes = (frame.Mesh == null) ? null : new xxSubmesh[frame.Mesh.SubmeshList.Count]; List <xxSubmesh> addSubmeshes = new List <xxSubmesh>(xxMesh.SubmeshList.Count); for (int i = 0; i < xxMesh.SubmeshList.Count; i++) { for (int j = 0; j < parser.MaterialList.Count; j++) { if (parser.MaterialList[j].Name == materialNames[i]) { xxMesh.SubmeshList[i].MaterialIndex = j; break; } } xxSubmesh xxSubmesh = xxMesh.SubmeshList[i]; List <xxVertex> xxVertexList = xxSubmesh.VertexList; if (worldCoords[i]) { for (int j = 0; j < xxVertexList.Count; j++) { xxVertexList[j].Position = Vector3.TransformCoordinate(xxVertexList[j].Position, transform); } } xxSubmesh baseSubmesh = null; int idx = indices[i]; if ((frame.Mesh != null) && (idx >= 0) && (idx < frame.Mesh.SubmeshList.Count)) { baseSubmesh = frame.Mesh.SubmeshList[idx]; CopyUnknowns(baseSubmesh, xxSubmesh, parser.Format, xxMesh.NumVector2PerVertex); } else { CreateUnknowns(xxSubmesh, parser.Format, xxMesh.NumVector2PerVertex); } if (baseSubmesh != null) { if (normalsMethod == CopyMeshMethod.CopyOrder) { xx.CopyNormalsOrder(baseSubmesh.VertexList, xxSubmesh.VertexList); } else if (normalsMethod == CopyMeshMethod.CopyNear) { xx.CopyNormalsNear(targetFullMesh ? allVertices : baseSubmesh.VertexList, xxSubmesh.VertexList); } if (bonesMethod == CopyMeshMethod.CopyOrder) { xx.CopyBonesOrder(baseSubmesh.VertexList, xxSubmesh.VertexList); } else if (bonesMethod == CopyMeshMethod.CopyNear) { xx.CopyBonesNear(targetFullMesh ? allVertices : baseSubmesh.VertexList, xxSubmesh.VertexList); } } if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i]) { replaceSubmeshes[idx] = xxSubmesh; } else { addSubmeshes.Add(xxSubmesh); } } if ((frame.Mesh != null) && merge) { xxMesh.SubmeshList = new List <xxSubmesh>(replaceSubmeshes.Length + addSubmeshes.Count); List <xxSubmesh> copiedSubmeshes = new List <xxSubmesh>(replaceSubmeshes.Length); for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] == null) { xxSubmesh xxSubmesh = frame.Mesh.SubmeshList[i].Clone(); copiedSubmeshes.Add(xxSubmesh); xxMesh.SubmeshList.Add(xxSubmesh); } else { xxMesh.SubmeshList.Add(replaceSubmeshes[i]); } } xxMesh.SubmeshList.AddRange(addSubmeshes); if ((frame.Mesh.BoneList.Count == 0) && (xxMesh.BoneList.Count > 0)) { for (int i = 0; i < copiedSubmeshes.Count; i++) { List <xxVertex> vertexList = copiedSubmeshes[i].VertexList; for (int j = 0; j < vertexList.Count; j++) { vertexList[j].BoneIndices = new byte[4] { 0xFF, 0xFF, 0xFF, 0xFF }; } } } else if ((frame.Mesh.BoneList.Count > 0) && (xxMesh.BoneList.Count == 0)) { for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] != null) { List <xxVertex> vertexList = replaceSubmeshes[i].VertexList; for (int j = 0; j < vertexList.Count; j++) { vertexList[j].BoneIndices = new byte[4] { 0xFF, 0xFF, 0xFF, 0xFF }; } } } for (int i = 0; i < addSubmeshes.Count; i++) { List <xxVertex> vertexList = addSubmeshes[i].VertexList; for (int j = 0; j < vertexList.Count; j++) { vertexList[j].BoneIndices = new byte[4] { 0xFF, 0xFF, 0xFF, 0xFF }; } } } else if ((frame.Mesh.BoneList.Count > 0) && (xxMesh.BoneList.Count > 0)) { byte[] boneIdxMap; xxMesh.BoneList = MergeBoneList(frame.Mesh.BoneList, xxMesh.BoneList, out boneIdxMap); for (int i = 0; i < replaceSubmeshes.Length; i++) { if (replaceSubmeshes[i] != null) { List <xxVertex> vertexList = replaceSubmeshes[i].VertexList; for (int j = 0; j < vertexList.Count; j++) { byte[] boneIndices = vertexList[j].BoneIndices; vertexList[j].BoneIndices = new byte[4]; for (int k = 0; k < 4; k++) { vertexList[j].BoneIndices[k] = boneIndices[k] < 0xFF ? boneIdxMap[boneIndices[k]] : (byte)0xFF; } } } } for (int i = 0; i < addSubmeshes.Count; i++) { List <xxVertex> vertexList = addSubmeshes[i].VertexList; for (int j = 0; j < vertexList.Count; j++) { byte[] boneIndices = vertexList[j].BoneIndices; vertexList[j].BoneIndices = new byte[4]; for (int k = 0; k < 4; k++) { vertexList[j].BoneIndices[k] = boneIndices[k] < 0xFF ? boneIdxMap[boneIndices[k]] : (byte)0xFF; } } } } } if ((xxMesh.NumVector2PerVertex > 0) || ((frame.Mesh != null) && merge)) { xxMesh.VertexListDuplicate = CreateVertexListDup(xxMesh.SubmeshList); } frame.Mesh = xxMesh; SetBoundingBox(frame); }
public float SetMorphKeyframe(xxFrame meshFrame, xaMorphIndexSet idxSet, xaMorphKeyframe keyframe, bool asStart) { foreach (AnimationFrame frame in meshFrames) { if (frame.Name == meshFrame.Name) { xxMesh xxMesh = meshFrame.Mesh; int meshObjIdx = xa.MorphMeshObjIdx(idxSet.MeshIndices, xxMesh); if (meshObjIdx < 0) { Report.ReportLog("no valid mesh object was found for the morph"); return(-1f); } MorphMeshContainer morphMesh = null; AnimationMeshContainer animMesh = frame.MeshContainer as AnimationMeshContainer; if (animMesh != null) { for (int i = 1; i < meshObjIdx; i++) { animMesh = (AnimationMeshContainer)animMesh.NextMeshContainer; if (animMesh == null) { break; } } if (animMesh == null) { Report.ReportLog("Bad submesh specified."); return(-1f); } morphMesh = new MorphMeshContainer(); morphMesh.FaceCount = xxMesh.SubmeshList[meshObjIdx].FaceList.Count; morphMesh.IndexBuffer = animMesh.MeshData.Mesh.IndexBuffer; morphMesh.VertexCount = xxMesh.SubmeshList[meshObjIdx].VertexList.Count; List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList); morphMesh.StartBuffer = morphMesh.EndBuffer = vertBuffer; int vertBufferSize = morphMesh.VertexCount * Marshal.SizeOf(typeof(TweeningMeshesVertexBufferFormat.Stream2)); vertBuffer = new VertexBuffer(device, vertBufferSize, Usage.WriteOnly, VertexFormat.Texture1, Pool.Managed); using (DataStream vertexStream = vertBuffer.Lock(0, vertBufferSize, LockFlags.None)) { for (int i = 0; i < vertexList.Count; i++) { xxVertex vertex = vertexList[i]; vertexStream.Write(vertex.UV[0]); vertexStream.Write(vertex.UV[1]); } vertBuffer.Unlock(); } morphMesh.CommonBuffer = vertBuffer; morphMesh.MaterialIndex = animMesh.MaterialIndex; morphMesh.TextureIndex = animMesh.TextureIndex; morphMesh.NextMeshContainer = animMesh; frame.MeshContainer = morphMesh; morphMesh.TweenFactor = 0.0f; } else { morphMesh = frame.MeshContainer as MorphMeshContainer; List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList); if (asStart) { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.StartBuffer.Dispose(); } morphMesh.StartBuffer = vertBuffer; morphMesh.TweenFactor = 0.0f; } else { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.EndBuffer.Dispose(); } morphMesh.EndBuffer = vertBuffer; morphMesh.TweenFactor = 1.0f; } } return(morphMesh.TweenFactor); } } Report.ReportLog("Mesh frame " + meshFrame + " not displayed."); return(-1f); }
public float UnsetMorphKeyframe(xxFrame meshFrame, xaMorphIndexSet idxSet, bool asStart) { foreach (AnimationFrame frame in meshFrames) { if (frame.Name == meshFrame.Name) { xxMesh xxMesh = meshFrame.Mesh; int meshObjIdx = xa.MorphMeshObjIdx(idxSet.MeshIndices, xxMesh); if (meshObjIdx < 0) { Report.ReportLog("no valid mesh object was found for the morph"); return(-1f); } MeshContainer animMesh = frame.MeshContainer; for (int i = 1; i < meshObjIdx; i++) { animMesh = animMesh.NextMeshContainer; if (animMesh == null) { break; } } if (animMesh == null) { Report.ReportLog("Bad submesh specified."); return(-1f); } MorphMeshContainer morphMesh = (MorphMeshContainer)animMesh; if (asStart) { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.StartBuffer.Dispose(); morphMesh.StartBuffer = morphMesh.EndBuffer; } else { frame.MeshContainer = morphMesh.NextMeshContainer; } morphMesh.TweenFactor = 1.0f; } else { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.EndBuffer.Dispose(); morphMesh.EndBuffer = morphMesh.StartBuffer; } else { frame.MeshContainer = morphMesh.NextMeshContainer; } morphMesh.TweenFactor = 0.0f; } return(morphMesh.TweenFactor); } } Report.ReportLog("Mesh frame " + meshFrame + " not displayed."); return(-1f); }
public static void CopyUnknowns(xxMesh src, xxMesh dest) { dest.NumVector2PerVertex = src.NumVector2PerVertex; dest.VertexListDuplicateUnknown = (byte[])src.VertexListDuplicateUnknown.Clone(); }
private AnimationFrame CreateFrame(xxFrame frame, xxParser parser, HashSet <string> extractFrames, HashSet <string> meshNames, 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; xxMesh mesh = frame.Mesh; if (meshNames.Contains(frame.Name) && (mesh != null)) { List <xxBone> boneList = mesh.BoneList; string[] boneNames = new string[boneList.Count]; Matrix[] boneOffsets = new Matrix[boneList.Count]; for (int i = 0; i < boneList.Count; i++) { xxBone bone = boneList[i]; boneNames[i] = bone.Name; boneOffsets[i] = bone.Matrix; } AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.SubmeshList.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < mesh.SubmeshList.Count; i++) { xxSubmesh submesh = mesh.SubmeshList[i]; List <xxFace> faceList = submesh.FaceList; List <xxVertex> vertexList = submesh.VertexList; 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[2]); indexStream.Write(indices[1]); } animationMesh.UnlockIndexBuffer(); } FillVertexBuffer(animationMesh, vertexList, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { xxVertex vertex = vertexList[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(vertex.Position, vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.Position + (vertex.Normal / 16), vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb()); min = Vector3.Minimize(min, vertex.Position); max = Vector3.Maximize(max, vertex.Position); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; meshContainers[i] = meshContainer; int matIdx = submesh.MaterialIndex; if ((matIdx >= 0) && (matIdx < parser.MaterialList.Count)) { int texIdx; if (!MatTexIndices.TryGetValue(matIdx, out texIdx)) { texIdx = -1; xxMaterial mat = parser.MaterialList[matIdx]; Material materialD3D = new Material(); materialD3D.Ambient = mat.Ambient; materialD3D.Diffuse = mat.Diffuse; materialD3D.Emissive = mat.Emissive; materialD3D.Specular = mat.Specular; materialD3D.Power = mat.Power; Materials[matIdx] = materialD3D; xxMaterialTexture matTex = mat.Textures[0]; string matTexName = matTex.Name; if (matTexName != String.Empty) { for (int j = 0; j < parser.TextureList.Count; j++) { xxTexture tex = parser.TextureList[j]; if (tex.Name == matTexName) { texIdx = j; if (Textures[j] == null) { ImportedTexture importedTex = xx.ImportedTexture(tex); Textures[j] = Texture.FromMemory(device, importedTex.Data); } break; } } } MatTexIndices.Add(matIdx, texIdx); } meshContainer.MaterialIndex = matIdx; meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } for (int i = 0; i < meshContainers.Length; i++) { meshContainers[i].BoneNames = boneNames; meshContainers[i].BoneOffsets = boneOffsets; } 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++) { xxFrame child = frame[i]; if (extractFrames.Contains(child.Name)) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, meshNames, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return(animationFrame); }
public static bool IsSkinned(xxMesh mesh) { return(mesh.BoneList.Count > 0); }
private static List <xxTexture> Export(string dest, xxParser parser, List <xxFrame> meshParents, bool worldCoords) { List <xxTexture> usedTextures = new List <xxTexture>(parser.TextureList.Count); DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(dest)); if (!dir.Exists) { dir.Create(); } List <int> materialList = new List <int>(parser.MaterialList.Count); using (StreamWriter writer = new StreamWriter(dest, false)) { for (int i = 0; i < meshParents.Count; i++) { xxMesh meshListSome = meshParents[i].Mesh; for (int j = 0; j < meshListSome.SubmeshList.Count; j++) { xxSubmesh meshObj = meshListSome.SubmeshList[j]; int meshObjMatIdx = meshObj.MaterialIndex; if ((meshObjMatIdx >= 0) && (meshObjMatIdx < parser.MaterialList.Count)) { if (!materialList.Contains(meshObjMatIdx)) { materialList.Add(meshObjMatIdx); } } else { Report.ReportLog("Warning: Mesh " + meshParents[i].Name + " Object " + j + " has an invalid material"); } } } writer.WriteLine("Metasequoia Document"); writer.WriteLine("Format Text Ver 1.0"); writer.WriteLine(); writer.WriteLine("Material " + materialList.Count + " {"); foreach (int matIdx in materialList) { xxMaterial mat = parser.MaterialList[matIdx]; string s = "\t\"" + mat.Name + "\" col(0.800 0.800 0.800 1.000) dif(0.500) amb(0.100) emi(0.500) spc(0.100) power(30.00)"; string matTexName = mat.Textures[0].Name; if (matTexName != String.Empty) { s += " tex(\"" + Path.GetFileName(matTexName) + "\")"; } writer.WriteLine(s); } writer.WriteLine("}"); Random rand = new Random(); for (int i = 0; i < meshParents.Count; i++) { Matrix transform = Matrix.Identity; if (worldCoords) { xxFrame parent = meshParents[i]; while (parent != null) { transform = parent.Matrix * transform; parent = (xxFrame)parent.Parent; } } string meshName = meshParents[i].Name; xxMesh meshListSome = meshParents[i].Mesh; for (int j = 0; j < meshListSome.SubmeshList.Count; j++) { xxSubmesh meshObj = meshListSome.SubmeshList[j]; int meshObjMatIdx = meshObj.MaterialIndex; int mqoMatIdx = -1; if ((meshObjMatIdx >= 0) && (meshObjMatIdx < parser.MaterialList.Count)) { mqoMatIdx = materialList.IndexOf(meshObjMatIdx); } float[] color = new float[3]; for (int k = 0; k < color.Length; k++) { color[k] = (float)((rand.NextDouble() / 2) + 0.5); } string mqoName = meshName + "[" + j + "]"; if (worldCoords) { mqoName += "[W]"; } writer.WriteLine("Object \"" + mqoName + "\" {"); writer.WriteLine("\tshading 1"); writer.WriteLine("\tcolor " + color[0].ToFloatString() + " " + color[1].ToFloatString() + " " + color[2].ToFloatString()); writer.WriteLine("\tcolor_type 1"); List <ImportedVertex> vertList = xx.ImportedVertexList(meshObj.VertexList, xx.IsSkinned(meshListSome)); List <ImportedFace> faceList = xx.ImportedFaceList(meshObj.FaceList); if (worldCoords) { for (int k = 0; k < vertList.Count; k++) { vertList[k].Position = Vector3.TransformCoordinate(vertList[k].Position, transform); } } ExporterCommon.WriteMeshObject(writer, vertList, faceList, mqoMatIdx, null); writer.WriteLine("}"); } } writer.WriteLine("Eof"); } foreach (int matIdx in materialList) { xxMaterial mat = parser.MaterialList[matIdx]; xxMaterialTexture matTex = mat.Textures[0]; string matTexName = matTex.Name; if (matTexName != String.Empty) { for (int i = 0; i < parser.TextureList.Count; i++) { xxTexture tex = parser.TextureList[i]; string texName = tex.Name; if ((texName == matTexName) && !usedTextures.Contains(tex)) { usedTextures.Add(tex); break; } } } } return(usedTextures); }
protected xxFrame ParseFrame() { xxFrame frame = new xxFrame(); frame.Name = reader.ReadName(); int numChildFrames = reader.ReadInt32(); frame.InitChildren(numChildFrames); frame.Matrix = reader.ReadMatrix(); frame.Unknown1 = (Format >= 7) ? reader.ReadBytes(32) : reader.ReadBytes(16); int numSubmeshes = reader.ReadInt32(); frame.Bounds = new BoundingBox(reader.ReadVector3(), reader.ReadVector3()); frame.Unknown2 = (Format >= 7) ? reader.ReadBytes(64) : reader.ReadBytes(16); if (Format >= 6) { frame.Name2 = reader.ReadName(); } if (numSubmeshes > 0) { xxMesh mesh = new xxMesh(); frame.Mesh = mesh; mesh.NumVector2PerVertex = reader.ReadByte(); mesh.SubmeshList = new List <xxSubmesh>(numSubmeshes); for (int i = 0; i < numSubmeshes; i++) { xxSubmesh submesh = new xxSubmesh(); mesh.SubmeshList.Add(submesh); submesh.Unknown1 = (Format >= 7) ? reader.ReadBytes(64) : reader.ReadBytes(16); submesh.MaterialIndex = reader.ReadInt32(); submesh.FaceList = ParseFaceList(); submesh.VertexList = ParseVertexList(); if (Format >= 7) { submesh.Unknown2 = reader.ReadBytes(20); } if (mesh.NumVector2PerVertex > 0) { submesh.Vector2Lists = new List <List <Vector2> >(submesh.VertexList.Count); for (int j = 0; j < submesh.VertexList.Count; j++) { List <Vector2> vectorList = new List <Vector2>(mesh.NumVector2PerVertex); submesh.Vector2Lists.Add(vectorList); for (byte k = 0; k < mesh.NumVector2PerVertex; k++) { vectorList.Add(reader.ReadVector2()); } } } if (Format >= 2) { submesh.Unknown3 = reader.ReadBytes(100); // 96 + 4 } if (Format >= 7) { submesh.Unknown4 = reader.ReadBytes(284); // 256 + 28 if (Format >= 8) { byte format = reader.ReadByte(); string nullFrame = reader.ReadName(); byte[] u5end = reader.ReadBytes(12 + 4); byte[] encryptedName = Utility.EncryptName(nullFrame); submesh.Unknown5 = new byte[1 + 4 + encryptedName.Length + 12 + 4]; submesh.Unknown5[0] = format; BitConverter.GetBytes(encryptedName.Length).CopyTo(submesh.Unknown5, 1); encryptedName.CopyTo(submesh.Unknown5, 1 + 4); u5end.CopyTo(submesh.Unknown5, 1 + 4 + encryptedName.Length); } } else { if (Format >= 3) { submesh.Unknown4 = reader.ReadBytes(64); } if (Format >= 5) { submesh.Unknown5 = reader.ReadBytes(20); } if (Format >= 6) { submesh.Unknown6 = reader.ReadBytes(28); } } } ushort numVerticesDup = reader.ReadUInt16(); mesh.VertexListDuplicate = new List <xxVertex>(numVerticesDup); mesh.VertexListDuplicateUnknown = reader.ReadBytes(8); // 4 + 4 for (int i = 0; i < numVerticesDup; i++) { mesh.VertexListDuplicate.Add(ParseVertex()); } mesh.BoneList = ParseBoneList(); } for (int i = 0; i < numChildFrames; i++) { frame.AddChild(ParseFrame()); } return(frame); }