public void ReadLODs() { int count = BitConverter.ToInt32(memory, readerpos); readerpos += 4; Mesh.LODs = new List<LOD>(); for (int i = 0; i < count; i++) { LOD lod = new LOD(); lod._offset = readerpos; lod.Headers = new List<LODHeader>(); int sectioncount = BitConverter.ToInt32(memory, readerpos); readerpos += 4; for (int j = 0; j < sectioncount; j++) { LODHeader lodsec = new LODHeader(); lodsec.matindex = BitConverter.ToUInt16(memory, readerpos); lodsec.index = BitConverter.ToUInt16(memory, readerpos + 2); lodsec.offset = BitConverter.ToUInt32(memory, readerpos + 4); lodsec.count = BitConverter.ToUInt16(memory, readerpos + 8); lodsec.unk1 = BitConverter.ToUInt16(memory, readerpos + 10); readerpos += 12; lod.Headers.Add(lodsec); } int indexsize = BitConverter.ToInt32(memory, readerpos); int indexcount = BitConverter.ToInt32(memory, readerpos + 4); readerpos += 8; lod.Indexes = new List<ushort>(); for (int j = 0; j < sectioncount; j++) { for (int k = 0; k < lod.Headers[j].count * 3; k++) { lod.Indexes.Add(BitConverter.ToUInt16(memory, readerpos)); readerpos += 2; } } indexcount = BitConverter.ToInt32(memory, readerpos); // ?? SoftVertices ?? readerpos += 4; if (indexcount != 0) { MessageBox.Show("Not implemented!"); return; } indexcount = BitConverter.ToInt32(memory, readerpos); // ?? RigidVertices ?? readerpos += 4; lod.UnkIndexes1 = new List<ushort>(); for (int k = 0; k < indexcount; k++) { lod.UnkIndexes1.Add(BitConverter.ToUInt16(memory, readerpos)); readerpos += 2; } indexcount = BitConverter.ToInt32(memory, readerpos); // ?? ShadowIndices ?? readerpos += 4; if (indexcount != 0) { MessageBox.Show("Not implemented!"); return; } lod.UnkCount1 = BitConverter.ToInt32(memory, readerpos); // ?? Sections ?? readerpos += 4; lod.UnkIndexes2 = new List<UInt32>(); for (int k = 0; k < 3; k++) // ?? Rot/Loc ?? { lod.UnkIndexes2.Add(BitConverter.ToUInt32(memory, readerpos)); readerpos += 4; } lod.UnkSec1 = new List<UnknownSection>(); for (int k = 0; k < lod.UnkCount1; k++) // ?? Sections ?? Materials ?? { UnknownSection unk = new UnknownSection(); indexcount = BitConverter.ToInt32(memory, readerpos); readerpos += 4; unk.Indexes = new List<ushort>(); for (int l = 0; l < indexcount; l++) // ?? active bones ?? { unk.Indexes.Add(BitConverter.ToUInt16(memory, readerpos)); readerpos += 2; } unk.Unkn = new byte[24]; for (int l = 0; l < 24; l++) unk.Unkn[l] = memory[readerpos + l]; readerpos += 24; lod.UnkSec1.Add(unk); } indexcount = BitConverter.ToInt32(memory, readerpos); readerpos += 4; lod.ActiveBones = new List<byte>(); for (int k = 0; k < indexcount; k++) lod.ActiveBones.Add(memory[readerpos + k]); readerpos += indexcount; lod.UnkSec2 = new byte[48]; for (int k = 0; k < 48; k++) lod.UnkSec2[k] = memory[readerpos + k]; readerpos += 48; indexsize = BitConverter.ToInt32(memory, readerpos); indexcount = BitConverter.ToInt32(memory, readerpos + 4); readerpos += 8; lod.Edges = new List<Edge>(); for (int k = 0; k < indexcount; k++) { Edge e = new Edge(); e._offset = readerpos; e.Unk1 = BitConverter.ToInt32(memory, readerpos); e.Unk2 = BitConverter.ToInt32(memory, readerpos + 4); e.Influences = new List<Influence>(); for (int l = 0; l < 4; l++) { Influence inf = new Influence(); inf.bone = memory[readerpos + 8 + l]; inf.weight = memory[readerpos + 12 + l]; e.Influences.Add(inf); } e.Position = ReadVector(readerpos + 16); UInt16 u = BitConverter.ToUInt16(memory, readerpos + 28); UInt16 v = BitConverter.ToUInt16(memory, readerpos + 30); e.UV = new Vector2(HalfToFloat(u), HalfToFloat(v)); e._imported = false; lod.Edges.Add(e); readerpos += 32; } lod.unk2 = BitConverter.ToUInt32(memory, readerpos); readerpos += 4; Mesh.LODs.Add(lod); } }
public void ImportFromPsk(string path, int lod) { DebugOutput.Clear(); DebugOutput.PrintLn("Loading \"" + Path.GetFileName(path) + "\"..."); psk = new PSKFile(); //source psk object psk.ImportPSK(path); //load file LOD l = Mesh.LODs[lod]; //target LOD object l.Indexes = new List<ushort>(); //Init l.Headers = new List<LODHeader>(); l.UnkSec1 = new List<UnknownSection>(); DebugOutput.PrintLn("Creating bone conversion table..."); List<int> pskBone2skm = new List<int>(); //to convert psk boneindex to skm boneindex foreach (PSKFile.PSKBone b in psk.psk.bones) //loop all psk bones for (int i = 0; i < Mesh.Bones.Count; i++) //for each loop all skm bones if (b.name.TrimEnd(' ') == pcc.getNameEntry(Mesh.Bones[i].name)) //if match, ... { pskBone2skm.Add(i); //...then add if (MPOpt.SKM_importbones) { Bone t = Mesh.Bones[i]; t.position = b.location.ToVector3(); t.orientation = new Quad(b.rotation.ToVector4()); t.position.Y *= -1; t.orientation.y *= -1; if (i == 0) t.orientation.w *= -1; Mesh.Bones[i] = t; } break; //break search for match on this bone } DebugOutput.PrintLn("Importing Materials..."); if (psk.psk.materials.Count > Mesh.Materials.Count()) //If more Materials are needed to import { int count = psk.psk.materials.Count - Mesh.Materials.Count(); int mat = Mesh.Materials[0]; for (int i = 0; i < count; i++) Mesh.Materials.Add(mat); //Fill up with first material used } l.UnkCount1 = psk.psk.materials.Count; DebugOutput.PrintLn("Importing Indexes..."); int facesoffset = 0; //faceoffset for current section for (int i = 0; i < psk.psk.materials.Count; i++) //Section count = Material Count { int count = 0; //Face count of this section LODHeader h = new LODHeader(); //Header object for Current Section h.index = (ushort)i; //yeah same as material h.matindex = (ushort)i; //yeah same as material h.offset = (ushort)facesoffset; //offset in index buffer foreach (PSKFile.PSKFace f in psk.psk.faces) //go through all faces if (f.material == i) //Face has current material? { l.Indexes.Add((ushort)psk.psk.edges[f.v0].index); //add corners to index buffer l.Indexes.Add((ushort)psk.psk.edges[f.v2].index); l.Indexes.Add((ushort)psk.psk.edges[f.v1].index); //culling swap facesoffset += 3; //3 indexes added count++; //1 face added } h.count = (uint)count; //sum faces h.unk1 = 0; //always zero l.Headers.Add(h); //add new header } l.Edges = new List<Edge>(); //reset edge list, first step: import coords and UVS DebugOutput.PrintLn("Importing Vertices and UVs..."); for (int i = 0; i < psk.psk.points.Count; i++) //loop all edges/vertices in psk { Edge ne = new Edge(); //the new skm edge PSKFile.PSKEdge e = new PSKFile.PSKEdge(); PSKFile.PSKPoint p = psk.psk.points[i]; //actual point from psk foreach(PSKFile.PSKEdge t in psk.psk.edges) if (t.index == i) { e = t; break; } ne.Position = p.ToVector3(); //set coords&UVs ne.Position.Y *= -1; //flip Y axis ne.UV = new Vector2(e.U, e.V); //offsets for light fix ne.Influences = new List<Influence>(); //prepare foreach (PSKFile.PSKWeight w in psk.psk.weights) if (w.point == i) ne.Influences.Add(new Influence(w.weight, pskBone2skm[w.bone])); ne.Unk1 = 0; //tangent space quad1 ne.Unk2 = 0; //tangent space quad2 l.Edges.Add(ne); } DebugOutput.PrintLn("Adding Dup Influences..."); int ccnt = 0; int ccnt2 = 0; foreach (Edge e in l.Edges) { bool done = false; if (e.Influences.Count() == 0) { foreach (Edge e2 in l.Edges) if (e2.Position == e.Position && e2.Influences.Count() != 0 && !done) { foreach (Influence i in e2.Influences) { Influence ni; ni.bone = i.bone; ni.weight = i.weight; e.Influences.Add(ni); } done = true; ccnt2++; } else if (done) break; ccnt++; } } for (int i = 0; i < l.Edges.Count; i++) { List<Influence> tinf = new List<Influence>(); for (int j = 0; j < l.Edges[i].Influences.Count; j++) if (l.Edges[i].Influences[j].weight > 0) tinf.Add(l.Edges[i].Influences[j]); Edge e = l.Edges[i]; e.Influences = tinf; l.Edges[i] = e; } List<int> tempidx = new List<int>(); for (int i = 0; i < l.Edges.Count; i++) if (l.Edges[i].Influences.Count == 1) tempidx.Add(i); for (int i = 0; i < l.Edges.Count; i++) if (l.Edges[i].Influences.Count > 1) tempidx.Add(i); List<Edge> tmpedges = new List<Edge>(); foreach (int n in tempidx) tmpedges.Add(l.Edges[n]); l.Edges = tmpedges; for(int i=0;i<l.Indexes.Count;i++) for(int j=0;j<tmpedges.Count;j++) if (tempidx[j] == l.Indexes[i]) { l.Indexes[i] = (ushort)j; break; } DebugOutput.PrintLn(ccnt + " " + ccnt2 + " Filling up Influences..."); foreach (Edge e in l.Edges) //loop all edges and fill up influences to 4 { int count = e.Influences.Count(); //current influence count for (int i = count; i < 4; i++) //add until 4 e.Influences.Add(new Influence(0, 0)); //add placeholder } DebugOutput.PrintLn("Creating active bone list..."); l.ActiveBones = new List<byte>(); //Init List, Get Active Bone List l.ActiveBones.Add(0); //add god node foreach (Edge e in l.Edges) //loop all edges for (int i = 0; i < 4; i++) //and each influence if (e.Influences[i].weight != 0) //if has influence { byte bone = e.Influences[i].bone; //get bone bool found = false; //search if already in list for (int j = 0; j < l.ActiveBones.Count; j++) if (l.ActiveBones[j] == bone) found = true; if (!found) //if not in list, add l.ActiveBones.Add(bone); } l.ActiveBones.Sort(); //Sort list int lastbone = l.ActiveBones[l.ActiveBones.Count - 1]; l.ActiveBones = new List<byte>(); for (byte i = 0; i <= lastbone; i++) l.ActiveBones.Add(i); DebugOutput.PrintLn("Creating sub bone lists..."); foreach (LODHeader h in l.Headers) //Get sub bonelists, loop each section { UnknownSection s = new UnknownSection(); //init s.Unkn = new byte[24]; //zero for now, !!!TODO!!! s.Indexes = new List<ushort>(); foreach (byte b in l.ActiveBones) s.Indexes.Add(b); //sort list l.UnkSec1.Add(s); //add this section } DebugOutput.PrintLn("Creating unknown bone list..."); l.UnkIndexes1 = new List<ushort>(); foreach (byte b in l.ActiveBones) l.UnkIndexes1.Add(b); int edgeoffset = 0; DebugOutput.PrintLn("Creating unknown sections..."); for (int i = 0; i < l.Headers.Count; i++) //update values in unknown section { LODHeader h = l.Headers[i]; int pos = (int)h.offset; int maxsimple = -1; int maxmulti = -1; int minsimple = l.Edges.Count; int minmulti = l.Edges.Count; int lensimple = 0, lenmulti = 0; for (int j = 0; j < h.count * 3; j++) //determine min,max edge indexes { Edge e = l.Edges[l.Indexes[pos]]; int index = l.Indexes[pos]; int count = 0; foreach (Influence inf in e.Influences) if (inf.weight != 0) count++; if (count == 0) { MessageBox.Show("Error: Found vertex without influences!"); return; } if (count == 1) { if (index < minsimple) minsimple = index; if (index > maxsimple) maxsimple = index; } if (count > 1) { if (index < minmulti) minmulti = index; if (index > maxmulti) maxmulti = index; } pos++; } lensimple = (maxsimple - minsimple) + 1; lenmulti = (maxmulti - minmulti) + 1; lensimple = Math.Max(lensimple, 0); lenmulti = Math.Max(lenmulti, 0); byte[] buff = BitConverter.GetBytes(lensimple); for (int j = 0; j < 4; j++) l.UnkSec1[i].Unkn[j] = buff[j]; buff = BitConverter.GetBytes(lenmulti); for (int j = 0; j < 4; j++) l.UnkSec1[i].Unkn[j + 4] = buff[j]; l.UnkSec1[i].Unkn[8] = 4; int sum = lensimple + lenmulti; edgeoffset += sum; if (i == l.Headers.Count - 1) { buff = BitConverter.GetBytes(edgeoffset); for (int j = 0; j < 4; j++) l.UnkSec1[i].Unkn[j + 16] = buff[j]; } else { buff = BitConverter.GetBytes(edgeoffset); for (int j = 0; j < 4; j++) l.UnkSec1[i].Unkn[j + 12] = buff[j]; } } DebugOutput.PrintLn("Calculating 4D tangent space quaternions..."); CalcTangentSpace2(l); //Calc 4D Tangents DebugOutput.PrintLn("Done."); DebugOutput.PrintLn("Saving pcc..."); Mesh.LODs[lod] = l; //assign lod }