public void RemoveMaterial(int id) { List <xxMaterial> materialList = Parser.MaterialList; int[] matIdxMap = new int[materialList.Count]; for (int i = 0; i < id; i++) { matIdxMap[i] = i; } matIdxMap[id] = -1; for (int i = id + 1; i < materialList.Count; i++) { matIdxMap[i] = i - 1; } for (int i = 0; i < Meshes.Count; i++) { List <xxSubmesh> submeshList = Meshes[i].Mesh.SubmeshList; for (int j = 0; j < submeshList.Count; j++) { xxSubmesh submesh = submeshList[j]; int matIdx = submesh.MaterialIndex; if ((matIdx >= 0) && (matIdx < materialList.Count)) { submesh.MaterialIndex = matIdxMap[submesh.MaterialIndex]; } } } Parser.MaterialList.RemoveAt(id); }
public void SetSubmeshMaterial(int meshId, int submeshId, int material) { xxSubmesh submesh = Meshes[meshId].Mesh.SubmeshList[submeshId]; submesh.MaterialIndex = material; Changed = true; }
public static List <xxVertex> CreateVertexListDup(List <xxSubmesh> submeshList) { List <xxVertex> vertListDup = new List <xxVertex>(UInt16.MaxValue); List <VertexCompare> vertCompareList = new List <VertexCompare>(UInt16.MaxValue); for (int i = 0; i < submeshList.Count; i++) { xxSubmesh meshObj = submeshList[i]; List <xxVertex> vertList = meshObj.VertexList; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; VertexCompare vertCompare = new VertexCompare(vertCompareList.Count, vert.Position, vert.Normal, vert.BoneIndices, vert.Weights3); int idx = vertCompareList.BinarySearch(vertCompare); if (idx < 0) { vertCompareList.Insert(~idx, vertCompare); vert.Index = vertCompareList.Count; vertListDup.Add(vert.Clone()); } else { vert.Index = vertCompareList[idx].index; } } } vertListDup.TrimExcess(); return(vertListDup); }
public void SetSubmeshUnknowns(int meshId, int submeshId, byte[] unknown1, byte[] unknown2, byte[] unknown3, byte[] unknown4, byte[] unknown5, byte[] unknown6) { xxSubmesh submesh = Meshes[meshId].Mesh.SubmeshList[submeshId]; submesh.Unknown1 = (byte[])unknown1.Clone(); if (Parser.Format >= 7) { submesh.Unknown2 = (byte[])unknown2.Clone(); } if (Parser.Format >= 2) { submesh.Unknown3 = (byte[])unknown3.Clone(); } if (Parser.Format >= 3) { submesh.Unknown4 = (byte[])unknown4.Clone(); } if (Parser.Format >= 5) { submesh.Unknown5 = (byte[])unknown5.Clone(); } if (Parser.Format == 6) { submesh.Unknown6 = (byte[])unknown6.Clone(); } }
public static void CreateUnknowns(xxSubmesh submesh, int xxFormat, byte numVector2PerVertex) { List <xxVertex> vertList = submesh.VertexList; submesh.Unknown1 = (xxFormat >= 7) ? new byte[64] : new byte[] { 0x0C, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; if (numVector2PerVertex > 0) { submesh.Vector2Lists = new List <List <Vector2> >(vertList.Count); for (int j = 0; j < vertList.Count; j++) { List <Vector2> vectorList = new List <Vector2>(numVector2PerVertex); submesh.Vector2Lists.Add(vectorList); for (byte k = 0; k < numVector2PerVertex; k++) { vectorList.Add(new Vector2()); } } } if (xxFormat >= 2) { submesh.Unknown3 = new byte[100]; } if (xxFormat >= 7) { submesh.Unknown2 = new byte[20]; submesh.Unknown4 = new byte[284]; if (xxFormat >= 8) { submesh.Unknown5 = new byte[21]; } } else { if (xxFormat >= 3) { submesh.Unknown4 = new byte[64]; } if (xxFormat >= 5) { submesh.Unknown5 = new byte[20]; } if (xxFormat >= 6) { submesh.Unknown6 = new byte[28]; } } if (xxFormat >= 4) { for (int j = 0; j < vertList.Count; j++) { vertList[j].Unknown1 = new byte[20]; } } }
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; }
private void InitTables() { xxTable.Rows.Add(new object[] { 0, "Header", Utility.BytesToString(parser.Header) }); xxTable.Rows.Add(new object[] { 1, "MaterialSection", Utility.BytesToString(parser.MaterialSectionUnknown) }); if (parser.Format >= 2) { xxTable.Rows.Add(new object[] { 2, "Footer", Utility.BytesToString(parser.Footer) }); // 3 } for (int i = 0; i < editor.Frames.Count; i++) { xxFrame frame = editor.Frames[i]; frameTable.Rows.Add(new object[] { i, frame.Name, Utility.BytesToString(frame.Unknown1), Utility.BytesToString(frame.Unknown2) }); } for (int i = 0; i < editor.Meshes.Count; i++) { xxFrame frame = editor.Meshes[i]; meshTable.Rows.Add(new object[] { i, frame.Name, frame.Mesh.NumVector2PerVertex.ToString("X2"), Utility.BytesToString(frame.Mesh.VertexListDuplicateUnknown) }); for (int j = 0; j < frame.Mesh.SubmeshList.Count; j++) { xxSubmesh submesh = frame.Mesh.SubmeshList[j]; submeshTable.Rows.Add(new object[] { new int[] { i, j }, frame.Name + "[" + j + "]", Utility.BytesToString(submesh.Unknown1), Utility.BytesToString(submesh.Unknown2), Utility.BytesToString(submesh.Unknown3), Utility.BytesToString(submesh.Unknown4), Utility.BytesToString(submesh.Unknown5), Utility.BytesToString(submesh.Unknown6) }); } } for (int i = 0; i < parser.MaterialList.Count; i++) { xxMaterial mat = parser.MaterialList[i]; materialTable.Rows.Add(new object[] { i, mat.Name, Utility.BytesToString(mat.Unknown1), Utility.BytesToString(mat.Textures[0].Unknown1), Utility.BytesToString(mat.Textures[1].Unknown1), Utility.BytesToString(mat.Textures[2].Unknown1), Utility.BytesToString(mat.Textures[3].Unknown1) }); } for (int i = 0; i < parser.TextureList.Count; i++) { xxTexture tex = parser.TextureList[i]; textureTable.Rows.Add(new object[] { i, tex.Name, Utility.BytesToString(tex.Unknown1) }); } }
public xxSubmesh Clone() { xxSubmesh submesh = new xxSubmesh(); submesh.Unknown1 = (byte[])Unknown1.Clone(); submesh.MaterialIndex = MaterialIndex; submesh.FaceList = new List <xxFace>(FaceList.Count); for (int i = 0; i < FaceList.Count; i++) { submesh.FaceList.Add(FaceList[i].Clone()); } submesh.VertexList = new List <xxVertex>(VertexList.Count); for (int i = 0; i < VertexList.Count; i++) { submesh.VertexList.Add(VertexList[i].Clone()); } submesh.Unknown2 = Unknown2.CloneIfNotNull(); if (Vector2Lists != null) { submesh.Vector2Lists = new List <List <Vector2> >(Vector2Lists.Count); for (int i = 0; i < Vector2Lists.Count; i++) { List <Vector2> vectorList = new List <Vector2>(Vector2Lists[i].Count); submesh.Vector2Lists.Add(vectorList); for (int j = 0; j < Vector2Lists[i].Count; j++) { vectorList.Add(Vector2Lists[i][j]); } } } submesh.Unknown3 = Unknown3.CloneIfNotNull(); submesh.Unknown4 = Unknown4.CloneIfNotNull(); submesh.Unknown5 = Unknown5.CloneIfNotNull(); submesh.Unknown6 = Unknown6.CloneIfNotNull(); return(submesh); }
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; } }
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); }
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); }
public static void ConvertFormat(xxFrame frame, int srcFormat, int destFormat) { if ((srcFormat < 7) && (destFormat >= 7)) { byte[] unknown1 = frame.Unknown1; frame.Unknown1 = new byte[32]; Array.Copy(unknown1, frame.Unknown1, unknown1.Length); byte[] unknown2 = frame.Unknown2; frame.Unknown2 = new byte[64]; Array.Copy(unknown2, frame.Unknown2, unknown2.Length); } else if ((srcFormat >= 7) && (destFormat < 7)) { byte[] unknown1 = frame.Unknown1; frame.Unknown1 = new byte[16]; Array.Copy(unknown1, frame.Unknown1, frame.Unknown1.Length); byte[] unknown2 = frame.Unknown2; frame.Unknown2 = new byte[16]; Array.Copy(unknown2, frame.Unknown2, frame.Unknown2.Length); } if ((srcFormat < 6) && (destFormat >= 6)) { frame.Name2 = String.Empty; } else if ((srcFormat >= 6) && (destFormat < 6)) { frame.Name2 = null; } if (frame.Mesh != null) { for (int i = 0; i < frame.Mesh.SubmeshList.Count; i++) { xxSubmesh submesh = frame.Mesh.SubmeshList[i]; if ((srcFormat < 7) && (destFormat >= 7)) { byte[] unknown1 = submesh.Unknown1; submesh.Unknown1 = new byte[64]; Array.Copy(unknown1, submesh.Unknown1, unknown1.Length); submesh.Unknown2 = new byte[20]; } else if ((srcFormat >= 7) && (destFormat < 7)) { byte[] unknown1 = submesh.Unknown1; submesh.Unknown1 = new byte[16]; Array.Copy(unknown1, submesh.Unknown1, submesh.Unknown1.Length); submesh.Unknown2 = null; } if ((srcFormat < 2) && (destFormat >= 2)) { submesh.Unknown3 = new byte[100]; } else if ((srcFormat >= 2) && (destFormat < 2)) { submesh.Unknown3 = null; } if ((srcFormat < 3) && ((destFormat >= 3) && (destFormat < 7))) { submesh.Unknown4 = new byte[64]; } else if ((srcFormat < 3) && (destFormat >= 7)) { submesh.Unknown4 = new byte[284]; } else if (((srcFormat >= 3) && (srcFormat < 7)) && (destFormat < 3)) { submesh.Unknown4 = null; } else if (((srcFormat >= 3) && (srcFormat < 7)) && (destFormat >= 7)) { byte[] unknown4 = submesh.Unknown4; submesh.Unknown4 = new byte[284]; Array.Copy(unknown4, submesh.Unknown4, unknown4.Length); } else if ((srcFormat >= 7) && (destFormat < 3)) { submesh.Unknown4 = null; } else if ((srcFormat >= 7) && ((destFormat >= 3) && (destFormat < 7))) { byte[] unknown4 = submesh.Unknown4; submesh.Unknown4 = new byte[64]; Array.Copy(unknown4, submesh.Unknown4, submesh.Unknown4.Length); } if ((srcFormat < 5) && ((destFormat >= 5) && (destFormat < 8))) { submesh.Unknown5 = new byte[20]; } else if ((srcFormat < 5) && (destFormat >= 8)) { submesh.Unknown5 = new byte[21]; } else if (((srcFormat >= 5) && (srcFormat < 8)) && (destFormat < 5)) { submesh.Unknown5 = null; } else if (((srcFormat >= 5) && (srcFormat < 8)) && (destFormat >= 8)) { byte[] unknown5 = submesh.Unknown5; submesh.Unknown5 = new byte[21]; Array.Copy(unknown5, submesh.Unknown5, unknown5.Length); } else if ((srcFormat >= 8) && (destFormat < 5)) { submesh.Unknown5 = null; } else if ((srcFormat >= 8) && ((destFormat >= 5) && (destFormat < 8))) { byte[] unknown5 = submesh.Unknown5; submesh.Unknown5 = new byte[20]; Array.Copy(unknown5, submesh.Unknown5, submesh.Unknown5.Length); } if ((srcFormat == 6) && (destFormat != 6)) { submesh.Unknown6 = null; } else if ((srcFormat != 6) && (destFormat == 6)) { submesh.Unknown6 = new byte[28]; } ConvertFormat(submesh.VertexList, srcFormat, destFormat); } ConvertFormat(frame.Mesh.VertexListDuplicate, srcFormat, destFormat); } for (int i = 0; i < frame.Count; i++) { ConvertFormat(frame[i], srcFormat, destFormat); } }
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 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 CopyUnknowns(xxSubmesh src, xxSubmesh dest, int xxFormat, byte xxMeshNumUnknownA) { List <xxVertex> srcVertexList = src.VertexList; List <xxVertex> destVertexList = dest.VertexList; dest.Unknown1 = (byte[])src.Unknown1.Clone(); if (xxFormat >= 7) { dest.Unknown2 = (byte[])src.Unknown2.Clone(); } if (xxMeshNumUnknownA > 0) { dest.Vector2Lists = new List <List <Vector2> >(destVertexList.Count); for (int j = 0; (j < destVertexList.Count) && (j < srcVertexList.Count); j++) { List <Vector2> vectorList = new List <Vector2>(xxMeshNumUnknownA); dest.Vector2Lists.Add(vectorList); for (byte k = 0; k < xxMeshNumUnknownA; k++) { vectorList.Add(src.Vector2Lists[j][k]); } } for (int j = srcVertexList.Count; j < destVertexList.Count; j++) { List <Vector2> vectorList = new List <Vector2>(xxMeshNumUnknownA); dest.Vector2Lists.Add(vectorList); for (byte k = 0; k < xxMeshNumUnknownA; k++) { vectorList.Add(new Vector2()); } } } if (xxFormat >= 2) { dest.Unknown3 = (byte[])src.Unknown3.Clone(); } if (xxFormat >= 7) { dest.Unknown4 = (byte[])src.Unknown4.Clone(); if (xxFormat >= 7) { dest.Unknown5 = (byte[])src.Unknown5.Clone(); } } else { if (xxFormat >= 3) { dest.Unknown4 = (byte[])src.Unknown4.Clone(); } if (xxFormat >= 5) { dest.Unknown5 = (byte[])src.Unknown5.Clone(); } if (xxFormat >= 6) { dest.Unknown6 = (byte[])src.Unknown6.Clone(); } } if (xxFormat >= 4) { for (int j = 0; j < destVertexList.Count; j++) { if (j < srcVertexList.Count) { destVertexList[j].Unknown1 = (byte[])srcVertexList[j].Unknown1.Clone(); } else { destVertexList[j].Unknown1 = new byte[20]; } } } }