public GenericTexture BakeTexturePalette(GenericTexture t, int pid, List <byte[]> Palette) { if (pid == -1) { return(t); } GenericTexture tex = new GenericTexture(); tex.Width = t.Width; tex.Height = t.Height; tex.Id = t.Id; tex.InternalFormat = PixelInternalFormat.Rgb5A1; tex.PixelFormat = PixelFormat.Rgba; byte[] palette = Palette[pid]; byte[] Data = new byte[tex.Width * tex.Height * 2]; for (int i = 0; i < t.Mipmaps[0].Length; i++) { if (palette.Length > 32) { //8bpp Data[i * 2 + 0] = palette[t.Mipmaps[0][i] * 2 + 1]; Data[i * 2 + 1] = palette[t.Mipmaps[0][i] * 2]; } else { //4bpp int id = t.Mipmaps[0][i]; Data[i * 4 + 2] = palette[(id & 0xF) * 2 + 1]; Data[i * 4 + 3] = palette[(id & 0xF) * 2]; Data[i * 4 + 0] = palette[((id >> 4) & 0xF) * 2 + 1]; Data[i * 4 + 1] = palette[((id >> 4) & 0xF) * 2]; } } tex.Mipmaps.Add(Data); return(tex); }
public void LoadGenericTexture(GenericTexture Texture) { if (Texture.Mipmaps.Count == 0) { return; } GL.BindTexture(TextureTarget.Texture2D, GLID); //todo: compressed PixelType PixelType = PixelType.UnsignedByte; if (Texture.InternalFormat == PixelInternalFormat.Rgb5A1) { PixelType = PixelType.UnsignedShort5551; } if (Texture.InternalFormat == PixelInternalFormat.CompressedRgbS3tcDxt1Ext || Texture.InternalFormat == PixelInternalFormat.CompressedRgbaS3tcDxt5Ext) { GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, (InternalFormat)Texture.InternalFormat, (int)Texture.Width, (int)Texture.Height, 0, Texture.Mipmaps[0].Length, Texture.Mipmaps[0]); Console.WriteLine(GL.GetError() + " " + Texture.Mipmaps[0].Length.ToString("X")); } else { GL.TexImage2D(TextureTarget.Texture2D, 0, Texture.InternalFormat, (int)Texture.Width, (int)Texture.Height, 0, Texture.PixelFormat, PixelType, Texture.Mipmaps[0]); } Width = Texture.Width; Height = Texture.Height; Console.WriteLine(GLID + " " + Texture.Width + " " + Texture.Height + " " + Texture.InternalFormat + " " + Texture.PixelFormat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); Loaded = true; }
public static GenericTexture ToGenericTexture(byte[] xifile) { GenericTexture tex = new GenericTexture(); Level5_XI xi = new Level5_XI(); xi.Open(xifile); if (xi.SwitchFile && xi.ImageFormat == 0x1D) { tex.Mipmaps.Add(xi.BuildImageDataFromBlock(8)[0]); tex.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbS3tcDxt1Ext; tex.Width = (uint)xi.Height; tex.Height = (uint)xi.Width; } else if (xi.SwitchFile && xi.ImageFormat == 0x1F) { tex.Mipmaps.Add(xi.BuildImageDataFromBlock(16)[0]); tex.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbaS3tcDxt5Ext; tex.Width = (uint)xi.Height; tex.Height = (uint)xi.Width; } else if (xi.SwitchFile && xi.ImageFormat == 0x1) { tex.Mipmaps.Add(xi.BuildImageData()[0]); tex.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.Rgb8; tex.PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgb; tex.Width = (uint)xi.Height; tex.Height = (uint)xi.Width; } else { var texture = xi.ToBitmap(); tex.FromBitmap(texture); texture.Dispose(); } return(tex); }
public void Open(FileItem File) { var igb = new IGBFile(File.GetFileBinary()); var igbSkel = new IGSkeleton(igb); Matrix4[] transforms = new Matrix4[igbSkel.Bones.Count]; Matrix4[] inverts = new Matrix4[igbSkel.Bones.Count]; int boneIndex = 0; foreach (var v in igbSkel.Bones) { if (v == null) continue; GenericBone b = new GenericBone(); b.Name = v.Name; b.ParentIndex = v.ParentIndex; transforms[boneIndex] = new Matrix4( v.WorldInverseMatrix.M11, v.WorldInverseMatrix.M12, v.WorldInverseMatrix.M13, v.WorldInverseMatrix.M14, v.WorldInverseMatrix.M21, v.WorldInverseMatrix.M22, v.WorldInverseMatrix.M23, v.WorldInverseMatrix.M24, v.WorldInverseMatrix.M31, v.WorldInverseMatrix.M32, v.WorldInverseMatrix.M33, v.WorldInverseMatrix.M34, v.WorldInverseMatrix.M41, v.WorldInverseMatrix.M42, v.WorldInverseMatrix.M43, v.WorldInverseMatrix.M44); inverts[boneIndex] = transforms[boneIndex].Inverted(); b.Transform = inverts[boneIndex]; boneIndex++; Skeleton.Bones.Add(b); } foreach (var b in Skeleton.Bones) { if (b.ParentIndex != -1) { b.Transform = inverts[b.ParentIndex] * transforms[Skeleton.Bones.IndexOf(b)]; b.Transform = b.Transform.Inverted(); var position = igbSkel.Bones[Skeleton.Bones.IndexOf(b)].Position; b.Position = new Vector3(position.X, position.Y, position.Z); } } var vertexBuffers = IGVertexAccessor.ToDivaModels(igb); Model.Skeleton = Skeleton; Console.WriteLine(vertexBuffers.Count); foreach (var model in vertexBuffers) { GenericMesh m = new GenericMesh(); m.Name = model.Name; if (m.Name.Equals("")) m.Name = "Mesh_" + vertexBuffers.IndexOf(model); Console.WriteLine(m.Name + " " + !(model.Texture==null)); if(model.Texture != null) { GenericTexture t = new GenericTexture(); t.Name = System.IO.Path.GetFileNameWithoutExtension(model.Texture.Name); t.Width = (uint)model.Texture.Width; t.Height = (uint)model.Texture.Height; t.Mipmaps.Add(model.Texture.RGBA); if(!Model.MaterialBank.ContainsKey(t.Name)) Model.TextureBank.Add(t.Name, t); GenericMaterial mat = new GenericMaterial(); mat.TextureDiffuse = t.Name; if (!Model.MaterialBank.ContainsKey(t.Name)) Model.MaterialBank.Add(t.Name, mat); m.MaterialName = t.Name; } foreach (var mesh in model.Mesh) { var vertices = ToGenericVertices(mesh.Vertices); foreach (var dl in mesh.DisplayList) { if (dl.PrimitiveType == PrimType.Triangles) { foreach(var f in dl.Indices) m.Vertices.Add(vertices[f]); } if (dl.PrimitiveType == PrimType.TriangleStrip) { var tempList = new List<GenericVertex>(); foreach (var f in dl.Indices) tempList.Add(vertices[f]); Tools.TriangleConverter.StripToList(tempList, out tempList); m.Vertices.AddRange(tempList); } } } if(model.SingleBindBone != null && model.SingleBindBone != "") { var singleBone = Skeleton.Bones.Find(e => e.Name.Equals(model.SingleBindBone)); var singleBindTransform = Skeleton.GetWorldTransform(singleBone); var singleBindIndex = Skeleton.Bones.IndexOf(singleBone); for (int i = 0; i < m.VertexCount;i++) { var vert = m.Vertices[i]; vert.Pos = Vector3.TransformPosition(vert.Pos, singleBindTransform); vert.Nrm = Vector3.TransformNormal(vert.Nrm, singleBindTransform); vert.Bones = new Vector4(singleBindIndex, 0, 0, 0); vert.Weights = new Vector4(1, 0, 0, 0); m.Vertices[i] = vert; } } m.Optimize(); Model.Meshes.Add(m); } }
private void ReadTextures(DataReader reader, uint offset, int count, uint paletteOffset, int paletteCount, uint stringTableOffset) { reader.Position = offset; var texInfo = reader.ReadStructArray <TextureInfo>(count); var startOffset = reader.Position; reader.Position = paletteOffset; var palInfo = reader.ReadStructArray <PaletteInfo>(paletteCount); var palSectionOffset = reader.Position; for (int i = 0; i < texInfo.Length; i++) { var textureName = reader.ReadString(stringTableOffset + texInfo[i].NameOffset, -1); Console.WriteLine($"{textureName} {texInfo[i].Type1} {texInfo[i].Type2} {texInfo[i].PaletteIndex} {texInfo[i].Width} {texInfo[i].Height} {(startOffset + texInfo[i].DataOffset).ToString("X")}"); var format = texInfo[i].Type1; byte[] palData = new byte[texInfo[i].Depth * 2]; var palFormat = 0; var palCount = 0; switch (texInfo[i].Type1) { case 0x00: format = 0; break; case 0x01: format = 1; break; case 0x03: format = 3; break; case 0x04: format = 4; break; case 0x05: format = 5; break; case 0x06: format = 6; break; case 0x07: format = 14; break; case 0x09: palFormat = 1; format = 9; if (texInfo[i].Type2 == 4) { format = 8; } break; case 0x0A: palFormat = 2; format = 9; if (texInfo[i].Type2 == 4) { format = 8; } break; case 0x0B: palFormat = 1; format = 9; if (texInfo[i].Type2 == 4) { format = 8; } break; default: throw new NotSupportedException("Unsupported Texture Type " + texInfo[i].Type1 + " " + texInfo[i].Type2); } //var pal = palInfo.ToList().Find(e => e.NameOffset == texInfo[i].NameOffset); if (texInfo[i].PaletteIndex > -1) { var pal = palInfo[texInfo[i].PaletteIndex]; palCount = pal.Count; palData = reader.GetSection(palSectionOffset + pal.DataOffset, 2 * palCount); Console.WriteLine((palSectionOffset + pal.DataOffset).ToString("X") + " " + (2 * palCount).ToString("X")); } var dataLength = Tools.TPL.textureByteSize((Tools.TPL_TextureFormat)format, texInfo[i].Width, texInfo[i].Height); ; Console.WriteLine(textureName + " " + (Tools.TPL_TextureFormat)format + " " + dataLength.ToString("X")); reader.Position = startOffset + texInfo[i].DataOffset; var bitmap = Tools.TPL.ConvertFromTextureMelee(reader.ReadBytes(dataLength), texInfo[i].Width, texInfo[i].Height, format, palData, palCount, palFormat);//.Save(textureName + ".png"); GenericTexture t = new GenericTexture(); t.Name = textureName; t.FromBitmap(bitmap); bitmap.Dispose(); Textures.Add(t); } }
public void Open(FileItem File) { var Data = File.GetFileBinary(); Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); Model.Skeleton.RotationOrder = RotationOrder.ZYX; // decompress using (DataReader reader = new DataReader(new MemoryStream(Data))) { reader.BigEndian = true; if (reader.BaseStream.Length < 8 || !reader.ReadString(8).Equals("PERS-SZP")) { // not compressed } else { reader.BigEndian = true; uint compressedoffset = reader.ReadUInt32(); reader.Seek(compressedoffset); Data = Tools.Decompress.YAY0(reader.ReadBytes((int)(reader.BaseStream.Length - compressedoffset))); } } // decode file contents using (DataReader reader = new DataReader(new MemoryStream(Data))) { reader.BigEndian = true; reader.Seek(0x8); if (!reader.ReadString(8).Equals("FRAGMENT")) { return; } reader.Seek(0x10); uint DataOffset = reader.ReadUInt32(); uint RelocationTableOffset = reader.ReadUInt32(); reader.Skip(4); // filesize reader.Skip(4); // tableOffset again // Relocation Table reader.Seek(RelocationTableOffset); int entryCount = reader.ReadInt32(); int[] offsets = new int[entryCount]; for (int i = 0; i < entryCount; i++) { int mask = 0xFFFF; offsets[i] = reader.ReadInt32(); if (RelocationTableOffset > 0xFFFF) { mask = 0x1FFFF; // hack } uint temp = reader.Position; reader.Seek((uint)(offsets[i] & 0x1FFFF)); reader.WriteInt32At(reader.ReadInt32() & mask, offsets[i] & 0x1FFFF); reader.Seek((uint)(offsets[i] & 0x1FFFF)); reader.Seek(temp); } // main data reader.Seek(DataOffset); reader.Skip(0x10); uint mainOffset = reader.ReadUInt32(); // main stuff reader.Seek(mainOffset); reader.Skip(8); // i dunno uint offsetToTextureOffset = reader.ReadUInt32(); reader.Seek(offsetToTextureOffset); uint textureOffset = reader.ReadUInt32(); // may be objects instead of just textures reader.Seek(textureOffset); int TextureCount = reader.ReadInt32() & 0xFFFF; // should have 0x17 in front int PaletteCount = reader.ReadInt16(); int VertexCount = reader.ReadInt16(); uint TextureOffset = reader.ReadUInt32(); uint PaletteOffset = reader.ReadUInt32(); uint VertexOffset = reader.ReadUInt32(); reader.Skip(0x1C); //I dunno uint objectOffset = reader.ReadUInt32(); // Textures------------------------------------------------------- List <GenericTexture> Textures = new List <GenericTexture>(); List <byte[]> Palettes = new List <byte[]>(); //Read Palettes reader.Seek(PaletteOffset); for (int i = 0; i < PaletteCount; i++) { int colorcount = reader.ReadInt32(); uint OffsetData = reader.ReadUInt32(); int OffsetSomething = reader.ReadInt32(); Palettes.Add(reader.GetSection(OffsetData, colorcount * 2)); } // Read Textures? reader.Seek(TextureOffset); //Console.WriteLine(reader.pos().ToString("x")); for (int i = 0; i < TextureCount; i++) { int format = reader.ReadByte(); int bitsize = reader.ReadByte(); uint width = reader.ReadUInt16(); uint height = reader.ReadUInt16(); uint size = reader.ReadUInt16(); // sometimes 8 maybe an id? pointer? uint texDataOffset = reader.ReadUInt32() & 0x1FFFF; Console.WriteLine("Texture " + format + " " + bitsize + " " + size + " " + width + " " + height); GenericTexture tex = new GenericTexture(); Textures.Add(tex); tex.Name = "Texture_" + i; byte[] data; tex.Width = width; tex.Height = height; tex.PixelFormat = PixelFormat.Rgba; if (format == 4) { // Raw if (bitsize == 1) //RGBA { data = reader.GetSection(texDataOffset, (int)size * bitsize); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Luminance8; tex.PixelFormat = PixelFormat.Luminance; } } else if (format == 2) { // Paletted if (bitsize == 0) //4bpp { data = reader.GetSection(texDataOffset, (int)size / 2); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Alpha4; } else if (bitsize == 1) //8bpp { data = reader.GetSection(texDataOffset, (int)size * bitsize); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Alpha8; } } else { if (bitsize == 2) { data = reader.GetSection(texDataOffset, (int)size * bitsize); // swap endian for (int j = 0; j < data.Length / 2; j++) { byte temp = data[j * 2]; data[j * 2] = data[(j * 2) + 1]; data[(j * 2) + 1] = temp; } tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Rgb5A1; } else if (bitsize == 3) { tex.InternalFormat = PixelInternalFormat.Rgba8; data = reader.GetSection(texDataOffset, (int)size * 4); tex.Mipmaps.Add(data); } } } // Objects-------------------------------------------------------- // now parse until end bool done = false; Stack <GenericBone> boneStack = new Stack <GenericBone>(); GenericBone parentBone = null; reader.Seek(objectOffset); reader.Skip(4); // idk int maybeCount = reader.ReadInt32(); string currentMaterialName = ""; GenericMaterial currentMaterial = new GenericMaterial(); GenericBone CurrentBone = null; while (!done) { int doff, temp; //Console.WriteLine(reader.Position().ToString("x") + " " + reader.ReadByte().ToString("x")); reader.ReadByte(); reader.Seek(reader.Position - 1); switch (reader.ReadByte()) { case 0x03: // Perhaps some object offset? Offset goes to beginning of file. Material maybe? reader.Skip(0x08 - 1); break; case 0x05: reader.Skip(0x04 - 1); boneStack.Push(CurrentBone); parentBone = boneStack.Peek(); break; case 0x06: reader.Skip(0x04 - 1); if (boneStack.Count > 0) { boneStack.Pop(); if (boneStack.Count > 0) { parentBone = boneStack.Peek(); } } break; case 0x08: reader.Skip(4 - 1); int s1 = reader.ReadByte() & 0x7F; reader.Skip(1); int s2 = reader.ReadInt16(); reader.Skip(4); // pops matrix // maybe pop until you get to this bone? //Also maybe some texture thing? Console.WriteLine("What dis?" + " " + s1 + " " + s2); //throw new Exception("Weird Special Thing"); /*for (int i = popto - s1; i < popto + s2; i++) * { * Bone bo = skel.GetBoneByID(i); * boneStack.Push(bo); * }*/ break; case 0x18: // idk has 4 values reader.Skip(0x08 - 1); break; case 0x1D: int id = reader.ReadByte(); int what = reader.ReadByte(); int parent = (sbyte)reader.ReadByte(); // read bone properties Vector3 trans = new Vector3((short)reader.ReadInt16(), (short)reader.ReadInt16(), (short)reader.ReadInt16()); Vector3 rot = new Vector3((short)reader.ReadInt16() / 180, ((short)reader.ReadInt16()) / 180, (short)reader.ReadInt16() / 180); // to radians rot.X = (rot.X * (float)Math.PI) / 180f; rot.Y = (rot.Y * (float)Math.PI) / 180f; rot.Z = (rot.Z * (float)Math.PI) / 180f; //rot = new Vector3(rot.Z, rot.X, rot.Y); Vector3 scale = new Vector3(); scale.X = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; scale.Y = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; scale.Z = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; int parent2 = boneStack.Count; GenericBone b = new GenericBone(); b.Name = "Bone_" + id; if (parentBone != null) { b.ParentIndex = Model.Skeleton.IndexOf(parentBone); } else { b.ParentIndex = -1; } b.ID = id; b.Scale = new Vector3(1, 1, 1); // scale b.Position = trans; b.Rotation = rot; CurrentBone = b; Model.Skeleton.Bones.Add(b); //Console.WriteLine(reader.Position().ToString("x") + " " + b.Name + " " + b.p1 + " " + what + " " + parent + " " + boneStack.Count + " " + trans.ToString() + " " + rot.ToString() + " " + scale.ToString()); //Console.WriteLine(b.transform.ToString()); break; case 0x1E: //reader.Skip(3); reader.Skip(1); int w = reader.ReadInt16(); // bone index doff = reader.ReadInt32(); temp = (int)reader.Position; reader.Seek((uint)doff); { GenericMesh mesh = DisplayListToGenericMesh(N64Tools.ReadDisplayList(reader, Model.Skeleton.IndexOf(Model.Skeleton.GetBoneByID(w)), Model.Skeleton.GetWorldTransform(Model.Skeleton.GetBoneByID(w)))); mesh.MaterialName = currentMaterialName; Model.Meshes.Add(mesh); } reader.Seek((uint)temp); break; case 0x22: int materialIndex = reader.ReadByte(); int ww = (short)reader.ReadInt16(); doff = reader.ReadInt32(); temp = (int)reader.Position; if (doff == 0) { continue; } reader.Seek((uint)doff); { GenericMesh mesh = DisplayListToGenericMesh(N64Tools.ReadDisplayList(reader, Model.Skeleton.IndexOf(parentBone), Model.Skeleton.GetWorldTransform(parentBone))); mesh.MaterialName = currentMaterialName; Model.Meshes.Add(mesh); } reader.Seek((uint)temp); //((DisplayList)DisplayLists.Nodes[DisplayLists.Nodes.Count - 1]).Mat = unk; //Console.WriteLine("Material Maybe 0x" + reader.pos().ToString("x") + " " + unk + " " + .Count); break; case 0x23: reader.Skip(1); int tidunk = (short)reader.ReadInt16(); int texOff = reader.ReadInt32(); //& 0x1FFFF Material Offset? int tid = (short)reader.ReadInt16(); int pid = (short)reader.ReadInt16(); reader.Skip(4); // 0xFF padding //Console.WriteLine("TextureCount " + tid + " " + pid + " " + tidunk + " " + texOfreader.ToString("x")); if (tid != -1) { currentMaterial = new GenericMaterial(); currentMaterialName = "material_" + Model.MaterialBank.Count; var diffuse = BakeTexturePalette(Textures[tid], pid, Palettes); diffuse.Name = "texture_" + Model.TextureBank.Count; currentMaterial.TextureDiffuse = diffuse.Name; Model.TextureBank.Add(diffuse.Name, diffuse); Model.MaterialBank.Add(currentMaterialName, currentMaterial); } else { var currentTexture = currentMaterial.TextureDiffuse; currentMaterial = new GenericMaterial(); currentMaterialName = "material_" + Model.MaterialBank.Count; currentMaterial.TextureDiffuse = currentTexture; Model.MaterialBank.Add(currentMaterialName, currentMaterial); } // Read Texture Info At Offset int tt = (int)reader.Position; reader.Seek((uint)texOff); ReadTextureCodes(reader, currentMaterial); reader.Seek((uint)tt); break; // Texture Binding case 0x24: reader.Skip(3); break; // has to do with matrix popping case 0x25: reader.Skip(0x04 - 1); //Console.WriteLine("Unknown 0x" + reader.pos().ToString("x")); break; default: done = true; break; } ; } } // Post Process // optimized texture sharing Dictionary <string, string> newTexName = new Dictionary <string, string>(); Dictionary <string, GenericTexture> newTexBank = new Dictionary <string, GenericTexture>(); Dictionary <byte[], string> TextureBank = new Dictionary <byte[], string>(); foreach (var tex in Model.TextureBank) { if (!TextureBank.ContainsKey(tex.Value.Mipmaps[0])) { string newName = "texture_" + newTexName.Count; newTexName.Add(tex.Key, newName); newTexBank.Add(newName, tex.Value); TextureBank.Add(tex.Value.Mipmaps[0], newName); } else { newTexName.Add(tex.Key, TextureBank[tex.Value.Mipmaps[0]]); } } Model.TextureBank = newTexBank; foreach (var mesh in Model.Meshes) { var material = Model.GetMaterial(mesh); if (material != null && material.TextureDiffuse != null) { material.TextureDiffuse = newTexName[material.TextureDiffuse]; } } Console.WriteLine(TextureBank.Count + " total textures"); // Transform Verts /*int meshindex = 0; * foreach(GenericMesh mesh in Model.Meshes) * { * mesh.Name = "Mesh_" + meshindex; * GenericVertex[] CorrectedVertices = mesh.Vertices.ToArray(); * for(int i =0; i < CorrectedVertices.Length; i++) * { * CorrectedVertices[i].Pos = Vector3.TransformPosition(CorrectedVertices[i].Pos, Model.Skeleton.GetWorldTransform((int)CorrectedVertices[i].Bones.X)); * } * mesh.Vertices.Clear(); * mesh.Vertices.AddRange(CorrectedVertices); * }*/ }
public GenericModel ToGenericModel() { var mdl = new GenericModel() { Skeleton = Skeleton };; byte[] Data = File.ReadAllBytes(@"chr0020_model.npki"); byte[] ImageData = File.ReadAllBytes(@"chr0020_model.npkv"); foreach (var t in TXRs) { GenericTexture tex = new GenericTexture(); tex.Width = (uint)t.Width; tex.Height = (uint)t.Height; var buf = new byte[t.Width * t.Height / 2]; Array.Copy(ImageData, t.BufferOffsets[0], buf, 0, buf.Length); buf = VitaSwizzle.UnswizzlePS4(buf, t.Width, t.Height); tex.Mipmaps.Add(buf); tex.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbS3tcDxt1Ext; if (!mdl.TextureBank.ContainsKey(t.Name)) { mdl.TextureBank.Add(t.Name, tex); } Console.WriteLine(tex.Width + " " + tex.Height + " " + t.Unknown.ToString("X") + " " + t.BufferOffsets[0].ToString("X") + " " + t.BufferSizes[0].ToString("X")); } foreach (var v in VTXs) { if (v.BufferSizes.Length < 2) { continue; } GenericMesh m = new GenericMesh(); mdl.Meshes.Add(m); m.Name = v.Name; using (DataReader r = new DataReader(Data)) { for (uint i = 0; i < v.BufferSizes[1]; i += 2) { r.Seek((uint)v.BufferOffsets[1] + i); //r.PrintPosition(); var index = r.ReadInt16(); GenericVertex vert = new GenericVertex(); foreach (var attr in v.Attribtues) { r.Seek((uint)(v.BufferOffsets[0] + v.BufferInfos[attr.RESBufferIndex].Offset + index * v.BufferInfos[attr.RESBufferIndex].Stride + attr.BufferOffset)); switch (attr.AttributeName) { case 1: vert.Pos = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case 2: vert.Nrm = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case 5: vert.UV0 = new OpenTK.Vector2(r.ReadSingle(), r.ReadSingle()); break; case 8: var b1 = v.Bones[r.ReadInt32()]; var b2 = v.Bones[r.ReadInt32()]; var b3 = v.Bones[r.ReadInt32()]; var b4 = v.Bones[r.ReadInt32()]; vert.Bones = new OpenTK.Vector4(Skeleton.IndexOf(Skeleton.GetBoneByName(b1)), Skeleton.IndexOf(Skeleton.GetBoneByName(b2)), Skeleton.IndexOf(Skeleton.GetBoneByName(b3)), Skeleton.IndexOf(Skeleton.GetBoneByName(b4))); break; case 7: vert.Weights = new OpenTK.Vector4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; } } if (v.Bones.Count == 1) { vert.Bones = new OpenTK.Vector4(Skeleton.IndexOf(Skeleton.GetBoneByName(v.Bones[0])), 0, 0, 0); vert.Weights = new OpenTK.Vector4(1, 0, 0, 0); } m.Vertices.Add(vert); m.Triangles.Add(i / 2); //Console.WriteLine(index + " " + v.BufferOffsets[0].ToString("X") + " " + v.BufferInfos[0].Offset + " " + v.BufferInfos[0].Stride); } //m.Optimize(); } } return(mdl); }
private void ParseTextures(string path) { using (DataReader r = new DataReader(path)) { r.BigEndian = false; r.Seek(0x0C); var offset = r.ReadUInt32(); var count = r.ReadInt32(); r.Seek(offset); for (int i = 0; i < count; i++) { var off = offset + r.ReadUInt32(); var temp = r.Position; r.Seek(off); int mipMap = r.ReadByte(); int T = r.ReadByte(); int W = r.ReadByte(); r.Skip(1); var flags = r.ReadInt32(); if ((flags >> 24) == 0x10) { r.Skip(0xC); } int H = (int)Math.Pow(2, (W >> 4)); W = (int)Math.Pow(2, (W & 0xF)); Console.WriteLine(W + " " + H + " " + T + " " + r.Position.ToString("X")); GenericTexture t = new GenericTexture(); var size = (int)r.Length - (int)r.Position; if (T == 0x59) { size = W * H / 2; t.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbS3tcDxt1Ext; } else if (T == 0x5B) { size = W * H; t.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbaS3tcDxt5Ext; } else { continue; } t.Width = (uint)W; t.Height = (uint)H; t.Mipmaps.Add(r.GetSection(r.Position, size)); Textures.Add(t); r.Seek(temp); } } }
public void Open(FileItem File) { var skelPath = File.FilePath.Replace(".mdg", ".anm"); var skelAngPath = File.FilePath.Replace(".mdg", ".ang"); var modelPath = File.FilePath.Replace(".mdg", ".mdl"); var texPath = File.FilePath.Replace(".mdg", ".tex"); if (!System.IO.File.Exists(skelPath)) { System.Windows.Forms.MessageBox.Show("Missing Skeleton File " + Path.GetFileName(skelPath)); return; } if (!System.IO.File.Exists(skelAngPath)) { System.Windows.Forms.MessageBox.Show("Missing Skeleton File " + Path.GetFileName(skelAngPath)); return; } if (!System.IO.File.Exists(modelPath)) { System.Windows.Forms.MessageBox.Show("Missing Model File " + Path.GetFileName(modelPath)); return; } Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); if (System.IO.File.Exists(texPath)) { using (DataReader r = new DataReader(new FileStream(texPath, FileMode.Open))) { r.BigEndian = true; var unk = r.ReadInt32(); var width = r.ReadInt32(); var height = r.ReadInt32(); var dataLength = r.ReadInt32(); var padding = r.ReadInt32(); var format = r.ReadByte(); var data = r.GetSection(0x20, (int)(r.BaseStream.Length - 0x20)); var bmp = HSDLib.Helpers.TPL.ConvertFromTextureMelee(data, width, height, (int)TPL_TextureFormat.CMP, null, 0, 0); GenericTexture t = new GenericTexture(); t.FromBitmap(bmp); bmp.Dispose(); Model.TextureBank.Add("texture", t); Model.MaterialBank.Add("material", new GenericMaterial() { TextureDiffuse = "texture" }); } } using (DataReader r = new DataReader(new FileStream(skelPath, FileMode.Open))) { r.BigEndian = false; r.ReadInt32(); // magic r.ReadInt32(); // header var boneCount = r.ReadInt32(); var boneOffset = r.ReadUInt32(); using (DataReader angr = new DataReader(new FileStream(skelAngPath, FileMode.Open))) { angr.BigEndian = false; for (int i = 0; i < boneCount; i++) { r.Seek(boneOffset + (uint)(i * 0x20)); var bone = new GenericBone(); bone.Position = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.ReadSingle(); //r.Skip(0x10); // inverted world position bone.Name = r.ReadString(r.ReadUInt32(), -1); bone.ParentIndex = r.ReadInt32(); var flags = r.ReadInt32(); var angOffset = r.ReadUInt32(); /*angr.Seek(angOffset); * angr.Skip(4); * var posOff = angr.ReadUInt32(); * var rotOff = angr.ReadUInt32(); * var scaOff = angr.ReadUInt32(); * angr.Seek(posOff); * bone.Position = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle()); * angr.Seek(rotOff); * bone.Rotation = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle()); * angr.Seek(scaOff); * bone.Scale = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle());*/ Model.Skeleton.Bones.Add(bone); } } } Model.Skeleton.TransformWorldToRelative(); using (DataReader r = new DataReader(new FileStream(modelPath, FileMode.Open))) { r.BigEndian = true; r.ReadInt32(); // magic int boneCount = r.ReadInt16(); var meshCount = r.ReadInt16(); boneCount = r.ReadInt32(); var meshOffset = r.ReadUInt32(); r.ReadUInt32(); var boneOffset = r.ReadUInt32(); for (int i = 0; i < meshCount; i++) { r.Seek(meshOffset + (uint)(i * 80)); r.Skip(0x30); // bounding stuff var mesh = new GenericMesh(); mesh.MaterialName = "material"; mesh.Name = r.ReadString(r.ReadUInt32(), -1); r.Skip(4 * 4); var datInfoOffset = r.ReadUInt32(); Model.Meshes.Add(mesh); r.Seek(datInfoOffset); var flag = r.ReadInt32(); var bufferOffset = r.ReadUInt32(); var someCount = r.ReadInt32(); var primCount = r.ReadInt32(); using (DataReader buffer = new DataReader(new FileStream(File.FilePath, FileMode.Open))) { buffer.BigEndian = true; if (new string(buffer.ReadChars(4)) == "MDG5") { buffer.Seek(0x10); } else { buffer.Seek(0); } buffer.Skip(bufferOffset); for (int p = 0; p < primCount; p++) { var primitiveType = buffer.ReadInt16(); var pcount = buffer.ReadInt16(); if (primitiveType != 0x98) { throw new NotSupportedException("Unknown prim type " + primitiveType.ToString("X")); } var strip = new List <GenericVertex>(); for (int v = 0; v < pcount; v++) { var vert = new GenericVertex(); vert.Pos = new OpenTK.Vector3(buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle()); vert.Nrm = new OpenTK.Vector3(buffer.ReadSByte(), buffer.ReadSByte(), buffer.ReadSByte()); vert.Nrm.Normalize(); // Color? int col = buffer.ReadInt16(); var R = (col >> 12) & 0xF; var G = (col >> 8) & 0xF; var B = (col >> 4) & 0xF; var A = (col) & 0xF; vert.Clr = new OpenTK.Vector4( (R | R << 4) / (float)0xFF, (G | G << 4) / (float)0xFF, (B | B << 4) / (float)0xFF, (A | A << 4) / (float)0xFF); vert.UV0 = new OpenTK.Vector2(buffer.ReadInt16() / (float)0xFFF, buffer.ReadInt16() / (float)0xFFF); var weight1 = buffer.ReadByte() / (float)0xFF; float weight2 = 0; if (weight1 != 1) { weight2 = 1 - weight1; } var bone1 = buffer.ReadByte(); var bone2 = buffer.ReadByte(); vert.Bones = new OpenTK.Vector4(bone1, bone2, 0, 0); vert.Weights = new OpenTK.Vector4(weight1, weight2, 0, 0); strip.Add(vert); } TriangleConverter.StripToList(strip, out strip); mesh.Vertices.AddRange(strip); } } mesh.Optimize(); } } }
private void ParseDOBJs(IHSDNode node, HSD_JOBJ parent, List <HSD_JOBJ> BoneList) { if (node is HSD_JOBJ jobj) { if (jobj.DOBJ != null) { foreach (var child in jobj.DOBJ.List) { ParseDOBJs(child, jobj, BoneList); } } foreach (var child in jobj.Children) { ParseDOBJs(child, child, BoneList); } } if (node is HSD_DOBJ dobj) { Console.WriteLine("DOBJ found"); GenericMesh mesh = new GenericMesh(); mesh.Name = "Mesh_" + outModel.Meshes.Count; GenericMaterial mat = new GenericMaterial(); mesh.MaterialName = "material_" + outModel.MaterialBank.Count; outModel.MaterialBank.Add(mesh.MaterialName, mat); var Xscale = 1; var Yscale = 1; if (dobj.MOBJ != null) { if (dobj.MOBJ.Textures != null) { var tobj = dobj.MOBJ.Textures; mat.SWrap = GXTranslator.toWrapMode(tobj.WrapS); mat.TWrap = GXTranslator.toWrapMode(tobj.WrapT); Xscale = tobj.WScale; Yscale = tobj.HScale; if (!tobjToIndex.ContainsKey(tobj.ImageData.Data)) { Bitmap B = null; if (tobj.ImageData != null) { if (tobj.Tlut != null) { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, tobj.Tlut.Data, tobj.Tlut.ColorCount, (int)tobj.Tlut.Format); } else { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, null, 0, 0); } } GenericTexture t = new GenericTexture(); t.FromBitmap(B); B.Dispose(); tobjToIndex.Add(tobj.ImageData.Data, outModel.TextureBank.Count); outModel.TextureBank.Add("texture_" + outModel.TextureBank.Count, t); } mat.TextureDiffuse = outModel.TextureBank.Keys.ToArray()[tobjToIndex[tobj.ImageData.Data]]; } } outModel.Meshes.Add(mesh); if (dobj.POBJ != null) { foreach (HSD_POBJ pobj in dobj.POBJ.List) { // Decode the Display List Data GXDisplayList DisplayList = new GXDisplayList(pobj.DisplayListBuffer, pobj.VertexAttributes); var Vertices = ToGenericVertex(VertexAccessor.GetDecodedVertices(pobj), BoneList, pobj.BindGroups != null ? new List <HSD_JOBJWeight>(pobj.BindGroups.Elements) : null, parent); int bufferOffset = 0; foreach (GXPrimitiveGroup g in DisplayList.Primitives) { var primitiveType = GXTranslator.toPrimitiveType(g.PrimitiveType); var strip = new List <GenericVertex>(); for (int i = bufferOffset; i < bufferOffset + g.Count; i++) { strip.Add(Vertices[i]); } bufferOffset += g.Count; switch (primitiveType) { case OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip: Tools.TriangleConverter.StripToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Quads: Tools.TriangleConverter.QuadToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Triangles: break; default: Debug.WriteLine("Error converting primitive type " + primitiveType); break; } mesh.Vertices.AddRange(strip); } } } for (int i = 0; i < mesh.Vertices.Count; i++) { var vert = mesh.Vertices[i]; vert.UV0 = new Vector2(vert.UV0.X * Xscale, vert.UV0.Y * Yscale); mesh.Vertices[i] = vert; } mesh.Optimize(); Tools.TriangleConverter.ReverseFaces(mesh.Triangles, out mesh.Triangles); } }