private void CopyMaterialSettings(PMXMaterial baseMat, PMXMaterial newMat) { newMat.Alpha = baseMat.Alpha; newMat.Ambient = baseMat.Ambient; newMat.Comment = baseMat.Comment; newMat.Diffuse = baseMat.Diffuse; newMat.DiffuseTexture = baseMat.DiffuseTexture; newMat.DoubleSided = baseMat.DoubleSided; newMat.EdgeColor = baseMat.EdgeColor; newMat.EdgeEnabled = baseMat.EdgeEnabled; newMat.EdgeSize = baseMat.EdgeSize; newMat.GroundShadow = baseMat.GroundShadow; newMat.GroundShadowType = baseMat.GroundShadowType; newMat.NameEN = baseMat.NameEN; newMat.NameJP = baseMat.NameJP; newMat.NonStandardToonTexture = baseMat.NonStandardToonTexture; newMat.SelfShadow = baseMat.SelfShadow; newMat.SelfShadowPlus = baseMat.SelfShadowPlus; newMat.Specular = baseMat.Specular; newMat.SphereMode = baseMat.SphereMode; newMat.SphereTexture = baseMat.SphereTexture; newMat.StandardToon = baseMat.StandardToon; newMat.StandardToonIndex = baseMat.StandardToonIndex; newMat.VertexColor = baseMat.VertexColor; //Triangles are not being copied! }
private void ImportTrianglesToMaterial(PMXMaterial mat, int triCount, int triType) { for (int i = 0; i < triCount; i++) { PMXVertex vtx1 = null, vtx2 = null, vtx3 = null; if (triType == 0x05) { vtx1 = pmxModel.Vertices[(int)sp.ReadU16()]; vtx2 = pmxModel.Vertices[(int)sp.ReadU16()]; vtx3 = pmxModel.Vertices[(int)sp.ReadU16()]; } else { vtx1 = pmxModel.Vertices[sp.ReadS32()]; vtx2 = pmxModel.Vertices[sp.ReadS32()]; vtx3 = pmxModel.Vertices[sp.ReadS32()]; } PMXTriangle tri = new PMXTriangle(pmxModel, vtx1, vtx2, vtx3); mat.Triangles.Add(tri); } }
private List <PMXMaterial> SplitTriangles(PMXMaterial mat) { int[] matIndex = new int[mat.Triangles.Count]; int i, j, mI; int addedTriangles; for (i = 0; i < matIndex.Length; i++) { matIndex[i] = -1; } mI = -1; int outInfo = 0; HashSet <TriangleEdge> edgesInPart; for (i = 0; i < matIndex.Length; i++) { int cIndex = matIndex[i]; if (cIndex >= 0) { continue; } if (i >= outInfo) { Console.WriteLine(i + " / " + matIndex.Length); while (i >= outInfo) { outInfo += 250; } } mI++; matIndex[i] = mI; edgesInPart = new HashSet <TriangleEdge>(); AddEdgesToList(GetEdges(mat.Triangles[i]), edgesInPart); do { addedTriangles = 0; for (j = i + 1; j < matIndex.Length; j++) { if (matIndex[j] >= 0) { continue; } PMXTriangle tri = mat.Triangles[j]; if (IsTriangleConnected(tri, edgesInPart)) { matIndex[j] = mI; addedTriangles++; } } } while (addedTriangles > 0); } List <PMXTriangle>[] triangleGroups = new List <PMXTriangle> [mI + 1]; for (i = 0; i <= mI; i++) { triangleGroups[i] = new List <PMXTriangle>(); } for (i = 0; i < matIndex.Length; i++) { PMXTriangle tri = mat.Triangles[i]; triangleGroups[matIndex[i]].Add(tri); } PMXMaterial restMaterial = new PMXMaterial(this._model); CopyMaterialSettings(mat, restMaterial); List <PMXMaterial> newMaterials = new List <PMXMaterial>(); int resIndex = 0; foreach (List <PMXTriangle> triangleGroup in triangleGroups) { if (triangleGroup.Count < 10 && this._ignoreSmallParts) { restMaterial.Triangles.AddRange(triangleGroup); continue; } resIndex++; PMXMaterial nm = new PMXMaterial(this._model); CopyMaterialSettings(mat, nm); nm.NameEN = nm.NameEN + " " + resIndex.ToString(); nm.NameJP = nm.NameJP + " " + resIndex.ToString(); nm.Triangles.AddRange(triangleGroup); newMaterials.Add(nm); } if (restMaterial.Triangles.Count > 0) { restMaterial.NameEN = restMaterial.NameEN + " Rest"; restMaterial.NameJP = restMaterial.NameJP + " Rest"; newMaterials.Add(restMaterial); } return(newMaterials); }
private ISMModel(string filename) { FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); sp = new StreamParser(fs, Endian.Little); pmxModel = new PMXModel(); sp.BaseStream.Seek(0x00, SeekOrigin.Begin); if (sp.ReadU32() != 0x324D5349) { fs.Close(); return; } sp.BaseStream.Seek(0x14, SeekOrigin.Begin); uint endianCheck = sp.ReadU32(); if (endianCheck > 0 && endianCheck < 65535) { sp.Endian = Endian.Little; } else { sp.Endian = Endian.Big; } sp.BaseStream.Seek(0x04, SeekOrigin.Begin); versionA = sp.ReadU8(); byte VersionB = sp.ReadU8(); byte VersionC = sp.ReadU8(); byte VersionD = sp.ReadU8(); uint header3 = sp.ReadU32(); uint header4 = sp.ReadU32(); uint filesize = sp.ReadU32(); uint sectionCount = sp.ReadU32(); uint header7 = sp.ReadU32(); uint header8 = sp.ReadU32(); int i, j, k; SectionData[] SectionArray = new SectionData[sectionCount]; for (i = 0; i < sectionCount; i++) { SectionArray[i] = new SectionData() { SectionType = sp.ReadU32(), SectionOffset = sp.ReadU32() }; } /** * Importing strings begin */ foreach (SectionData sd in SectionArray) { if (sd.SectionType == 33) //String array needs to be filled first { sp.BaseStream.Seek(sd.SectionOffset + 8, SeekOrigin.Begin); int stringCount = sp.ReadS32(); stringArray = new string[stringCount]; uint[] strOffsets = new uint[stringCount]; for (i = 0; i < stringCount; i++) { strOffsets[i] = sp.ReadU32(); } for (i = 0; i < stringCount; i++) { sp.BaseStream.Seek(strOffsets[i], SeekOrigin.Begin); stringArray[i] = sp.ReadAnsiNullTerminatedString(); } } } /** * Importing strings end */ /** * Materials */ foreach (SectionData sd in SectionArray) { if (sd.SectionType == 97) { sp.BaseStream.Seek(sd.SectionOffset + 8, SeekOrigin.Begin); int matTotal = sp.ReadS32(); uint[] matOffsetArray = new uint[matTotal]; for (i = 0; i < matTotal; i++) { matOffsetArray[i] = sp.ReadU32(); } for (i = 0; i < matTotal; i++) { sp.BaseStream.Seek(matOffsetArray[i] + 8, SeekOrigin.Begin); int matSubTotal = sp.ReadS32(); string matSubString1 = stringArray[sp.ReadS32()]; string matSubString2 = stringArray[sp.ReadS32()]; string matSubString3 = stringArray[sp.ReadS32()]; sp.BaseStream.Seek(4, SeekOrigin.Current); PMXMaterial mat = new PMXMaterial(pmxModel); pmxModel.Materials.Add(mat); mat.NameEN = matSubString1; mat.NameJP = matSubString1; mat.Diffuse = new PMXColorRGB(0.77f, 0.77f, 0.77f); mat.Specular = new PMXColorRGB(0.0f, 0.0f, 0.0f); mat.Ambient = new PMXColorRGB(1.0f, 1.0f, 1.0f); mat.StandardToonIndex = 3; mat.EdgeEnabled = false; if (matSubTotal > 0) { int matSubOffset = sp.ReadS32(); sp.BaseStream.Seek(matSubOffset + 12, SeekOrigin.Begin); matSubOffset = sp.ReadS32(); sp.BaseStream.Seek(matSubOffset + 20, SeekOrigin.Begin); matSubOffset = sp.ReadS32(); sp.BaseStream.Seek(matSubOffset + 24, SeekOrigin.Begin); matSubOffset = sp.ReadS32(); sp.BaseStream.Seek(matSubOffset + 24, SeekOrigin.Begin); matSubOffset = sp.ReadS32(); sp.BaseStream.Seek(matSubOffset, SeekOrigin.Begin); mat.DiffuseTexture = stringArray[sp.ReadS32()] + ".dds"; } else { mat.DiffuseTexture = "tex_c.dds"; } //Console.WriteLine(texturename); } } } /** * Bones and material groups */ foreach (SectionData sd in SectionArray) { if (sd.SectionType == 03) { Console.WriteLine("Object data"); sp.BaseStream.Seek(sd.SectionOffset + 8, SeekOrigin.Begin); int boneCount = sp.ReadS32(); uint[] boneOffsets = new uint[boneCount]; string boneDataString1 = stringArray[sp.ReadS32()]; string boneDataString2 = stringArray[sp.ReadS32()]; for (i = 0; i < boneCount; i++) { boneOffsets[i] = sp.ReadU32(); } for (i = 0; i < boneCount; i++) { sp.BaseStream.Seek(boneOffsets[i] + 8, SeekOrigin.Begin); /*uint sectionType = sp.ReadU32(); * sp.ReadU32();*/ int boneHeaderTotal = sp.ReadS32(); string boneName1 = stringArray[sp.ReadS32()]; string boneName2 = stringArray[sp.ReadS32()]; sp.BaseStream.Seek(8, SeekOrigin.Current); uint boneParentOffset = sp.ReadU32(); int boneParent = -1; for (j = 0; j < boneCount; j++) { if (boneOffsets[j] == boneParentOffset) { boneParent = j; } } sp.BaseStream.Seek(12, SeekOrigin.Current); int boneIdNum = sp.ReadS32(); sp.BaseStream.Seek(16, SeekOrigin.Current); uint[] boneHeaderOffsets = new uint[boneHeaderTotal]; for (j = 0; j < boneHeaderTotal; j++) { boneHeaderOffsets[j] = sp.ReadU32(); } for (j = 0; j < boneHeaderTotal; j++) { sp.BaseStream.Seek(boneHeaderOffsets[j], SeekOrigin.Begin); uint sectionType = sp.ReadU32(); if (sectionType == 76) { ImportSurface(); } if (sectionType == 91) { ImportBone(boneName1, i, boneParent, boneIdNum); } } } } } /** * Importing textures begin */ /*foreach (SectionData sd in SectionArray) * { * if (sd.SectionType == 46) * { * sp.BaseStream.Seek(sd.SectionOffset + 8, SeekOrigin.Begin); * int texTotal = sp.ReadS32(); * uint[] texOffsetArray = new uint[texTotal]; * for (i = 0; i < texTotal; i++) * { * texOffsetArray[i] = sp.ReadU32(); * } * * for (i = 0; i < texTotal; i++) * { * sp.BaseStream.Seek(texOffsetArray[i] + 12, SeekOrigin.Begin); * string texturename = stringArray[sp.ReadS32()]; * sp.BaseStream.Seek(12, SeekOrigin.Current); * //Console.WriteLine(texturename); * } * } * }*/ //TODO: Not sure what these do /** * Importing strings end */ /** * Vertices */ foreach (SectionData sd in SectionArray) { if (sd.SectionType == 11) { Console.WriteLine("Vertex data"); sp.BaseStream.Seek(sd.SectionOffset + 8, SeekOrigin.Begin); int vtxHeaderTotal = sp.ReadS32(); uint[] vtxHeadOffsets = new uint[vtxHeaderTotal]; for (i = 0; i < vtxHeaderTotal; i++) { vtxHeadOffsets[i] = sp.ReadU32(); } for (i = 0; i < vtxHeaderTotal; i++) { sp.BaseStream.Seek(vtxHeadOffsets[i], SeekOrigin.Begin); uint sectionType = sp.ReadU32(); if (sectionType == 10) { ImportVertexGroup(); } } } } fs.Close(); }
private void loadMeshs() { int i, j, k, l, m; int vtxIndex = 0; for (i = 0; i < this.mdlInfo.Count7; i++) { long vtxBase = this.vertBase + this.meshInfoList[i].vtxBufferStart; long idxBase = this.faceBase + this.meshInfoList[i].idxBufferStart; uint vtxStride = this.meshInfoList[i].vtxStride; //Console.WriteLine(vtxStride); uint matBase = this.meshInfoList[i].meshId; FvfInfo[] fvfInfo = this.fvfList[i]; this.fs.Seek(this.boneMapStart + this.meshInfoList[i].bonePalletStart * 2, SeekOrigin.Begin); List <ushort> bonePallet = new List <ushort>(); for (j = 0; j < this.meshInfoList[i].bonePalletCount; j++) { bonePallet.Add(br.ReadUInt16()); } for (j = 0; j < this.meshInfoList[i].meshCount; j++) { PMXMaterial mat = new PMXMaterial(this.pmx); mat.Diffuse.R = 0.77f; mat.Diffuse.G = 0.77f; mat.Diffuse.B = 0.77f; mat.Specular.R = 0.0f; mat.Specular.G = 0.0f; mat.Specular.B = 0.0f; mat.Ambient.R = 0.5f; mat.Ambient.G = 0.5f; mat.Ambient.B = 0.5f; mat.EdgeEnabled = false; mat.EdgeSize = 0.0f; mat.StandardToonIndex = 3; string meshname = this.matInfoList[i].MeshName; if (this.matNames != null && matNames.Count > 0) { meshname = this.matNames[(int)this.meshInfoList[i].matID] + "_" + i.ToString() + "_" + j.ToString(); } mat.NameJP = meshname; mat.NameEN = meshname; MaterialInfo matInfo = this.matInfoList[(int)(matBase + j)]; if (matInfo.Lod != 1 && matInfo.Lod != -1) { continue; } this.fs.Seek(idxBase, SeekOrigin.Begin); List <int> idxTmp = new List <int>(); for (l = 0; l < matInfo.FaceCount; l++) { if (meshInfoList[i].idxType == 2) { idxTmp.Add((int)(this.br.ReadUInt32() - matInfo.FaceStart)); } else { idxTmp.Add((int)(this.br.ReadUInt16() - matInfo.FaceStart)); } } idxBase = this.fs.Position; this.fs.Seek(vtxBase + vtxStride * matInfo.FaceStart, SeekOrigin.Begin); long vtxPosition = this.fs.Position; List <PMXVertex> vertices = new List <PMXVertex>(); for (k = 0; k < matInfo.VertCount; k++) { PMXVertex vtx = new PMXVertex(this.pmx); byte[] idx = new byte[4] { 0, 0, 0, 0 }; byte[] wgt = new byte[4] { 0, 0, 0, 0 }; for (l = 0; l < fvfInfo.Length; l++) { this.fs.Seek(vtxPosition + k * vtxStride + fvfInfo[l].fvfPos, SeekOrigin.Begin); switch (fvfInfo[l].compType) { case 0: vtx.Position.X = this.br.ReadSingle() * SCALE; vtx.Position.Y = this.br.ReadSingle() * SCALE; vtx.Position.Z = this.br.ReadSingle() * SCALE * (-1); break; case 2: vtx.Normals.X = this.br.ReadSingle(); vtx.Normals.Y = this.br.ReadSingle(); vtx.Normals.Z = this.br.ReadSingle() * (-1); break; case 8: vtx.UV.U = this.br.ReadSingle(); vtx.UV.V = this.br.ReadSingle(); break; case 7: for (m = 0; m < 4; m++) { idx[m] = this.br.ReadByte(); } break; case 1: for (m = 0; m < 4; m++) { wgt[m] = this.br.ReadByte(); } break; } } int totalWeight = 0; Dictionary <ushort, int> weights = new Dictionary <ushort, int>(); for (m = 0; m < 4; m++) { byte bi = idx[m]; if (bi >= bonePallet.Count) { continue; } ushort bni = bonePallet[bi]; int weight = 0; if (weights.ContainsKey(bni)) { weight = weights[bni]; } byte cw = wgt[m]; totalWeight += cw; weight += cw; weights[bni] = weight; } if (weights.Count == 1) { PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[weights.Keys.First()]; vtx.Deform = b1; } else { List <KeyValuePair <ushort, int> > weightList = weights.ToList(); weightList.Sort(delegate(KeyValuePair <ushort, int> pair1, KeyValuePair <ushort, int> pair2) { return(pair2.Value.CompareTo(pair1.Value)); }); for (m = 3; m >= 1; m--) { if (weightList.Count > m && weightList[m].Value == 0) { weightList.RemoveAt(m); } } if (weightList.Count == 1) { PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[weightList[0].Key]; vtx.Deform = b1; } else if (weightList.Count == 2) { PMXVertexDeformBDEF2 b2 = new PMXVertexDeformBDEF2(this.pmx, vtx); b2.Bone1 = this.pmx.Bones[weightList[0].Key]; b2.Bone1Weight = (float)weightList[0].Value / (float)totalWeight; b2.Bone2 = this.pmx.Bones[weightList[1].Key]; vtx.Deform = b2; } else if (weightList.Count > 2) { PMXVertexDeformBDEF4 b4 = new PMXVertexDeformBDEF4(this.pmx, vtx); b4.Bone1 = this.pmx.Bones[weightList[0].Key]; b4.Bone1Weight = (float)weightList[0].Value / (float)totalWeight; b4.Bone2 = this.pmx.Bones[weightList[1].Key]; b4.Bone2Weight = (float)weightList[1].Value / (float)totalWeight; b4.Bone3 = this.pmx.Bones[weightList[2].Key]; b4.Bone3Weight = (float)weightList[2].Value / (float)totalWeight; if (weightList.Count < 4) { b4.Bone4 = null; } else { b4.Bone4 = this.pmx.Bones[weightList[3].Key]; b4.Bone4Weight = (float)weightList[3].Value / (float)totalWeight; } vtx.Deform = b4; } else { //Most likely a prop! //Console.WriteLine("Weight error on " + this.inFile); if (pmx.Bones.Count == 0) { PMXBone mb = new PMXBone(pmx); mb.NameEN = "prop"; mb.NameJP = "prop"; mb.Position = new PMXVector3(0, 0, 0); mb.Translatable = true; pmx.Bones.Add(mb); } PMXVertexDeformBDEF1 b1 = new PMXVertexDeformBDEF1(this.pmx, vtx); b1.Bone1 = this.pmx.Bones[0]; vtx.Deform = b1; } } vertices.Add(vtx); this.pmx.Vertices.Add(vtx); vtxIndex++; } for (k = 0; k < idxTmp.Count; k += 3) { PMXTriangle tri = new PMXTriangle(this.pmx); tri.Vertex1 = vertices[idxTmp[k + 2]]; tri.Vertex2 = vertices[idxTmp[k + 1]]; tri.Vertex3 = vertices[idxTmp[k + 0]]; mat.Triangles.Add(tri); } this.pmx.Materials.Add(mat); } } this.totalVertCount = (uint)vtxIndex; if (this.mdlInfo.hasExp == 0) { this.WritePMX(); } else { this.CheckForVertexMorphs(); } }