private static float DetermineWeight(PMXVertex v, List <PMXBone> checkBones) { Dictionary <PMXBone, float> weights = new Dictionary <PMXBone, float>(); float weightSum = 0.0f; if (v.Deform is PMXVertexDeformBDEF4) { PMXVertexDeformBDEF4 df4 = (PMXVertexDeformBDEF4)(v.Deform); AddWeightInternal(df4.Bone1, df4.Bone1Weight, weights, ref weightSum); AddWeightInternal(df4.Bone2, df4.Bone2Weight, weights, ref weightSum); AddWeightInternal(df4.Bone3, df4.Bone3Weight, weights, ref weightSum); AddWeightInternal(df4.Bone4, df4.Bone4Weight, weights, ref weightSum); } else if (v.Deform is PMXVertexDeformBDEF2) { PMXVertexDeformBDEF2 df2 = (PMXVertexDeformBDEF2)(v.Deform); AddWeightInternal(df2.Bone1, df2.Bone1Weight, weights, ref weightSum); AddWeightInternal(df2.Bone2, 1.0f - df2.Bone1Weight, weights, ref weightSum); } else { PMXVertexDeformBDEF1 df1 = (PMXVertexDeformBDEF1)(v.Deform); AddWeightInternal(df1.Bone1, 1.0f, weights, ref weightSum); } if (weights.Count == 0 || weightSum <= 0.0f) { return(0.0f); } float resWeight = 0.0f; foreach (PMXBone b in checkBones) { if (weights.ContainsKey(b)) { resWeight += weights[b]; } } if (resWeight > 1.0f) { return(1.0f); } else if (resWeight < 0.0f) { return(0.0f); } return(resWeight); }
private void CreateDeform(PMXVertex vtx, int boneCount, int boneIndexSize, int floatLength) { PMXBone[] bones = new PMXBone[boneCount]; float[] weights = new float[boneCount]; for (int i = 0; i < boneCount; i++) { switch (boneIndexSize) { case 1: bones[i] = GetBoneByBoneId((int)sp.ReadU8()); break; case 2: bones[i] = GetBoneByBoneId((int)sp.ReadU16()); break; default: throw new Exception(); } } for (int i = 0; i < boneCount; i++) { switch (floatLength) { case 2: weights[i] = sp.ReadHalfFloat(); break; case 4: weights[i] = sp.ReadSingle(); break; default: throw new Exception(); } } List <BonePlusWeight> usableBones = new List <BonePlusWeight>(); for (int i = 0; i < boneCount; i++) { if (bones[i] != null) { usableBones.Add(new BonePlusWeight() { Bone = bones[i], Weight = weights[i] }); } } usableBones.Sort(); if (usableBones.Count == 1) { PMXVertexDeformBDEF1 df = new PMXVertexDeformBDEF1(pmxModel, vtx); df.Bone1 = usableBones[0].Bone; vtx.Deform = df; } else if (usableBones.Count == 2) { PMXVertexDeformBDEF2 df = new PMXVertexDeformBDEF2(pmxModel, vtx); df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone1Weight = (usableBones[0].Weight) / (usableBones[0].Weight + usableBones[1].Weight); vtx.Deform = df; } else if (usableBones.Count == 3) { PMXVertexDeformBDEF4 df = new PMXVertexDeformBDEF4(pmxModel, vtx); float totalWeight = usableBones[0].Weight + usableBones[1].Weight + usableBones[2].Weight; df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone3 = usableBones[2].Bone; df.Bone4 = null; df.Bone1Weight = (usableBones[0].Weight) / totalWeight; df.Bone2Weight = (usableBones[1].Weight) / totalWeight; df.Bone3Weight = (usableBones[2].Weight) / totalWeight; df.Bone4Weight = 0.0f; vtx.Deform = df; } else { PMXVertexDeformBDEF4 df = new PMXVertexDeformBDEF4(pmxModel, vtx); float totalWeight = usableBones[0].Weight + usableBones[1].Weight + usableBones[2].Weight + usableBones[3].Weight; df.Bone1 = usableBones[0].Bone; df.Bone2 = usableBones[1].Bone; df.Bone3 = usableBones[2].Bone; df.Bone4 = usableBones[3].Bone; df.Bone1Weight = (usableBones[0].Weight) / totalWeight; df.Bone2Weight = (usableBones[1].Weight) / totalWeight; df.Bone3Weight = (usableBones[2].Weight) / totalWeight; df.Bone4Weight = (usableBones[3].Weight) / totalWeight; vtx.Deform = df; } }
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(); } }