public void read(FileData f) { int nameOff = f.readInt(); unknown = f.readInt(); valueCount = f.readInt(); int frameCount = f.readInt(); unknown2 = f.readUShort(); unknown3 = f.readUShort(); int dataOff = f.readInt(); f.seek(nameOff); name = f.readString(); f.seek(dataOff); for (int i = 0; i < frameCount; i++) { frame temp = new frame(); //temp.size = valueCount; temp.values = new float[valueCount]; for (int j = 0; j < valueCount; j++) { temp.values[j] = f.readFloat(); } frames.Add(temp); } }
public void Read(string fname) { FileData d = new FileData(fname); d.Endian = System.IO.Endianness.Little; d.skip(4); // RIFF int riffsize = d.readInt(); d.skip(4); //WAVE d.skip(4); //fmt int formatsize = d.readInt(); int audio_format = d.readUShort(); int channelCount = d.readUShort(); int sampleRate = d.readInt(); int byte_rate = d.readInt(); int blockalign = d.readUShort(); int bps = d.readUShort(); d.skip(4); // data int datasize = d.readInt(); byte[] data = d.getSection(d.pos(), datasize); Play(data, channelCount, bps, sampleRate); }
public void Read(FileData d) { d.Endian = Endianness.Big; d.seek(0x16); int count = d.readUShort(); d.seek(0x60); for (int i = 0; i < count; i++) { string name = d.readString(d.pos(), -1); d.skip(0x40); int unk = d.readInt(); int nextFile = d.readInt(); int c2 = d.readUShort(); int c1 = d.readUShort(); d.skip(4); // padding? int[] partsizes = new int[4]; for (int j = 0; j < 4; j++) { partsizes[j] = d.readInt(); } TreeNode part = new TreeNode(); part.Text = name; Nodes.Add(part); int off = 0; for (int j = 0; j < c1; j++) { TreeNode t = new TreeNode(); part.Nodes.Add(t); int decompressedSize = d.readInt(); byte[] dat = FileData.InflateZLIB(d.getSection(d.pos(), partsizes[j] - 4 - off)); d.skip(partsizes[j] - 4); off += partsizes[j]; string mag = new FileData(dat).Magic(); t.Text = name + "." + mag; if (mag.Equals("NTWD")) { Runtime.TextureContainers.Add(new NUT(new FileData(dat))); } if (mag.Equals("OMO ")) { Runtime.Animations.Add(t.Text, OMOOld.read(new FileData(dat))); MainForm.Instance.animList.treeView1.Nodes.Add(t.Text); } } } }
public Entry Read(FileData f) { attackId = f.readUShort(); unk = f.readUShort(); start = f.readUShort(); end = f.readUShort(); xmin = f.readFloat(); xmax = f.readFloat(); ymin = f.readFloat(); ymax = f.readFloat(); return(this); }
public Entry Read(FileData f) { subaction = f.readUShort(); f.readUShort();//skip padding startFrame = f.readUShort(); lastFrame = f.readUShort(); xmin = f.readFloat(); xmax = f.readFloat(); ymin = f.readFloat(); ymax = f.readFloat(); return(this); }
public void read(FileData f) { int nameOff = f.readInt(); unk1 = (f.readInt() != 0); int dataOff = f.readInt(); f.seek(nameOff); name = f.readString(); f.seek(dataOff); frameCount = f.readInt(); unk2 = (f.readUShort() != 0); short keyframeCount = f.readShort(); int keyframeOffset = f.readInt(); f.seek(keyframeOffset); frame tempFrame; for (int i = 0; i < keyframeCount; i++) { tempFrame.frameNum = f.readShort(); tempFrame.state = f.readByte(); tempFrame.unknown = f.readByte(); frames.Add(tempFrame); tempFrame = new frame(); } }
public static double readVal(FileData d, int valueFormat) { int scale = (int)Math.Pow(2, valueFormat & 0x1F); d.Endian = System.IO.Endianness.Little; switch (valueFormat & 0xF0) { case 0x00: return(d.readFloat()); case 0x20: return(d.readShort() / (double)scale); case 0x40: return(d.readUShort() / (double)scale); case 0x60: return(d.readSByte() / (double)scale); case 0x80: return(d.readByte() / (double)scale); default: return(0); } }
public void Read(FileData d) { d.skip(8); // magic and section size d.skip(4); // 0 padding? unk1 = d.readInt(); d.skip(2); //0 unk2 = d.readUShort(); int ssize = d.readByte(); project = d.readString(d.pos(), ssize - 1); d.skip(ssize - 1); d.skip(6); unk3 = d.readUShort(); d.align(4); ssize = d.readByte(); timestamp = d.readString(d.pos(), ssize - 1); d.skip(ssize - 1); d.skip(4); }
public override void Read(string filename) { { { FileData d = new FileData(filename); var size1 = d.readUShort(); if (size1 > 255) { d.seek(0); d.Endian = Endianness.Little; size1 = d.readUShort(); } if (d.size() < 4) { return; } var size2 = d.readUShort(); List <short> Table1 = new List <short>(); for (int i = 0; i < size1; i++) { if (d.pos() + 2 > d.size()) { break; } Table1.Add(d.readShort()); } List <short> Table2 = new List <short>(); for (int i = 0; i < size2; i++) { if (d.pos() + 2 > d.size()) { break; } Table2.Add(d.readShort()); } Tables = new List <List <short> >(); Tables.Add(Table1); Tables.Add(Table2); } } }
public void Read(FileData d) { d.Endian = Endianness.Big; d.skip(4); header = new OMOHeader() { verHi = d.readUShort(), verLow = d.readUShort(), flags = d.readInt(), unk1 = d.readUShort(), boneCount = d.readUShort(), frameCount = d.readUShort(), frameSize = d.readUShort(), nodeOffset = d.readInt(), interOffset = d.readInt(), keyOffset = d.readInt() }; d.seek(header.nodeOffset); for (int i = 0; i < header.boneCount; i++) { OMONode node = new OMONode() { flags = d.readInt(), hash = (uint)d.readInt(), interOffset = d.readInt(), keyOffset = d.readInt() }; int temp = d.pos(); d.seek(header.interOffset + node.interOffset); Console.WriteLine(node.hash.ToString("x") + " " + (header.interOffset + node.interOffset).ToString("x")); node.Read(d); d.seek(temp); Nodes.Add(node); } d.seek(header.keyOffset); for (int i = 0; i < header.frameCount; i++) { OMOFrame frame = new OMOFrame(); // /2 because size of short for (int j = 0; j < header.frameSize / 2; j++) { frame.keys.Add(d.readUShort()); } Frames.Add(frame); } }
public void Read(FileData d) { Endian = Endianness.Big; d.Endian = Endian; uint magic = d.readUInt(); Version = d.readUShort(); if (magic == 0x4E545033) //NTP3 { ReadNTP3(d); } else if (magic == 0x4E545755) //NTWU { ReadNTWU(d); } else if (magic == 0x4E545744) //NTWD { Endian = Endianness.Little; d.Endian = Endian; ReadNTP3(d); } }
public void OpenMBN(FileData f) { f.Endian = Endianness.Little; f.seek(0); int format = f.readUShort(); f.skip(2);//0xFFFF int flags = f.readInt(); int mode = f.readInt(); int meshCount = f.readInt(); int length = 0; if (mode == 1) { //One Attribute int count = f.readInt(); for (int i = 0; i < count; i++) { VertexAttribute a = new VertexAttribute(); a.Read(f); attributes.Add(a); } length = f.readInt(); } // Get Mesh Nodes /*List<BCH_Mesh> meshes = new List<BCH_Mesh>(); * foreach(BCH_Mesh m in Nodes) * { * meshes.Add(m); * foreach (BCH_Mesh m2 in m.Nodes) * meshes.Add(m); * }*/ for (int i = 0; i < meshCount; i++) { BCH_Mesh m = (BCH_Mesh)Nodes[i]; int polyCount = f.readInt(); for (int j = 0; j < polyCount; j++) { BCH_PolyGroup pg = new BCH_PolyGroup(); m.Nodes.Add(pg); int nodeCount = f.readInt(); int[] nodeList = new int[nodeCount]; pg.BoneList = (nodeList); for (int k = 0; k < nodeCount; k++) { nodeList[k] = f.readInt(); } pg.Count = (f.readInt()); if ((flags & 2) > 0) { f.readInt(); } } } if (format != 4) { f.align(32); } int stride = 0; foreach (VertexAttribute a in attributes) { stride += _3DSGPU.getTypeSize(a.format) * _3DSGPU.getFormatSize(a.type); } // Vertex Bank vertices = new Vertex[length / (stride + stride % 2)]; for (int vi = 0; vi < vertices.Length; vi++) { Vertex v = new Vertex(); foreach (VertexAttribute a in attributes) { //f.align(2); a.ReadVertex(f, ref v); } vertices[vi] = v; } f.align(32); for (int i = 0; i < meshCount; i++) { BCH_Mesh m = (BCH_Mesh)Nodes[i]; int pi = 0; foreach (BCH_PolyGroup pg in m.Nodes) { pg.Text = "Polygroup_" + pi++; pg.Faces = new int[pg.Count]; for (int k = 0; k < pg.Count; k++) { pg.Faces[k] = f.readUShort(); } f.align(32); } } }
public void ReadNTWU(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); d.skip(1); byte mipmapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.readInt(); //Always 1? uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; int mipDataOffset = d.readInt() + headerPtr; int gtxHeaderOffset = d.readInt() + headerPtr; d.readInt(); int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int imageSize = 0; //Total size of first mipmap of every surface int mipSize = 0; //Total size of mipmaps other than the first of every surface if (mipmapCount == 1) { if (isCubemap) { imageSize = cmapSize1; } else { imageSize = dataSize; } } else { imageSize = d.readInt(); mipSize = d.readInt(); d.skip((mipmapCount - 2) * 4); d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HashId = d.readInt(); d.skip(4); // padding align 8 d.seek(gtxHeaderOffset); GTX.GX2Surface gtxHeader = new GTX.GX2Surface(); gtxHeader.dim = d.readInt(); gtxHeader.width = d.readInt(); gtxHeader.height = d.readInt(); gtxHeader.depth = d.readInt(); gtxHeader.numMips = d.readInt(); gtxHeader.format = d.readInt(); gtxHeader.aa = d.readInt(); gtxHeader.use = d.readInt(); gtxHeader.imageSize = d.readInt(); gtxHeader.imagePtr = d.readInt(); gtxHeader.mipSize = d.readInt(); gtxHeader.mipPtr = d.readInt(); gtxHeader.tileMode = d.readInt(); gtxHeader.swizzle = d.readInt(); gtxHeader.alignment = d.readInt(); gtxHeader.pitch = d.readInt(); //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset) //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1]) //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i]) int[] mipOffsets = new int[mipmapCount]; mipOffsets[0] = 0; for (byte mipLevel = 1; mipLevel < mipmapCount; ++mipLevel) { mipOffsets[mipLevel] = 0; mipOffsets[mipLevel] = mipOffsets[1] + d.readInt(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { tex.surfaces.Add(new TextureSurface()); } int w = tex.Width, h = tex.Height; for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { int p = gtxHeader.pitch / (gtxHeader.width / w); int size; if (mipmapCount == 1) { size = imageSize; } else if (mipLevel + 1 == mipmapCount) { size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel]; } else { size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel]; } size /= surfaceCount; for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size); //Real size //Leave the below line commented for now because it breaks RGBA textures //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8); if (size < (GTX.getBPP(gtxHeader.format) / 8)) { size = (GTX.getBPP(gtxHeader.format) / 8); } byte[] deswiz = GTX.swizzleBC( gtxHeader.data, w, h, gtxHeader.format, gtxHeader.tileMode, p, gtxHeader.swizzle ); tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size)); } w /= 2; h /= 2; if (w < 1) { w = 1; } if (h < 1) { h = 1; } } headerPtr += headerSize; Nodes.Add(tex); } }
public void ReadNTP3(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); if (Version == 0x100) { count -= 1; } d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.isDds = true; tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); //It might seem that mipmapCount and pixelFormat would be shorts, but they're bytes because they stay in the same place regardless of endianness d.skip(1); byte mipmapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.skip(4); uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; d.readInt(); d.readInt(); d.readInt(); //The size of a single cubemap face (discounting mipmaps). I don't know why it is repeated. If mipmaps are present, this is also specified in the mipSize section anyway. int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int[] mipSizes = new int[mipmapCount]; if (mipmapCount == 1) { if (isCubemap) { mipSizes[0] = cmapSize1; } else { mipSizes[0] = dataSize; } } else { for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { mipSizes[mipLevel] = d.readInt(); } d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HashId = d.readInt(); d.skip(4); // padding align 8 if (Version == 0x100) { dataOffset = d.pos(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { TextureSurface surface = new TextureSurface(); for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel) { byte[] texArray = d.getSection(dataOffset, mipSizes[mipLevel]); surface.mipmaps.Add(texArray); dataOffset += mipSizes[mipLevel]; } tex.surfaces.Add(surface); } if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17) { tex.SwapChannelOrderUp(); } headerPtr += headerSize; Nodes.Add(tex); } }
public static void process(FileData d, int type, int secOff, Animation.KeyNode node, String part, bool debug, Animation a) { int offset = d.readInt() + secOff; int temp = d.pos(); d.seek(offset); int max = 0; int fCount = -1; float scale = 0; float[] frame = null, step = null, tan = null; if (type == 0x1) { fCount = d.readUShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readByte(); int th = d.readThree(); step[i] = base2 + ((th >> 12) & 0xfff) * stepb; tan[i] = (FileData.sign12Bit(th & 0xfff) / 32f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x2) { fCount = d.readUShort(); d.skip(2); scale = d.readFloat(); float stepb = d.readFloat(); float base2 = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readUShort() / 32f; step[i] = base2 + d.readUShort() * stepb; tan[i] = (d.readShort() / 256f); if (frame[i] > max) { max = (int)frame[i]; } } } if (type == 0x3) { //if(debug) //System.out.println(part + "\tInterpolated 12 " + Integer.toHexString(offset)); fCount = d.readUShort(); d.skip(2); scale = d.readFloat(); frame = new float[fCount]; step = new float[fCount]; tan = new float[fCount]; for (int i = 0; i < fCount; i++) { frame[i] = d.readFloat(); step[i] = d.readFloat(); tan[i] = d.readFloat(); if (frame[i] > max) { max = (int)frame[i]; } } } //a.FrameCount = max; float degrad = (float)(Math.PI / 180f); if (frame != null) { for (int i = 0; i < fCount; i++) { Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.HERMITE; f.Value = step[i]; f.Frame = frame[i]; f.In = tan[i]; switch (part) { case "RX": f.Value = step[i] * degrad; node.XROT.Keys.Add(f); f.Degrees = true; break; case "RY": f.Value = step[i] * degrad; node.YROT.Keys.Add(f); f.Degrees = true; break; case "RZ": f.Value = step[i] * degrad; node.ZROT.Keys.Add(f); f.Degrees = true; break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } if (type == 0x4) { float stepb = d.readFloat(); float base2 = d.readFloat(); for (int i = 0; i < a.FrameCount; i++) { float v = base2 + stepb * (d.readByte()); Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.LINEAR; f.Value = v; f.Frame = i; switch (part) { case "RX": f.Value = v * degrad; node.XROT.Keys.Add(f); break; case "RY": f.Value = v * degrad; node.YROT.Keys.Add(f); break; case "RZ": f.Value = v * degrad; node.ZROT.Keys.Add(f); break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } if (type == 0x6) { for (int i = 0; i < a.FrameCount; i++) { float v = d.readFloat(); Animation.KeyFrame f = new Animation.KeyFrame(); f.InterType = Animation.InterpolationType.LINEAR; f.Value = v; f.Frame = i; switch (part) { case "RX": f.Value = v * degrad; node.XROT.Keys.Add(f); break; case "RY": f.Value = v * degrad; node.YROT.Keys.Add(f); break; case "RZ": f.Value = v * degrad; node.ZROT.Keys.Add(f); break; case "X": node.XPOS.Keys.Add(f); break; case "Y": node.YPOS.Keys.Add(f); break; case "Z": node.ZPOS.Keys.Add(f); break; case "SX": node.XSCA.Keys.Add(f); break; case "SY": node.YSCA.Keys.Add(f); break; case "SZ": node.ZSCA.Keys.Add(f); break; } } } d.seek(temp); }
public static Animation readAnim(FileData d, VBN m) { int offset = d.readInt(); int nameoff = d.readInt(); d.skip(4); int fCount = d.readUShort(); int animDataCount = d.readUShort(); d.skip(8); Animation anim = new Animation(d.readString(nameoff, -1)); anim.FrameCount = fCount; //anim.setModel(m); d.seek(offset); int sectionOffset = d.readInt() + offset; int size = d.readInt(); // size again for (int i = 0; i < size; i++) { // System.out.print(d.readShort()); // id d.skip(4); // id and unknown d.readUShort(); //left d.readUShort(); //right int nameOffset = d.readInt() + offset; int dataOffset = d.readInt() + offset; if (dataOffset == offset) { i--; continue; // d.skip(8); // nameOffset = d.readInt() + 4; // dataOffset = d.readInt() + offset; } int temp = d.pos(); d.seek(dataOffset); int pos = d.pos(); int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4; int flags = d.readInt(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; Animation.KeyNode node = new Animation.KeyNode(d.readString(nameOff, -1)); anim.Bones.Add(node); node.RotType = Animation.RotationType.EULER; if (hasS == 1) { if (Siso == 1) { float iss = d.readFloat(); node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (SXfixed == 1) { node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SX", false, anim); } if (SYfixed == 1) { node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SY", false, anim); } if (SZfixed == 1) { node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SZ", false, anim); } } } if (hasR == 1) { if (Riso == 1) { float iss = (float)((d.readFloat()) * Math.PI / 180f); node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (RXfixed == 1) { node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RX", false, anim); } if (RYfixed == 1) { node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RY", false, anim); } if (RZfixed == 1) { node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RZ", false, anim); } } } if (hasT == 1) { if (Tiso == 1) { float iss = d.readFloat(); node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (Xfixed == 1) { node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "X", false, anim); } if (Yfixed == 1) { node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Y", false, anim); } if (Zfixed == 1) { node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Z", false, anim); } } } d.seek(temp); } return(anim); }
public static Animation read(FileData d) { d.Endian = Endianness.Big; d.skip(4); // header OMO d.skip(4); // two shorts, idk d.skip(4); //flags? d.skip(2); int boneCount = d.readUShort(); int frameCount = d.readUShort(); int frameSize = d.readUShort(); int offset1 = d.readInt(); // nodeOffset int offset2 = d.readInt(); // interOffset int offset3 = d.readInt(); // keyOffset SkelAnimation anim = new SkelAnimation(); anim.Tag = d; if (boneCount > offset2 / 0x10) { boneCount = offset2 / 0x10; anim.Tag = null; } // base frames // These are linked to bones via hashes d.seek(offset1); // int[] framekey = new int[boneCount]; KeyNode[] baseNode = new KeyNode[boneCount]; // Start positions for bones/nodes for (int i = 0; i < boneCount; i++) { flagsused = flagsused | d.readInt(); d.seek(d.pos() - 4); //Console.WriteLine(flagsused.ToString("x")); int flags = d.readByte(); int tFlag = d.readByte(); int rFlag = d.readByte(); int sFlag = d.readByte(); int hash = d.readInt(); // used to find the identifying bone int off1 = d.readInt() + offset2; framekey[i] = d.readInt(); bool hasTrans = (flags & 0x01) == 0x01; bool hasScale = (flags & 0x04) == 0x04; bool hasRot = (flags & 0x02) == 0x02; KeyNode node = new KeyNode(); baseNode[i] = node; node.hash = (uint)hash; int temp = d.pos(); d.seek(off1); if (hasTrans) { if (tFlag == 0x8) { // interpolated node.t_type = KeyNode.INTERPOLATED; node.t = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.t2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } else if (tFlag == 0x20) { node.t_type = KeyNode.CONSTANT; node.t = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } else if (tFlag == 0x4) { // entire Vector3 provided in keyframe data i.e. KEYFRAME type node.t_type = KeyNode.KEYFRAME; } } if (hasRot) { if ((rFlag & 0xF0) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0) { //Console.WriteLine(rFlag); } if ((rFlag & 0xF0) == 0xA0) { // All data is in the keyframe for this type node.r_type = KeyNode.COMPRESSED; } if ((rFlag & 0xF0) == 0x50) { // interpolated node.r_type = KeyNode.INTERPOLATED; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.rv2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } if ((rFlag & 0xF0) == 0x60) { node.r_type = KeyNode.KEYFRAME; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.r_extra = d.readFloat() / 65535; } if ((rFlag & 0xF0) == 0x70) { node.r_type = KeyNode.CONSTANT; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } if (hasScale) { if ((sFlag & 0xF0) == 0x80) { // interpolated node.s_type = KeyNode.INTERPOLATED; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); node.s2 = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } // TODO: investigate the difference between these if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03) { // constant node.s_type = KeyNode.CONSTANT; node.s = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); } } d.seek(temp); } // Interpolated type below here is always a set translation/rotation/scale // from the coords specified with the bone node above Animation a = new Animation("Anim"); a.Tag = anim.Tag; a.FrameCount = frameCount; d.seek(offset3); for (int j = 0; j < boneCount; j++) { string bid = ""; int hash = -1; if (!MainForm.Hashes.ids.TryGetValue(baseNode[j].hash, out bid)) { hash = (int)baseNode[j].hash; } Animation.KeyNode n = new Animation.KeyNode(bid); n.Hash = hash; a.Bones.Add(n); n.Type = Animation.BoneType.NORMAL; /*foreach (ModelContainer con in Runtime.ModelContainers) * if (con.VBN != null) * bid = con.VBN.getBone(baseNode[j].hash) == null ? "" : con.VBN.getBone(baseNode[j].hash).Text;*/ for (int i = 0; i < a.FrameCount; i++) { d.seek(offset3 + frameSize * i + framekey[j]); if (baseNode[j].t_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readUShort() / 0xffff); float i2 = ((float)d.readUShort() / 0xffff); float i3 = ((float)d.readUShort() / 0xffff); float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1)); float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2)); float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3)); //node.t = new Vector3(x, y, z); // Translation n.XPOS.Keys.Add(new Animation.KeyFrame(x, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i)); } else if (baseNode[j].t_type == KeyNode.CONSTANT) { //node.t = baseNode[j].t; n.XPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.X, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Z, i)); } else if (baseNode[j].t_type == 2) { float x = d.readFloat(); float y = d.readFloat(); float z = d.readFloat(); //node.t = new Vector3(x, y, z); n.XPOS.Keys.Add(new Animation.KeyFrame(x, i)); n.YPOS.Keys.Add(new Animation.KeyFrame(y, i)); n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i)); } if (baseNode[j].r_type == KeyNode.COMPRESSED) { // There are 64 bits present for each node of this rot type // The format is: 20bits * 3 of encoded floats, and 4 bits of flags // The flags describe which 3 components of the quaternion are being presented int b1 = d.readByte(); int b2 = d.readByte(); int b3 = d.readByte(); int b4 = d.readByte(); int b5 = d.readByte(); int b6 = d.readByte(); int b7 = d.readByte(); int b8 = d.readByte(); // Capture 20 bits at a time of the raw data int f1 = (b1 << 12) | (b2 << 4) | ((b3 & 0xF0) >> 4); int f2 = ((b3 & 0xF) << 16) | (b4 << 8) | b5; int f3 = (b6 << 12) | (b7 << 4) | ((b8 & 0xF0) >> 4); int flags = b8 & 0xF; Quaternion r = new Quaternion(); switch (flags) { case 0: // y, z, w provided r.Y = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.X = (float)Math.Sqrt(Math.Abs(1 - (r.Y * r.Y + r.Z * r.Z + r.W * r.W))); break; case 1: // x, z, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Z = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Y = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Z * r.Z + r.W * r.W))); break; case 2: // x, y, w provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.W = encodedRot10ToQuaternionComponent(f3); r.Z = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.W * r.W))); break; case 3: // x, y, z, provided r.X = encodedRot10ToQuaternionComponent(f1); r.Y = encodedRot10ToQuaternionComponent(f2); r.Z = encodedRot10ToQuaternionComponent(f3); r.W = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.Z * r.Z))); break; default: Console.WriteLine("Unknown rotation type3 flags: " + flags); break; } n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].r_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readUShort() / (0xffff)); float i2 = ((float)d.readUShort() / (0xffff)); float i3 = ((float)d.readUShort() / (0xffff)); float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1)); float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2)); float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3)); float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(new Vector3(x, y, z), w); r.Normalize(); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else if (baseNode[j].r_type == KeyNode.KEYFRAME) { float scale = d.readUShort() * baseNode[j].r_extra; float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z + scale; float w = rot6CalculateW(x, y, z); Quaternion r = new Quaternion(x, y, z, w); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } else { float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z; float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z))); Quaternion r = new Quaternion(baseNode[j].rv, w); r.Normalize(); n.RotType = Animation.RotationType.QUATERNION; n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i)); n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i)); n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i)); n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i)); } if (baseNode[j].s_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readUShort() / (0xffff)); float i2 = ((float)d.readUShort() / (0xffff)); float i3 = ((float)d.readUShort() / (0xffff)); float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1)); float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2)); float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3)); //node.s = new Vector3(x, y, z); n.XSCA.Keys.Add(new Animation.KeyFrame(x, i)); n.YSCA.Keys.Add(new Animation.KeyFrame(y, i)); n.ZSCA.Keys.Add(new Animation.KeyFrame(z, i)); } else { //node.s = baseNode[j].s; n.XSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.X, i)); n.YSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Y, i)); n.ZSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Z, i)); } } } return(a); }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); int backwardCompatibility = f.readByte(); int forwardCompatibility = f.readByte(); int version = f.readUShort(); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandsOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendedOffset = 0; int dataExtendedLength = 0; if (backwardCompatibility > 0x20) { dataExtendedOffset = f.readInt(); } int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandsLength = f.readInt(); int dataLength = f.readInt(); if (backwardCompatibility > 0x20) { dataExtendedLength = f.readInt(); } int relocationTableLength = f.readInt(); int uninitializedDataSectionLength = f.readInt(); int uninitializedDescriptionSectionLength = f.readInt(); if (backwardCompatibility > 7) { int flags = f.readUShort(); int addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < relocationTableLength; i += 4) { f.seek(relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset); break; case 1: f.seek(off + mainHeaderOffset); f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset); break; case 2: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset); break; } f.seek((off * 4) + gpuCommandsOffset); if (backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } //File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size())); f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt(); int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt(); int materialsPointerTableOffset = f.readInt(); int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int shadersPointerTableOffset = f.readInt(); int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt(); int texturesPointerTableOffset = f.readInt(); int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt(); int materialsLUTPointerTableOffset = f.readInt(); int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt(); int lightsPointerTableOffset = f.readInt(); int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt(); int camerasPointerTableOffset = f.readInt(); int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt(); int fogsPointerTableOffset = f.readInt(); int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt(); int skeletalAnimationsPointerTableOffset = f.readInt(); int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt(); int materialAnimationsPointerTableOffset = f.readInt(); int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt(); int visibilityAnimationsPointerTableOffset = f.readInt(); int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt(); int lightAnimationsPointerTableOffset = f.readInt(); int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt(); int cameraAnimationsPointerTableOffset = f.readInt(); int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt(); int fogAnimationsPointerTableOffset = f.readInt(); int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt(); int scenePointerTableOffset = f.readInt(); int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt(); Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : ""); Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : ""); Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : ""); Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : ""); Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : ""); Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : ""); Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : ""); Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : ""); Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : ""); Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : ""); Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : ""); Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : ""); Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : ""); Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : ""); Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : ""); // Textures for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); // one for each mip I assume int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int textureCommandsOffset2 = f.readInt(); int textureCommandsWordCount2 = f.readInt(); int textureCommandsOffset3 = f.readInt(); int textureCommandsWordCount3 = f.readInt(); int unk = f.readInt(); BCH_Texture tex = new BCH_Texture(); tex.Text = f.readString(f.readInt(), -1); Textures.Nodes.Add(tex); f.seek(textureCommandsOffset); tex.ReadParameters(f, textureCommandsWordCount); } //Models for (int index = 0; index < modelsPointerTableEntries; index++) { f.seek(modelsPointerTableOffset + (index * 4)); f.seek(f.readInt()); BCH_Model model = new BCH_Model(); Models.Nodes.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readUShort(); model.worldTransform = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); model.Text = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); int rootLeftNode = f.readUShort(); int rootRightNode = f.readUShort(); int rootNameOffset = f.readInt(); //Console.WriteLine(rootReferenceBit.ToString("x") + " " + f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode); // Object name tree Radix Tree for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = f.readShort(); short rightNode = f.readShort(); objectName[i] = f.readString(f.readInt(), -1); Console.WriteLine((referenceBit >> 3) + " " + (referenceBit & 0x7) + " " + objectName[i] + " " + leftNode + " " + rightNode); } //TODO: Metadata, boundingbox, normal mesh, materials f.seek(verticesTableOffset); Dictionary <int, BCH_Mesh> MeshIndex = new Dictionary <int, BCH_Mesh>(); int nim = 0; for (int i = 0; i < verticesTableEntries; i++) { BCH_Mesh Mesh = new BCH_Mesh(); Mesh.MaterialIndex = f.readUShort(); int mflags = f.readUShort(); int meshId = f.readUShort(); if (!MeshIndex.ContainsKey(meshId)) { MeshIndex.Add(meshId, Mesh); Mesh.Text = nim < objectName.Length ? objectName[nim++] : i + ""; model.Nodes.Add(Mesh); } else { BCH_Mesh m = MeshIndex[meshId]; Mesh.Text = m.Text; model.Nodes.Insert(model.Nodes.IndexOf(m) - 1, Mesh); } // node visibility TODO: finish... Mesh.Checked = ((nodeVisibility & (1 << i)) > 0); Mesh.renderPriority = f.readUShort(); int vshAttBufferCommandOffset = f.readInt(); int vshAttBufferCommandCount = f.readInt(); int faceOffset = f.readInt(); int faceCount = f.readInt(); int vshAttBufferCommandOffsetEx = f.readInt(); int vshAttBufferCommandCountEx = f.readInt(); Vector3 Center = new Vector3(f.readFloat(), f.readFloat(), f.readFloat()); int flagoffset = f.readInt(); // flagsOffset f.skip(4); // 0? int boundingBoxOffset = f.readInt(); } //Materials Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x")); for (int i = 0; i < materialsTableEntries; i++) { f.seek(materialsTableOffset + (i * 0x2c)); int paramOffset = f.readInt(); f.skip(12); // other offsets int texCommandOffset = f.readInt(); int texCommandCount = f.readInt(); int mapperOffset = f.readInt(); BCH_Material mat = new BCH_Material(); Materials.Nodes.Add(mat); mat.Text = f.readString(f.readInt(), -1); Console.WriteLine(mat.Text); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); // TODO: Parameters } //Skeleton f.seek(skeletonOffset); for (int bindex = 0; bindex < skeletonEntries; bindex++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = f.readShort(); short boneSpace = f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); int metaDataPointerOffset2 = f.readInt(); if (metaDataPointerOffset2 != 0) { int position = f.pos(); f.seek(metaDataPointerOffset2); //bone.userData = getMetaData(input); f.seek(position); } model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public void ReadNTWU(FileData d) { d.seek(0x4); Version = d.readUShort(); ushort count = d.readUShort(); d.skip(0x8); int headerPtr = 0x10; for (ushort i = 0; i < count; ++i) { d.seek(headerPtr); NutTexture tex = new NutTexture(); tex.type = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(2); d.skip(1); byte mipMapCount = d.readByte(); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.readInt(); //Always 1? uint caps2 = d.readUInt(); bool isCubemap = false; byte surfaceCount = 1; if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP) { //Only supporting all six faces if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) { isCubemap = true; surfaceCount = 6; } else { throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HASHID:X}. Six faces are required."); } } int dataOffset = d.readInt() + headerPtr; int mipDataOffset = d.readInt() + headerPtr; int gtxHeaderOffset = d.readInt() + headerPtr; d.readInt(); int cmapSize1 = 0; int cmapSize2 = 0; if (isCubemap) { cmapSize1 = d.readInt(); cmapSize2 = d.readInt(); d.skip(8); } int imageSize = 0; //Total size of first mipmap of every surface int mipSize = 0; //Total size of mipmaps other than the first of every surface if (mipMapCount == 1) { if (isCubemap) { imageSize = cmapSize1; } else { imageSize = dataSize; } } else { imageSize = d.readInt(); mipSize = d.readInt(); d.skip((mipMapCount - 2) * 4); d.align(0x10); } d.skip(0x10); //eXt data - always the same d.skip(4); //GIDX d.readInt(); //Always 0x10 tex.HASHID = d.readInt(); d.skip(4); // padding align 8 d.seek(gtxHeaderOffset); GTX.GX2Surface gtxHeader = new GTX.GX2Surface(); gtxHeader.dim = d.readInt(); gtxHeader.width = d.readInt(); gtxHeader.height = d.readInt(); gtxHeader.depth = d.readInt(); gtxHeader.numMips = d.readInt(); gtxHeader.format = d.readInt(); gtxHeader.aa = d.readInt(); gtxHeader.use = d.readInt(); gtxHeader.imageSize = d.readInt(); gtxHeader.imagePtr = d.readInt(); gtxHeader.mipSize = d.readInt(); gtxHeader.mipPtr = d.readInt(); gtxHeader.tileMode = d.readInt(); gtxHeader.swizzle = d.readInt(); gtxHeader.alignment = d.readInt(); gtxHeader.pitch = d.readInt(); //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset) //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1]) //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i]) int[] mipOffsets = new int[mipMapCount]; mipOffsets[0] = 0; for (byte mipLevel = 1; mipLevel < mipMapCount; ++mipLevel) { mipOffsets[mipLevel] = 0; mipOffsets[mipLevel] = mipOffsets[1] + d.readInt(); } for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { tex.surfaces.Add(new TextureSurface()); } int w = tex.Width, h = tex.Height; for (byte mipLevel = 0; mipLevel < mipMapCount; ++mipLevel) { int p = gtxHeader.pitch / (gtxHeader.width / w); int size; if (mipMapCount == 1) { size = imageSize; } else if (mipLevel + 1 == mipMapCount) { size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel]; } else { size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel]; } size /= surfaceCount; for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel) { gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size); //Real size //Leave the below line commented for now because it breaks RGBA textures //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8); if (size < (GTX.getBPP(gtxHeader.format) / 8)) { size = (GTX.getBPP(gtxHeader.format) / 8); } byte[] deswiz = GTX.swizzleBC( gtxHeader.data, w, h, gtxHeader.format, gtxHeader.tileMode, p, gtxHeader.swizzle ); tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size)); } w /= 2; h /= 2; if (w < 1) { w = 1; } if (h < 1) { h = 1; } } headerPtr += headerSize; Nodes.Add(tex); } RefreshGlTexturesByHashId(); //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + dataSize - dataOffset : size)); //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle); //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel)); //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray); //Console.WriteLine(GL.GetError()); /*int j = 0; * foreach(byte[] b in textures[0].mipmaps) * { * if (j == 3) * { * for(int w = 3; w < 8; w++) * { * for (int p = 3; p < 6; p++) * { * byte[] deswiz = GTX.swizzleBC( * b, * (int)Math.Pow(2, w), * 64, * 51, * 4, * (int)Math.Pow(2, p), * 197632 * ); * File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz); * } * } * * } * j++; * }*/ }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++) { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Debug.WriteLine("Animation Name: " + skeletalAnimationName); //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X")); //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X")); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); OSkeletalAnimationBone bone = new OSkeletalAnimationBone(); f.seek(offset); bone.name = f.readString(f.readInt(), -1); Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); int flags = f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0x18); int notExistMask = 0x80000; int constantMask = 0x200; for (int j = 0; j < 2; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup(); frame.exists = !notExist; if (frame.exists) { if (constant) { frame.interpolation = OInterpolationMode.linear; frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0)); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); //getAnimationKeyFrame(input, frame); f.seek(position); } } else { f.seek(f.pos() + 0x04); } if (j == 0) { switch (axis) { case 0: bone.rotationX = frame; break; case 1: bone.rotationY = frame; break; case 2: bone.rotationZ = frame; break; } } else { switch (axis) { case 0: bone.translationX = frame; break; case 1: bone.translationY = frame; break; case 2: bone.translationZ = frame; break; } } notExistMask <<= 1; constantMask <<= 1; } constantMask <<= 1; } break; case OSegmentType.transformQuaternion: bone.isFrameFormat = true; int scaleOffset = f.readInt(); int rotationOffset = f.readInt(); int translationOffset = f.readInt(); if ((flags & 0x20) == 0) { bone.scale.exists = true; f.seek(scaleOffset); if ((flags & 4) > 0) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.scale.startFrame = f.readFloat(); bone.scale.endFrame = f.readFloat(); int scaleFlags = f.readInt(); int scaleDataOffset = f.readInt(); int scaleEntries = f.readInt(); f.seek(scaleDataOffset); for (int j = 0; j < scaleEntries; j++) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } if ((flags & 0x10) == 0) { bone.rotationQuaternion.exists = true; f.seek(rotationOffset); if ((flags & 2) > 0) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } else { bone.rotationQuaternion.startFrame = f.readFloat(); bone.rotationQuaternion.endFrame = f.readFloat(); int rotationFlags = f.readInt(); int rotationDataOffset = f.readInt(); int rotationEntries = f.readInt(); f.seek(rotationDataOffset); for (int j = 0; j < rotationEntries; j++) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } } } if ((flags & 8) == 0) { bone.translation.exists = true; f.seek(translationOffset); if ((flags & 1) > 0) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.translation.startFrame = f.readFloat(); bone.translation.endFrame = f.readFloat(); int translationFlags = f.readInt(); int translationDataOffset = f.readInt(); int translationEntries = f.readInt(); f.seek(translationDataOffset); for (int j = 0; j < translationEntries; j++) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } break; case OSegmentType.transformMatrix: bone.isFullBakedFormat = true; f.readInt(); f.readInt(); int matrixOffset = f.readInt(); int entries = f.readInt(); f.seek(matrixOffset); for (int j = 0; j < entries; j++) { /*OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform);*/ } break; default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); } //skeletalAnimation.bone.Add(bone); } } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.Height = f.readUShort(); tex.Width = f.readUShort(); f.skip(12); int doffset = f.readInt(); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type); //Texture texture = new Texture2D(tex.texture); //tex.display = texture.Id; } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readUShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); String name = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readUShort(); int rootRightNode = f.readUShort(); int rootNameOffset = f.readInt(); for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = f.readShort(); short rightNode = f.readShort(); objectName[i] = f.readString(f.readInt(), -1); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readUShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readUShort(); mbn.mesh[index].Text = objectName[nameId]; // node visibility TODO: finish... mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readUShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = f.readShort(); short boneSpace = f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data bones.bones.Add(bone); model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public static AnimationGroupNode Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = filename }; for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)// { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Runtime.Animations.Add(skeletalAnimationName, a); //MainForm.animNode.Nodes.Add(skeletalAnimationName); //Debug.WriteLine("Animation Name: " + skeletalAnimationName); Animation a = new Animation(skeletalAnimationName); ThisAnimation.Nodes.Add(a); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); f.seek(offset); bone.Text = f.readString(f.readInt(), -1); //Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); uint flags = (uint)f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); //Debug.WriteLine(bone.Text + " " + flags.ToString("x")); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0xC); //Console.WriteLine(f.pos().ToString("x") + " " + flags.ToString("x")); uint notExistMask = 0x10000; uint constantMask = 0x40; for (int j = 0; j < 3; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; //Console.WriteLine(notExist + " " + constant); Animation.KeyGroup group = new Animation.KeyGroup(); //frame.exists = !notExist; if (!notExist) { if (constant) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.LINEAR; frame.Value = f.readFloat(); frame.Frame = 0; group.Keys.Add(frame); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); float c = 0; //Debug.WriteLine(j + " " + axis + " " + bone.Text); getAnimationKeyFrame(f, group, out c); if (c > a.FrameCount) { a.FrameCount = (int)c; } f.seek(position); } } else { f.seek(f.pos() + 0x04); } bone.RotType = Animation.RotationType.EULER; if (j == 0) { switch (axis) { case 0: bone.XSCA = group; break; case 1: bone.YSCA = group; break; case 2: bone.ZSCA = group; break; } } else if (j == 1) { switch (axis) { case 0: bone.XROT = group; break; case 1: bone.YROT = group; break; case 2: bone.ZROT = group; break; } } else if (j == 2) { switch (axis) { case 0: bone.XPOS = group; break; case 1: bone.YPOS = group; break; case 2: bone.ZPOS = group; break; } } notExistMask <<= 1; constantMask <<= 1; } if (j == 1) { constantMask <<= 1; } } break; /*case OSegmentType.transformQuaternion: * bone.isFrameFormat = true; * * int scaleOffset = f.readInt(); * int rotationOffset = f.readInt(); * int translationOffset = f.readInt(); * * if ((flags & 0x20) == 0) * { * bone.scale.exists = true; * f.seek(scaleOffset); * * if ((flags & 4) > 0) * { * bone.scale.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * else * { * bone.scale.startFrame = f.readFloat(); * bone.scale.endFrame = f.readFloat(); * * int scaleFlags = f.readInt(); * int scaleDataOffset = f.readInt(); * int scaleEntries = f.readInt(); * * f.seek(scaleDataOffset); * for (int j = 0; j < scaleEntries; j++) * { * bone.scale.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * } * } * * if ((flags & 0x10) == 0) * { * bone.rotationQuaternion.exists = true; * f.seek(rotationOffset); * * if ((flags & 2) > 0) * { * bone.rotationQuaternion.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * f.readFloat())); * } * else * { * bone.rotationQuaternion.startFrame = f.readFloat(); * bone.rotationQuaternion.endFrame = f.readFloat(); * * int rotationFlags = f.readInt(); * int rotationDataOffset = f.readInt(); * int rotationEntries = f.readInt(); * * f.seek(rotationDataOffset); * for (int j = 0; j < rotationEntries; j++) * { * bone.rotationQuaternion.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * f.readFloat())); * } * } * } * * if ((flags & 8) == 0) * { * bone.translation.exists = true; * f.seek(translationOffset); * * if ((flags & 1) > 0) * { * bone.translation.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * else * { * bone.translation.startFrame = f.readFloat(); * bone.translation.endFrame = f.readFloat(); * * int translationFlags = f.readInt(); * int translationDataOffset = f.readInt(); * int translationEntries = f.readInt(); * * f.seek(translationDataOffset); * for (int j = 0; j < translationEntries; j++) * { * bone.translation.vector.Add(new Vector4( * f.readFloat(), * f.readFloat(), * f.readFloat(), * 0)); * } * } * } * * break; * case OSegmentType.transformMatrix: * bone.isFullBakedFormat = true; * * f.readInt(); * f.readInt(); * int matrixOffset = f.readInt(); * int entries = f.readInt(); * * f.seek(matrixOffset); * for (int j = 0; j < entries; j++) * { * OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform); * } * * break;*/ default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.Text)); } //skeletalAnimation.bone.Add(bone); } } //return a; return(ThisAnimation); }
public void Read(FileData f) { f.Endian = Endianness.Little; f.seek(4); int count = f.readInt(); f.skip(12); int dataCount = f.readInt(); int boneCount = f.readInt(); int hashCount = f.readInt(); int hashOffset = f.readInt() + 0x28; f.skip(4); int pos = f.pos(); f.seek(hashOffset); csvHashes csv = new csvHashes(Path.Combine(MainForm.executableDir, "hashTable.csv")); List <string> bonename = new List <string>(); for (int i = 0; i < hashCount; i++) { uint hash = (uint)f.readInt(); Console.WriteLine(csv.ids[hash]); bonename.Add(csv.ids[hash]); } f.seek(pos); Console.WriteLine("Count " + count); for (int i = 0; i < dataCount; i++) { Console.WriteLine("Bone " + i + " start at " + f.pos().ToString("x")); // 3 sections int secLength = f.readInt(); int someCount = f.readInt(); // usually 2? for (int sec = 0; sec < 5; sec++) { int size = f.readInt(); int id = f.readInt(); Console.WriteLine(id + ":\t" + size.ToString("x")); for (int j = 0; j < ((size - 1) / 4) - 1; j++) { if (id == 4) { short b1 = f.readShort(); short b2 = f.readShort(); Console.Write("\t" + (b1 == -1 ? b1 + "" : bonename[b1]) + " " + b2 + "\t"); } else if (id == 5) { short b1 = f.readShort(); short b2 = f.readShort(); Console.Write("\t" + (b1 == -1 ? b1 + "" : bonename[b1]) + " " + (b2 == -1 ? b2 + "" : bonename[b2]) + "\t"); } else { Console.Write("\t" + (f.readUShort() / (id == 7 ? (float)0xffff : 1)) + " " + (f.readUShort() / (id == 7 ? (float)0xffff : 1)) + "\t"); } } Console.WriteLine(); } f.skip(8); } Console.WriteLine("0x" + f.pos().ToString("X")); f.skip(8); int hashSize = f.readInt(); int unk = f.readInt(); }
public void ReadNTP3(FileData d) { Version = d.readUShort(); int count = d.readUShort(); d.skip(0x8); if (Version == 0x100) { count -= 1; } int dataPtr = 0; for (int i = 0; i < count; i++) { //Debug.WriteLine(d.pos().ToString("x")); NutTexture tex = new NutTexture(); tex.type = PixelInternalFormat.Rgba32ui; int totalSize = d.readInt(); d.skip(4); // padding int dataSize = d.readInt(); int headerSize = d.readUShort(); d.skip(3); int numMips = d.readByte(); //Debug.WriteLine(numMips); d.skip(1); tex.setPixelFormatFromNutFormat(d.readByte()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.skip(8); // padding? int dataOffset = d.readInt() + dataPtr + 0x10; d.skip(0x0C); int[] mipSizes = new int[numMips]; if (numMips == 1) { mipSizes[0] = dataSize; } else { for (int j = 0; j < numMips; j++) { mipSizes[j] = d.readInt(); } } d.align(16); d.skip(0x18); tex.HASHID = d.readInt(); d.skip(4); // padding align 8 if (Version == 0x100) { dataOffset = d.pos(); } // add mipmap data for (int miplevel = 0; miplevel < numMips; miplevel++) { byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]); //Debug.WriteLine(texArray.Length.ToString("x")); tex.mipmaps.Add(texArray); dataOffset += mipSizes[miplevel]; } dataPtr += headerSize; if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17) { Console.WriteLine("Endian swap"); // swap foreach (byte[] mip in tex.mipmaps) { for (int t = 0; t < mip.Length; t += 4) { byte t1 = mip[t]; mip[t] = mip[t + 1]; mip[t + 1] = mip[t + 2]; mip[t + 2] = mip[t + 3]; mip[t + 3] = t1; /*byte t1 = mip[t]; * byte t2 = mip[t+1]; * mip[t] = mip[t + 3]; * mip[t + 1] = mip[t + 2]; * mip[t + 2] = t2; * mip[t + 3] = t1;*/ } } } Nodes.Add(tex); /*for (int miplevel = 0; miplevel < numMips; miplevel++) * { * byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]); * * if (tex.getNutFormat() == 14) * { * byte[] oldArray = texArray; * for (int pos = 0; pos < mipSizes[miplevel]; pos+=4) * { * * for (int p = 0; p < 4; p++) * { * if (p == 0) * texArray[pos + 3] = oldArray[pos]; * else * texArray[pos + p - 1] = oldArray[pos + p]; * } * * } * } * tex.mipmaps.Add(texArray); * dataOffset += mipSizes[miplevel]; * }*/ } foreach (NutTexture tex in Nodes) { if (!draw.ContainsKey(tex.HASHID)) { draw.Add(tex.HASHID, loadImage(tex, true)); } } }
/** * Reading and saving -------------------- **/ public override void Read(string filename) { FileData d = new FileData(filename); d.seek(0); d.Endian = Endianness.Little; format = d.readUShort(); unknown = d.readUShort(); flags = d.readInt(); mode = d.readInt(); bool hasNameTable = (flags & 2) > 0; int polyCount = d.readInt(); mesh = new List <Mesh>(); descript = new List <Descriptor>(); List <List <int> > prim = new List <List <int> >(); for (int i = 0; i < polyCount; i++) { if (i == 0 && mode == 1) { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } Mesh m = new Mesh(); mesh.Add(m); int faceCount = d.readInt(); List <int> prims = new List <int>(); prim.Add(prims); for (int j = 0; j < faceCount; j++) { int nodeCount = d.readInt(); List <int> nodeList = new List <int>(); m.nodeList.Add(nodeList); for (int k = 0; k < nodeCount; k++) { nodeList.Add(d.readInt()); // for a node list? } int primitiveCount = d.readInt(); prims.Add(primitiveCount); if (hasNameTable) { int nameId = d.readInt(); } if (mode == 0) { if (format == 4) { int[] buffer = new int[primitiveCount]; for (int k = 0; k < primitiveCount; k++) { buffer[k] = d.readUShort(); } d.align(4); List <int> buf = new List <int>(); buf.AddRange(buffer); m.faces.Add(buf); } else { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } } } } if (mode == 0) { //Console.WriteLine("Extra!"); } // TODO: STRING TABLE if (hasNameTable) { for (int i = 0; i < mesh.Count; i++) { int index = d.readByte(); nameTable.Add(d.readString()); } } if (format != 4) { d.align(32); } // Vertex Bank int start = d.pos(); for (int i = 0; i < 1; i++) { if (mode == 0 || i == 0) { Descriptor des = descript[i]; if (format != 4) { while (d.pos() < start + des.length) { Vertex v = new Vertex(); vertices.Add(v); for (int k = 0; k < des.type.Length; k++) { d.align(2); switch (des.type[k]) { case 0: //Position v.pos.X = readType(d, des.format[k], des.scale[k]); v.pos.Y = readType(d, des.format[k], des.scale[k]); v.pos.Z = readType(d, des.format[k], des.scale[k]); break; case 1: //Normal v.nrm.X = readType(d, des.format[k], des.scale[k]); v.nrm.Y = readType(d, des.format[k], des.scale[k]); v.nrm.Z = readType(d, des.format[k], des.scale[k]); break; case 2: //Color v.col.X = (int)(readType(d, des.format[k], des.scale[k])); v.col.Y = (int)(readType(d, des.format[k], des.scale[k])); v.col.Z = (int)(readType(d, des.format[k], des.scale[k])); v.col.W = (int)(readType(d, des.format[k], des.scale[k])); break; case 3: //Tex0 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 4: //Tex1 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 5: //Bone Index v.node.Add(d.readByte()); v.node.Add(d.readByte()); break; case 6: //Bone Weight v.weight.Add(readType(d, des.format[k], des.scale[k])); v.weight.Add(readType(d, des.format[k], des.scale[k])); break; //default: // Console.WriteLine("WTF is this"); } } } d.align(32); } } for (int j = 0; j < mesh.Count; j++) { foreach (int l in prim[j]) { List <int> face = new List <int>(); mesh[j].faces.Add(face); for (int k = 0; k < l; k++) { face.Add(d.readUShort()); } d.align(32); } } } PreRender(); }
public void ReadNTWU(FileData d) { d.skip(0x02); int count = d.readUShort(); d.skip(0x10); int headerPtr = d.pos(); int dataPtr = 0; int gtxHeaderOffset = 0; for (int i = 0; i < count; i++) { NutTexture tex = new NutTexture(); tex.type = PixelInternalFormat.Rgba32ui; d.seek(headerPtr); int totalSize = d.readInt(); int headerSize = d.readUShort(); int numMips = d.readInt(); tex.setPixelFormatFromNutFormat(d.readUShort()); tex.Width = d.readUShort(); tex.Height = d.readUShort(); d.skip(8); // mipmaps and padding int dataOffset = d.readInt() + dataPtr + 0x10; headerPtr += headerSize; dataPtr += headerSize; d.skip(0x04); if (i == 0) { gtxHeaderOffset = d.readInt() + 0x10; } else { gtxHeaderOffset += 0x80; d.skip(0x04); } d.skip(0x04); // check for cubemap bool cmap = (d.readInt() == d.readInt()); d.seek(d.pos() - 8); if (cmap) { Console.WriteLine("cubemap detected"); } d.skip(headerSize - 0x50); d.skip(0x18); tex.HASHID = d.readInt(); Console.WriteLine(gtxHeaderOffset.ToString("x")); d.seek(gtxHeaderOffset); d.skip(0x04); // dim d.skip(0x04); // width d.skip(0x04); // height d.skip(0x04); // depth d.skip(0x04); // numMips int format = d.readInt(); d.skip(0x04); // aa d.skip(0x04); // use int imageSize = d.readInt(); d.skip(0x04); // imagePtr int maxSize = d.readInt(); // mipSize d.skip(0x04); // mipPtr int tileMode = d.readInt(); int swizzle = d.readInt(); d.skip(0x04); // alignment int pitch = d.readInt(); int ds = dataOffset; int s1 = 0; int size = 0; Console.WriteLine(totalSize.ToString("x")); for (int mipLevel = 0; mipLevel < numMips; mipLevel++) { // Maybe this is the problem? int mipSize = imageSize >> (mipLevel * 2); int p = pitch >> mipLevel; size = d.readInt(); //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + totalSize - dataOffset : size)); //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle); //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel)); //if (cmap) tex.height *= 2; int w = (tex.Width >> mipLevel); int h = (tex.Height >> mipLevel); { byte[] deswiz = GTX.swizzleBC( d.getSection(dataOffset, d.size() - dataOffset), w, h, format, tileMode, p, swizzle ); tex.mipmaps.Add(new FileData(deswiz).getSection(0, mipSize)); } if (mipLevel == 0) { s1 = size; dataOffset = ds + size; } else { dataOffset = ds + s1 + size; } //dataOffset += mipSize; /*if (cmap) * { * for(int k = 0; k < 5; k++) * { * p = pitch >> (mipLevel + k + 1); * tex.mipmaps.Add(GTX.swizzleBC( * d.getSection(dataOffset, mipSize), * w, * h, * format, * tileMode, * p, * swizzle * )); * * dataOffset += mipSize; * } * }*/ //while (dataOffset % 1024 != 0) dataOffset++; //if (mipSize == 0x4000) dataOffset += 0x400; } Nodes.Add(tex); } foreach (NutTexture tex in Nodes) { if (!draw.ContainsKey(tex.HASHID)) { draw.Add(tex.HASHID, loadImage(tex, false)); } // redo mipmaps /*GL.BindTexture(TextureTarget.Texture2D, draw[tex.id]); * for (int k = 1; k < tex.mipmaps.Count; k++) * { * tex.mipmaps[k] = new byte[tex.mipmaps[k].Length]; * GCHandle pinnedArray = GCHandle.Alloc(tex.mipmaps[k], GCHandleType.Pinned); * IntPtr pointer = pinnedArray.AddrOfPinnedObject(); * GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, pointer); * pinnedArray.Free(); * }*/ } //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray); //Console.WriteLine(GL.GetError()); /*int j = 0; * foreach(byte[] b in textures[0].mipmaps) * { * if (j == 3) * { * for(int w = 3; w < 8; w++) * { * for (int p = 3; p < 6; p++) * { * byte[] deswiz = GTX.swizzleBC( * b, * (int)Math.Pow(2, w), * 64, * 51, * 4, * (int)Math.Pow(2, p), * 197632 * ); * File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz); * } * } * * } * j++; * }*/ }