public bool CopyIntoSVI(xxFrame meshFrame, int submeshIdx, bool positions, bool bones, bool normals, bool uvs, bool unrestricted, bool nearestBones, bool nearestNormals, bool nearestUVs) { bool argPositions = positions, argBones = bones, argNormals = normals, argUVs = uvs; foreach (sviParser submeshSection in Parser.sections) { if (submeshSection.meshName == meshFrame.Name && submeshSection.submeshIdx == submeshIdx) { xxSubmesh submesh = meshFrame.Mesh.SubmeshList[submeshIdx]; int[] nearestVertexIndices = null; if (nearestBones || nearestNormals || nearestUVs) { if (submeshSection.positionsPresent == 1) { nearestVertexIndices = new int[submesh.VertexList.Count]; for (ushort i = 0; i < submesh.VertexList.Count; i++) { int bestIdx = -1; double nearestDist = Double.MaxValue; for (ushort j = 0; j < submeshSection.positions.Length; j++) { double distSquare = (submeshSection.positions[j].X - submesh.VertexList[i].Position.X) * (submeshSection.positions[j].X - submesh.VertexList[i].Position.X) + (submeshSection.positions[j].Y - submesh.VertexList[i].Position.Y) * (submeshSection.positions[j].Y - submesh.VertexList[i].Position.Y) + (submeshSection.positions[j].Z - submesh.VertexList[i].Position.Z) * (submeshSection.positions[j].Z - submesh.VertexList[i].Position.Z); if (distSquare < nearestDist) { bestIdx = j; nearestDist = distSquare; } } nearestVertexIndices[i] = bestIdx; } } else { Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has no positions in " + Parser.Name + "."); return(false); } } Vector3[] newNormals = submeshSection.normals; Vector2[] newUVs = submeshSection.uvs; byte[][] newBoneIndices = submeshSection.boneIndices; float[][] newBoneWeights3 = submeshSection.boneWeights3; if (submeshSection.indices.Length != submesh.VertexList.Count) { if (unrestricted) { submeshSection.indices = new ushort[submesh.VertexList.Count]; for (ushort i = 0; i < submeshSection.indices.Length; i++) { submeshSection.indices[i] = i; } if (submeshSection.positionsPresent == 1) { submeshSection.positions = new Vector3[submesh.VertexList.Count]; } if (submeshSection.bonesPresent == 1) { newBoneWeights3 = new float[submesh.VertexList.Count][]; newBoneIndices = new byte[submesh.VertexList.Count][]; } if (submeshSection.normalsPresent == 1) { newNormals = new Vector3[submesh.VertexList.Count]; } if (submeshSection.uvsPresent == 1) { newUVs = new Vector2[submesh.VertexList.Count]; } positions = bones = normals = uvs = true; } else { Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has a different number of vertices than defined in the sviex(" + submesh.VertexList.Count + "/" + submeshSection.indices.Length + ")."); return(false); } } if (positions && submeshSection.positionsPresent == 1) { for (ushort i = 0; i < submeshSection.positions.Length; i++) { submeshSection.positions[i] = submesh.VertexList[submeshSection.indices[i]].Position; } } if (bones && submeshSection.bonesPresent == 1) { if (nearestBones) { for (ushort i = 0; i < newBoneWeights3.Length; i++) { newBoneWeights3[i] = (float[])submeshSection.boneWeights3[nearestVertexIndices[submeshSection.indices[i]]].Clone(); newBoneIndices[i] = (byte[])submeshSection.boneIndices[nearestVertexIndices[submeshSection.indices[i]]].Clone(); } } else { for (ushort i = 0; i < newBoneWeights3.Length; i++) { newBoneWeights3[i] = (float[])submesh.VertexList[submeshSection.indices[i]].Weights3.Clone(); newBoneIndices[i] = (byte[])submesh.VertexList[submeshSection.indices[i]].BoneIndices.Clone(); } submeshSection.bones = new sviParser.sviBone[meshFrame.Mesh.BoneList.Count]; for (ushort i = 0; i < submeshSection.bones.Length; i++) { sviParser.sviBone bone = new sviParser.sviBone(); bone.name = (string)meshFrame.Mesh.BoneList[i].Name.Clone(); bone.boneIdx = meshFrame.Mesh.BoneList[i].Index; bone.matrix = meshFrame.Mesh.BoneList[i].Matrix; submeshSection.bones[i] = bone; } } submeshSection.boneWeights3 = newBoneWeights3; submeshSection.boneIndices = newBoneIndices; } if (normals && submeshSection.normalsPresent == 1) { if (nearestNormals) { for (ushort i = 0; i < submesh.VertexList.Count; i++) { newNormals[i] = submeshSection.normals[nearestVertexIndices[submeshSection.indices[i]]]; } } else { for (ushort i = 0; i < submesh.VertexList.Count; i++) { newNormals[i] = submesh.VertexList[submeshSection.indices[i]].Normal; } } submeshSection.normals = newNormals; } if (uvs && submeshSection.uvsPresent == 1) { if (nearestUVs) { for (ushort i = 0; i < submesh.VertexList.Count; i++) { newUVs[i] = submeshSection.uvs[nearestVertexIndices[submeshSection.indices[i]]]; } } else { for (ushort i = 0; i < submesh.VertexList.Count; i++) { float[] uv = submesh.VertexList[submeshSection.indices[i]].UV; newUVs[i] = new Vector2(uv[0], uv[1]); } } submeshSection.uvs = newUVs; } return(true); } } return(false); }
public bool CopyToSubmesh(xxFrame meshFrame, int submeshIdx, bool positions, bool bones, bool normals, bool uvs) { foreach (sviParser submeshSection in Parser.sections) { if (submeshSection.meshName == meshFrame.Name && submeshSection.submeshIdx == submeshIdx) { xxSubmesh submesh = meshFrame.Mesh.SubmeshList[submeshIdx]; if (submeshSection.indices.Length != submesh.VertexList.Count) { Report.ReportLog(meshFrame.Name + "[" + submeshIdx + "] has a different number of vertices than defined in the sviex(" + submesh.VertexList.Count + "/" + submeshSection.indices.Length + ")."); return(false); } if (positions && submeshSection.positionsPresent == 1) { for (ushort i = 0; i < submeshSection.positions.Length; i++) { submesh.VertexList[submeshSection.indices[i]].Position = submeshSection.positions[i]; } } if (bones && submeshSection.bonesPresent == 1) { for (ushort i = 0; i < submeshSection.boneWeights3.Length; i++) { submesh.VertexList[submeshSection.indices[i]].Weights3 = (float[])submeshSection.boneWeights3[i].Clone(); } for (ushort i = 0; i < submeshSection.boneIndices.Length; i++) { submesh.VertexList[submeshSection.indices[i]].BoneIndices = (byte[])submeshSection.boneIndices[i].Clone(); } meshFrame.Mesh.BoneList.Clear(); for (ushort i = 0; i < submeshSection.bones.Length; i++) { xxBone bone = new xxBone(); bone.Name = (string)submeshSection.bones[i].name.Clone(); bone.Index = submeshSection.bones[i].boneIdx; bone.Matrix = submeshSection.bones[i].matrix; meshFrame.Mesh.BoneList.Add(bone); } } if (normals && submeshSection.normalsPresent == 1) { for (ushort i = 0; i < submeshSection.normals.Length; i++) { submesh.VertexList[submeshSection.indices[i]].Normal = submeshSection.normals[i]; } } if (uvs && submeshSection.uvsPresent == 1) { for (ushort i = 0; i < submeshSection.uvs.Length; i++) { submesh.VertexList[submeshSection.indices[i]].UV = new float[2] { submeshSection.uvs[i].X, submeshSection.uvs[i].Y }; } } meshFrame.Mesh.VertexListDuplicate = xx.CreateVertexListDup(meshFrame.Mesh.SubmeshList); return(true); } } return(false); }
public void CopyNearestNormals(object[] srcMeshes, object[] srcSubmeshes, object[] dstMeshes, object[] dstSubmeshes, sviexParser dstParser, double nearVertexThreshold, bool nearestNormal, bool automatic) { xxFrame[] srcMeshArr = Utility.Convert <xxFrame>(srcMeshes); double[] srcSubmeshDoubleIndices = Utility.Convert <double>(srcSubmeshes); HashSet <xxSubmesh> srcSubmeshSet = new HashSet <xxSubmesh>(); int srcSubmeshIdxIdx = 0; int srcTotalSubmeshes = 0; foreach (xxFrame meshFrame in srcMeshArr) { int numSubmeshes = (int)srcSubmeshDoubleIndices[srcSubmeshIdxIdx++]; srcTotalSubmeshes += numSubmeshes; for (int i = 0; i < numSubmeshes; i++) { int srcSubmeshIdx = (int)srcSubmeshDoubleIndices[srcSubmeshIdxIdx++]; foreach (sviParser section in SortedParser.sections) { if (section.meshName == meshFrame.Name && section.submeshIdx == srcSubmeshIdx) { xxSubmesh submesh = meshFrame.Mesh.SubmeshList[srcSubmeshIdx]; srcSubmeshSet.Add(submesh); break; } } } } if (srcTotalSubmeshes != srcSubmeshSet.Count) { Report.ReportLog("Not all source submeshes exist in " + SortedParser.Name + ". Using only " + srcSubmeshSet.Count + "."); } xxFrame[] dstMeshArr = Utility.Convert <xxFrame>(dstMeshes); double[] dstSubmeshDoubleIndices = Utility.Convert <double>(dstSubmeshes); List <xxSubmesh> dstSubmeshList = new List <xxSubmesh>(); int dstSubmeshIdxIdx = 0; foreach (xxFrame meshFrame in dstMeshArr) { int numSubmeshes = (int)dstSubmeshDoubleIndices[dstSubmeshIdxIdx++]; if (numSubmeshes == -1) { dstSubmeshList.AddRange(meshFrame.Mesh.SubmeshList); } else { for (int i = 0; i < numSubmeshes; i++) { int dstSubmeshIdx = (int)dstSubmeshDoubleIndices[dstSubmeshIdxIdx++]; xxSubmesh submesh = meshFrame.Mesh.SubmeshList[dstSubmeshIdx]; dstSubmeshList.Add(submesh); } } } sviexParser newParser = new sviexParser(); foreach (xxFrame dstMeshFrame in dstMeshArr) { foreach (xxSubmesh dstSubmesh in dstMeshFrame.Mesh.SubmeshList) { if (!dstSubmeshList.Contains(dstSubmesh)) { continue; } if (progressBar != null) { progressBar.Maximum += dstSubmesh.VertexList.Count; } sviParser newSection = new sviParser(); newSection.meshName = dstMeshFrame.Name; newSection.submeshIdx = dstMeshFrame.Mesh.SubmeshList.IndexOf(dstSubmesh); newSection.indices = new ushort[dstSubmesh.VertexList.Count]; newSection.normalsPresent = 1; newSection.normals = new Vector3[dstSubmesh.VertexList.Count]; for (ushort i = 0; i < dstSubmesh.VertexList.Count; i++) { xxVertex dstVertex = dstSubmesh.VertexList[i]; if (automatic) { nearestNormal = false; for (int j = 0; j < dstSubmesh.VertexList.Count; j++) { if (j != i) { xxVertex vert = dstSubmesh.VertexList[j]; double distSquare = (vert.Position.X - dstVertex.Position.X) * (vert.Position.X - dstVertex.Position.X) + (vert.Position.Y - dstVertex.Position.Y) * (vert.Position.Y - dstVertex.Position.Y) + (vert.Position.Z - dstVertex.Position.Z) * (vert.Position.Z - dstVertex.Position.Z); if (distSquare <= nearVertexThreshold) { nearestNormal = true; break; } } } } Dictionary <xxFrame, Dictionary <xxSubmesh, List <int> > > bestFindings = new Dictionary <xxFrame, Dictionary <xxSubmesh, List <int> > >(); int totalFindings = 0; xxFrame bestMeshFrame = null; xxSubmesh bestSubmesh = null; int bestIdx = -1; double bestDist = double.MaxValue; foreach (xxFrame srcMeshFrame in srcMeshArr) { Dictionary <xxSubmesh, List <int> > bestSubmeshFindings = new Dictionary <xxSubmesh, List <int> >(); foreach (xxSubmesh srcSubmesh in srcMeshFrame.Mesh.SubmeshList) { if (!srcSubmeshSet.Contains(srcSubmesh)) { continue; } List <int> bestIndexFindings = new List <int>(srcSubmesh.VertexList.Count); for (int j = 0; j < srcSubmesh.VertexList.Count; j++) { xxVertex srcVertex = srcSubmesh.VertexList[j]; double distSquare = (srcVertex.Position.X - dstVertex.Position.X) * (srcVertex.Position.X - dstVertex.Position.X) + (srcVertex.Position.Y - dstVertex.Position.Y) * (srcVertex.Position.Y - dstVertex.Position.Y) + (srcVertex.Position.Z - dstVertex.Position.Z) * (srcVertex.Position.Z - dstVertex.Position.Z); if (distSquare <= nearVertexThreshold) { bestIndexFindings.Add(j); totalFindings++; continue; } if (totalFindings == 0 && distSquare < bestDist) { bestMeshFrame = srcMeshFrame; bestSubmesh = srcSubmesh; bestIdx = j; bestDist = distSquare; } } if (bestIndexFindings.Count > 0) { bestSubmeshFindings.Add(srcSubmesh, bestIndexFindings); } } if (bestSubmeshFindings.Count > 0) { bestFindings.Add(srcMeshFrame, bestSubmeshFindings); } } if (totalFindings > 0) { Vector3 normalSummed = new Vector3(); Vector3 normalNearest = new Vector3(); double nearestDist = Double.MaxValue; foreach (var finding in bestFindings) { foreach (sviParser srcSection in SortedParser.sections) { if (srcSection.meshName == finding.Key.Name) { foreach (var submeshFinding in finding.Value) { if (srcSection.submeshIdx == finding.Key.Mesh.SubmeshList.IndexOf(submeshFinding.Key)) { foreach (int j in submeshFinding.Value) { if (nearestNormal) { double distSquare = (srcSection.normals[j].X - dstVertex.Normal.X) * (srcSection.normals[j].X - dstVertex.Normal.X) + (srcSection.normals[j].Y - dstVertex.Normal.Y) * (srcSection.normals[j].Y - dstVertex.Normal.Y) + (srcSection.normals[j].Z - dstVertex.Normal.Z) * (srcSection.normals[j].Z - dstVertex.Normal.Z); if (distSquare < nearestDist) { normalNearest = srcSection.normals[j]; nearestDist = distSquare; } } else { normalSummed += srcSection.normals[j]; } } } } } } } if (totalFindings > 1) { normalSummed.Normalize(); } newSection.indices[i] = i; newSection.normals[i] = nearestNormal ? normalNearest : normalSummed; } else { int bestSubmeshIdx = bestMeshFrame.Mesh.SubmeshList.IndexOf(bestSubmesh); foreach (sviParser srcSection in SortedParser.sections) { if (srcSection.meshName == bestMeshFrame.Name && srcSection.submeshIdx == bestSubmeshIdx) { newSection.indices[i] = i; newSection.normals[i] = srcSection.normals[bestIdx]; break; } } } if (progressBar != null) { progressBar.PerformStep(); } } newParser.sections.Add(newSection); } } dstParser.sections = newParser.sections; }
private static void SwapNormals(ComboBoxItemXX cbItem, string sviexName) { Dictionary <xxVertex, Vector3> originalNormals = new Dictionary <xxVertex, Vector3>(); sviexParser targetParser = PluginsPPD.OpenSVIEX((ppParser)Gui.Scripting.Variables[cbItem.ppForm.ParserVar], sviexName); foreach (sviParser section in targetParser.sections) { bool meshFound = false; foreach (ComboBoxItemMesh itemMesh in cbItem.meshes) { if (section.meshName == itemMesh.meshFrame.Name) { meshFound = true; xxSubmesh submesh = itemMesh.meshFrame.Mesh.SubmeshList[section.submeshIdx]; if (section.indices.Length != submesh.VertexList.Count) { Report.ReportLog("Unmatching SVIEX mesh=" + section.meshName + " submeshIdx=" + section.submeshIdx + " has " + section.indices.Length + " indices."); break; } for (int i = 0; i < section.indices.Length; i++) { ushort vIdx = section.indices[i]; Vector3 norm = section.normals[i]; xxVertex vert = submesh.VertexList[vIdx]; originalNormals.Add(vert, vert.Normal); vert.Normal = norm; } break; } } if (!meshFound) { Report.ReportLog("SVIEX Normals not copied for " + section.meshName); } } cbItem.xxForm.RecreateRenderObjects(); foreach (sviParser section in targetParser.sections) { foreach (ComboBoxItemMesh itemMesh in cbItem.meshes) { if (section.meshName == itemMesh.meshFrame.Name) { xxSubmesh submesh = itemMesh.meshFrame.Mesh.SubmeshList[section.submeshIdx]; if (section.indices.Length != submesh.VertexList.Count) { break; } for (int i = 0; i < section.indices.Length; i++) { ushort vIdx = section.indices[i]; xxVertex vert = submesh.VertexList[vIdx]; Vector3 norm = originalNormals[vert]; vert.Normal = norm; } break; } } } }
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 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; }