public void Read(FileData d) { destone.Clear(); d.skip(8);// magic and section size int count = d.readInt(); int start = d.pos(); for (int i = 0; i < count; i++) { int offset = d.readInt(); int size = d.readInt(); int temp = d.pos(); d.seek(start + offset); TONE_DES des = new TONE_DES(); des.Read(d); destone.Add(des); d.seek(temp); } }
public void Read(FileData d) { d.skip(8);// magic and section size int count = d.readInt(); int start = d.pos(); for (int i = 0; i < count; i++) { int offset = d.readInt(); int size = d.readInt(); int temp = d.pos(); d.seek(offset + start); TONE_META meta = new TONE_META(); meta.Read(d); tones.Add(meta); d.seek(temp); } }
public void Read(FileData f) { f.Endian = endianess; if (f.size() < 4) { return; } int entryCount = f.readInt(); int otherCount = f.readInt(); int startOffset = f.readInt(); int unk = f.readInt(); //0x20 - Entry size? int unk2 = f.readInt(); //0x8? - values per entry? int unk3 = f.readInt(); //0x30? - start offset again? int otherStartOffset = f.readInt(); if (unk != 0x20 || unk2 != 0x8 || unk3 != 0x30) { throw new Exception("Unexpected Unkowns Please Report to Jam"); } f.seek(startOffset); for (int i = 0; i < entryCount; i++) { Entry temp = new Entry(); temp.values = new int[8]; for (int j = 0; j < 8; j++) { temp.values[j] = f.readInt(); } int returnOffset = f.pos(); f.seek(temp.values[0]); temp.name = f.readString(); f.seek(returnOffset); entries.Add(temp); } f.seek(otherStartOffset); for (int i = 0; i < otherCount; i++) { Entry temp = new Entry(); temp.values = new int[2]; for (int j = 0; j < 2; j++) { temp.values[j] = f.readInt(); } int returnOffset = f.pos(); f.seek(temp.values[0]); temp.name = f.readString(); f.seek(returnOffset); otherEntries.Add(temp); } }
public void read(FileData f) { int nameOffset = f.readInt(); matHash = f.readInt(); int propertyCount = f.readInt(); int propertyPos = f.readInt(); hasPat = (0 != f.readByte()); f.skip(3); int patOffset = f.readInt(); int secondNameOff = f.readInt(); matHash2 = f.readInt(); f.seek(nameOffset); name = f.readString(); if (secondNameOff != 0) { f.seek(secondNameOff); name2 = f.readString(); } if (hasPat) { f.seek(patOffset); int patDataPos = f.readInt(); if (patDataPos != 0) { f.seek(patDataPos); pat0.read(f); } } f.seek(propertyPos); for (int i = 0; i < propertyCount; i++) { int propOffset = f.readInt(); int returnPos = f.pos(); f.seek(propOffset); MatData temp = new MatData(); temp.read(f); properties.Add(temp); f.seek(returnPos); } }
public DDS(FileData d) { d.Endian = System.IO.Endianness.Little; d.seek(0); header = new Header(); header.magic = new char[4]; header.magic [0] = (char)d.readByte(); header.magic [1] = (char)d.readByte(); header.magic [2] = (char)d.readByte(); header.magic [3] = (char)d.readByte(); header.size = d.readInt(); header.flags = d.readInt(); header.height = d.readInt(); header.width = d.readInt(); header.pitchOrLinear = d.readInt(); header.depth = d.readInt(); header.mipmapCount = d.readInt(); header.reserved = new int[11]; for (int i = 0; i < 11; i++) { header.reserved [i] = d.readInt(); } header.dwSize = d.readInt(); header.dwFlags = d.readInt(); header.dwFourCC = d.readInt(); header.dwBitmask = d.readInt(); header.dwCaps = (uint)d.readInt(); header.dwCaps2 = (uint)d.readInt(); header.dwCaps3 = (uint)d.readInt(); header.dwCaps4 = (uint)d.readInt(); header.reserve = d.readInt(); d.skip(16); // not needed another header data = new byte[d.size() - d.pos()]; for (int i = 0; i < data.Length; i++) { data [i] = (byte)d.readByte(); } }
public override void Read(string filename) { { { FileData d = new FileData(filename); var size1 = d.readShort(); if (size1 > 255) { d.seek(0); d.Endian = Endianness.Little; size1 = d.readShort(); } if (d.size() < 4) { return; } var size2 = d.readShort(); List <short> Table1 = new List <short>(); for (int i = 0; i < size1; i++) { if (d.pos() + 2 > d.size()) { break; } Table1.Add((short)d.readShort()); } List <short> Table2 = new List <short>(); for (int i = 0; i < size2; i++) { if (d.pos() + 2 > d.size()) { break; } Table2.Add((short)d.readShort()); } Tables = new List <List <short> >(); Tables.Add(Table1); Tables.Add(Table2); } } }
public void read(FileData f) { keyframe temp; defaultTexId = f.readInt(); int keyframeCount = f.readInt(); int keyframeOffset = f.readInt(); frameCount = f.readInt() + 1; unknown = f.readInt(); if (keyframeOffset != f.eof()) { f.seek(keyframeOffset); for (int i = 0; i < keyframeCount; i++) { temp.texId = f.readInt(); temp.frameNum = f.readInt(); keyframes.Add(temp); } } }
public void read(FileData f) { f.Endian = Endian; if (f.size() < 4) { return; } f.seek(4); unknown = f.readUInt(); frameCount = f.readUInt(); startFrame = f.readUInt(); endFrame = f.readUInt(); frameRate = f.readUInt(); int matCount = f.readInt(); int matOffset = f.readInt(); int visCount = f.readInt(); int visOffset = f.readInt(); int returnPos; f.seek(matOffset); for (int i = 0; i < matCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); MatEntry tempMatEntry = new MatEntry(); tempMatEntry.read(f); matEntries.Add(tempMatEntry); f.seek(returnPos); } f.seek(visOffset); for (int i = 0; i < visCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); VisEntry tempVisEntry = new VisEntry(); tempVisEntry.read(f); visEntries.Add(tempVisEntry); f.seek(returnPos); } }
public void read(FileData f) { f.Endian = Endian; if (f.size() < 4) { throw new EndOfStreamException("Blank/Broken MTA"); } f.seek(4); unknown = (uint)f.readInt(); numFrames = (uint)f.readInt(); f.skip(8); frameRate = (uint)f.readInt(); int matCount = f.readInt(); int matOffset = f.readInt(); int visCount = f.readInt(); int visOffset = f.readInt(); int returnPos; f.seek(matOffset); for (int i = 0; i < matCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); MatEntry tempMatEntry = new MatEntry(); tempMatEntry.read(f); matEntries.Add(tempMatEntry); f.seek(returnPos); } f.seek(visOffset); for (int i = 0; i < visCount; i++) { returnPos = f.pos() + 4; f.seek(f.readInt()); VisEntry tempVisEntry = new VisEntry(); tempVisEntry.read(f); visEntries.Add(tempVisEntry); f.seek(returnPos); } }
public override void Read(string filename) { var offsets = new List <int>(); var strings = new List <string>(); var sizes = new List <int>(); Files = new Dictionary <string, byte[]>(); FileData data = new FileData(filename); data.Endian = Endianness.Big; if (data != null) { var magic = data.readString(); if (magic == "PACK") { data.Endian = Endianness.Little; } data.seek(0x08); var count = data.readInt(); for (int i = 0; i < count; i++) { data.seek(0x10 + (i * 4)); var strOffset = data.readInt(); data.seek(strOffset); strings.Add(data.readString()); data.seek(0x10 + (count * 4) + (i * 4)); offsets.Add(data.readInt()); data.seek((count * 4) + (count * 4) + (i * 4) + 0x10); sizes.Add(data.readInt()); data.seek(offsets[i]); var b = data.read(sizes[i]); Files.Add(strings[i], b); } } }
public BRTI(FileData f) //Docs thanks to gdkchan!! { ImageKey = "texture"; SelectedImageKey = "texture"; f.skip(4); int BRTISize1 = f.readInt(); long BRTISize2 = (f.readInt() | f.readInt() << 32); surf = new Swizzle.Surface(); surf.tileMode = (sbyte)f.readByte(); surf.dim = (sbyte)f.readByte(); ushort Flags = (ushort)f.readShort(); surf.swizzle = (ushort)f.readShort(); surf.numMips = (ushort)f.readShort(); uint unk18 = (uint)f.readInt(); surf.format = (uint)f.readInt(); DataType = (byte)(surf.format & 0xFF); uint unk20 = (uint)f.readInt(); surf.width = f.readInt(); surf.height = f.readInt(); surf.depth = f.readInt(); int FaceCount = f.readInt(); surf.sizeRange = f.readInt(); uint unk38 = (uint)f.readInt(); uint unk3C = (uint)f.readInt(); uint unk40 = (uint)f.readInt(); uint unk44 = (uint)f.readInt(); uint unk48 = (uint)f.readInt(); uint unk4C = (uint)f.readInt(); surf.imageSize = f.readInt(); surf.alignment = f.readInt(); int ChannelType = f.readInt(); int TextureType = f.readInt(); Text = f.readString((f.readInt() | f.readInt() << 32) + BNTX.temp + 2, -1); long ParentOffset = f.readInt() | f.readInt() << 32; long PtrsOffset = f.readInt() | f.readInt() << 32; format = surf.format; f.seek((int)PtrsOffset + BNTX.temp); long dataOff = f.readInt() | f.readInt() << 32; surf.data = f.getSection((int)dataOff + BNTX.temp, surf.imageSize); //Console.WriteLine(surf.data.Length + " " + dataOff.ToString("x") + " " + surf.imageSize); uint blk_dim = Formats.blk_dims(surf.format >> 8); uint blkWidth = blk_dim >> 4; uint blkHeight = blk_dim & 0xF; uint bpp = Formats.bpps(surf.format >> 8); // Console.WriteLine($"{Name} Height {surf.height}wdith = {surf.width}allignment = {surf.alignment}blkwidth = {blkWidth}blkheight = {blkHeight}blkdims = {blk_dim} format = {surf.format} datatype = {DataType} dataoffset = {dataOff}"); // byte[] result = surf.data; byte[] result = Swizzle.deswizzle((uint)surf.width, (uint)surf.height, blkWidth, blkHeight, bpp, (uint)surf.tileMode, (uint)surf.alignment, surf.sizeRange, surf.data, 0); uint width = Swizzle.DIV_ROUND_UP((uint)surf.width, blkWidth); uint height = Swizzle.DIV_ROUND_UP((uint)surf.height, blkHeight); result_ = new byte[width * height * bpp]; Array.Copy(result, 0, result_, 0, width * height * bpp); texture.data = result_; texture.width = surf.width; texture.height = surf.height; Width = surf.width; Height = surf.height; texture.mipmaps.Add(result_); switch (surf.format >> 8) { case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC1): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext; } else if (DataType == (byte)Formats.BNTXImageTypes.SRGB) { texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt1Ext; } else { throw new Exception("Unsupported data type for BC1"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC2): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext; } else if (DataType == (byte)Formats.BNTXImageTypes.SRGB) { texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext; } else { throw new Exception("Unsupported data type for BC2"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC3): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext; } else if (DataType == (byte)Formats.BNTXImageTypes.SRGB) { texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext; } else { throw new Exception("Unsupported data type for BC3"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC4): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { texture.type = PixelInternalFormat.CompressedRedRgtc1; /* byte[] fixBC4 = DecompressBC4(texture.data, texture.width, texture.height, false); * texture.data = fixBC4; * texture.type = PixelInternalFormat.Rgba; * texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;*/ } else if (DataType == (byte)Formats.BNTXImageTypes.SNORM) { texture.type = PixelInternalFormat.CompressedSignedRedRgtc1; /* byte[] fixBC4 = DecompressBC4(texture.data, texture.width, texture.height, true); * texture.data = fixBC4; * texture.type = PixelInternalFormat.Rgba; * texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;*/ } else { throw new Exception("Unsupported data type for BC4"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC5): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { // byte[] fixBC5 = DecompressBC5(texture.data, texture.width, texture.height, false); // texture.data = fixBC5; texture.type = PixelInternalFormat.CompressedRgRgtc2; // texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba; } else if (DataType == (byte)Formats.BNTXImageTypes.SNORM) { byte[] fixBC5 = DecompressBC5(texture.data, texture.width, texture.height, true); texture.data = fixBC5; texture.type = PixelInternalFormat.Rgba; texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba; } else { Console.WriteLine("Unsupported data type for BC5"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC7): if (DataType == (byte)Formats.BNTXImageTypes.UNORM) { /* ProcessStartInfo startInfo = new ProcessStartInfo(); * startInfo.CreateNoWindow = false; * startInfo.UseShellExecute = false; * startInfo.FileName = "lib\texconv.exe"; * startInfo.WindowStyle = ProcessWindowStyle.Hidden; * startInfo.Arguments = "-ft png -f R10G10B10A2_UNORM -y";*/ } else if (DataType == (byte)Formats.BNTXImageTypes.SNORM) { } else { Console.WriteLine("Unsupported data type for BC7"); } break; case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_R8_G8_B8_A8): if (DataType == (byte)Formats.BNTXImageTypes.UNORM || DataType == (byte)Formats.BNTXImageTypes.SRGB) { texture.type = PixelInternalFormat.Rgba; texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba; } else { throw new Exception("Unsupported data type for R8_G8_B8_A8"); } break; } texture.display = loadImage(texture); display = texture.display; RenderableTex.Add(texture); }
public void Read(byte[] file) { FileData f = new FileData(file); f.Endian = Endianness.Big; f.seek(0); f.seek(4); // magic check SwitchCheck = f.readInt(); //Switch version only has padded magic verNumD = f.readByte(); verNumC = f.readByte(); verNumB = f.readByte(); verNumA = f.readByte(); if (SwitchCheck == 0x20202020) { //Console.WriteLine("Version = " + verNumA + "." + verNumB + "." + verNumC + "." + verNumD); if (f.readShort() == 0xFEFF) { f.Endian = Endianness.Big; } else { f.Endian = Endianness.Little; } f.skip(2); //Size Headeer f.skip(4); //File Name Direct int fileAlignment = f.readInt(); int RelocationTableOffset = f.readInt(); int BfresSize = f.readInt(); string name = f.readString(readOffset(f) + 2, -1); f.skip(4); // Padding long FMDLOffset = f.readInt64(); long FMDLDict = f.readInt64(); long FSKAOffset = f.readInt64(); long FSKADict = f.readInt64(); long FMAAOffset = f.readInt64(); long FMAADict = f.readInt64(); long FVISOffset = f.readInt64(); long FVISDict = f.readInt64(); long FSHUOffset = f.readInt64(); long FSHUDict = f.readInt64(); long FSCNOffset = f.readInt64(); long FSCNDict = f.readInt64(); long BuffMemPool = f.readInt64(); long BuffMemPoolInfo = f.readInt64(); long EMBOffset = f.readInt64(); long EMBDict = f.readInt64(); f.skip(8); // Padding long StringTableOffset = f.readInt64(); int unk11 = f.readInt(); int FMDLCount = f.readShort(); /*FSKACount =*/ f.readShort(); int FMAACount = f.readShort(); int FVISCount = f.readShort(); int FSHUCount = f.readShort(); int FSCNCount = f.readShort(); int EMBCount = f.readShort(); f.skip(12); // Padding // //Console.WriteLine($"FMDLOffset {FMDLOffset} FMDLCount {FMDLCount} FMDLDict {FMDLDict} FSKAOffset {FSKAOffset} FSKADict {FSKADict}"); // //Console.WriteLine($"FMAAOffset {FMAAOffset} FMAADict {FMAADict} FVISOffset {FVISOffset} FSHUOffset {FSKAOffset} FSKADict {FSHUDict}"); //FMDLs -Models- for (int i = 0; i < EMBCount; i++) { f.seek((int)EMBOffset + (i * 16)); int DataOffset = f.readInt(); f.seek(DataOffset); string EmMagic = f.readString(f.pos(), 4); if (EmMagic.Equals("BNTX")) //Textures { f.skip(24); int size = f.readInt(); f.seek(DataOffset); BinaryTexture t = new BinaryTexture(f.GetStream(size)); textures.Add(t.Name, t); } } f.seek((int)FMDLOffset); for (int i = 0; i < FMDLCount; i++) { // //Console.WriteLine("Reading FMDL...."); FMDL_Model model = new FMDL_Model(); //FMDL modelTest = new FMDL(); //modelTest.Read(f); f.skip(16); FMDLheader fmdl_info = new FMDLheader { name = f.readString(f.readInt() + 2, -1), padding = f.readInt(), eofString = f.readInt64(), fsklOff = f.readInt64(), fvtxArrOff = f.readInt64(), fshpOffset = f.readInt64(), fshpIndx = f.readInt64(), fmatOffset = f.readInt64(), fmatIndx = f.readInt64(), UserDataOffset = f.readInt64(), padding1 = f.readInt64(), padding2 = f.readInt64(), fvtxCount = f.readShort(), fshpCount = f.readShort(), fmatCount = f.readShort(), paramCount = f.readShort(), VertCount = f.readInt(), unk2 = f.readInt(), }; int NextFMDL = f.pos(); model.name = fmdl_info.name; //Models.Nodes.Add(fmdl_info.name); // //Console.WriteLine($" Name {fmdl_info.name} eofString {fmdl_info.eofString} fsklOff {fmdl_info.fsklOff}"); // //Console.WriteLine(fmdl_info.fvtxCount); List <FVTXH> FVTXArr = new List <FVTXH>(); f.seek((int)fmdl_info.fvtxArrOff); for (int vtx = 0; vtx < fmdl_info.fvtxCount; vtx++) { // //Console.WriteLine("Reading FVTX...."); f.skip(16); FVTXArr.Add(new FVTXH { attArrOff = f.readInt64(), attIndxOff = f.readInt64(), unk1 = f.readInt64(), unk2 = f.readInt64(), unk3 = f.readInt64(), buffSizeOff = f.readInt64(), buffStrideSizeOff = f.readInt64(), buffArrOff = f.readInt64(), buffOff = f.readInt(), attCount = f.readByte(), buffCount = f.readByte(), sectIndx = f.readShort(), vertCount = f.readInt(), SkinWeightInfluence = f.readInt() }); // //Console.WriteLine($"attCount {FVTXArr[vtx].attCount}"); } f.seek((int)fmdl_info.fmatOffset); List <FMATH> FMATheaders = new List <FMATH>(); for (int mat = 0; mat < fmdl_info.fmatCount; mat++) { // //Console.WriteLine("Reading FMAT...."); f.skip(16); FMATH fmat_info = new FMATH { name = f.readString((int)f.readInt64() + 2, -1), renderInfoOff = f.readInt64(), renderInfoIndx = f.readInt64(), shaderAssignOff = f.readInt64(), u1 = f.readInt64(), texSelOff = f.readInt64(), u2 = f.readInt64(), texAttSelOff = f.readInt64(), texAttIndxOff = f.readInt64(), matParamArrOff = f.readInt64(), matParamIndxOff = f.readInt64(), matParamOff = f.readInt64(), userDataOff = f.readInt64(), userDataIndxOff = f.readInt64(), volatileFlagOffset = f.readInt64(), u3 = f.readInt64(), samplerSlotOff = f.readInt64(), textureSlotOff = f.readInt64(), flags = f.readInt(), //This toggles material visabilty sectIndx = f.readShort(), rendParamCount = f.readShort(), texSelCount = f.readByte(), texAttSelCount = f.readByte(), matParamCount = f.readShort(), u4 = f.readShort(), matParamSize = f.readShort(), rawParamDataSize = f.readShort(), userDataCount = f.readShort(), padding = f.readInt(), }; string FMATNameOffset = fmat_info.name; // //Console.WriteLine($"{FMATNameOffset} {fmat_info.texSelCount} "); FMATheaders.Add(fmat_info); } f.seek((int)fmdl_info.fsklOff + 16); // //Console.WriteLine("Reading FSKL...."); FSKLH fskl_info = new FSKLH { boneIndxOff = f.readInt64(), boneArrOff = f.readInt64(), invIndxArrOff = f.readInt64(), invMatrArrOff = f.readInt64(), padding1 = f.readInt64(), fsklType = f.readInt(), //flags boneArrCount = f.readShort(), invIndxArrCount = f.readShort(), exIndxCount = f.readShort(), u1 = f.readInt(), }; f.seek((int)fmdl_info.fsklOff + 16); FSKLH fskl_infov8 = new FSKLH { boneIndxOff = f.readInt64(), boneArrOff = f.readInt64(), invIndxArrOff = f.readInt64(), invMatrArrOff = f.readInt64(), padding1 = f.readInt64(), padding2 = f.readInt64(), padding3 = f.readInt64(), fsklType = f.readInt(), //flags boneArrCount = f.readShort(), invIndxArrCount = f.readShort(), exIndxCount = f.readShort(), u1 = f.readInt(), }; // //Console.WriteLine($"Bone Count {fskl_info.boneArrCount}"); //FSKL and many other sections will be revised and cleaner later if (verNumB == 8) { model.Node_Array = new int[fskl_infov8.invIndxArrCount + fskl_infov8.exIndxCount]; f.seek((int)fskl_infov8.invIndxArrOff); for (int nodes = 0; nodes < fskl_infov8.invIndxArrCount + fskl_infov8.exIndxCount; nodes++) { model.Node_Array[nodes] = (f.readShort()); } } else { model.Node_Array = new int[fskl_info.invIndxArrCount + fskl_info.exIndxCount]; f.seek((int)fskl_info.invIndxArrOff); for (int nodes = 0; nodes < fskl_info.invIndxArrCount + fskl_info.exIndxCount; nodes++) { model.Node_Array[nodes] = (f.readShort()); } } List <FSHPH> FSHPArr = new List <FSHPH>(); // //Console.WriteLine("Reading FSHP...."); f.seek((int)fmdl_info.fshpOffset); for (int shp = 0; shp < fmdl_info.fshpCount; shp++) { f.skip(16); FSHPArr.Add(new FSHPH { polyNameOff = f.readInt(), u1 = f.readInt(), fvtxOff = f.readInt64(), lodMdlOff = f.readInt64(), fsklIndxArrOff = f.readInt64(), u3 = f.readInt64(), u4 = f.readInt64(), boundingBoxOff = f.readInt64(), radiusOff = f.readInt64(), padding = f.readInt64(), flags = f.readInt(), sectIndx = f.readShort(), fmatIndx = f.readShort(), fsklIndx = f.readShort(), fvtxIndx = f.readShort(), fsklIndxArrCount = f.readShort(), matrFlag = f.readByte(), lodMdlCount = f.readByte(), visGrpCount = f.readInt(), visGrpIndxOff = f.readShort(), visGrpNodeOff = f.readShort(), }); } // //Console.WriteLine("Reading Bones...."); // //Console.WriteLine("Reading FSHP Array...."); //MeshTime!! for (int m = 0; m < FSHPArr.Count; m++) { Mesh poly = new Mesh(); poly.name = f.readString(FSHPArr[m].polyNameOff + 2, -1); // //Console.WriteLine("Polygon = " + poly.name); List <attdata> AttrArr = new List <attdata>(); f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].attArrOff); for (int att = 0; att < FVTXArr[FSHPArr[m].fvtxIndx].attCount; att++) { string AttType = f.readString(f.readInt() + 2, -1); f.skip(4); //padding f.Endian = Endianness.Big; int vertType = f.readShort(); f.skip(2); f.Endian = Endianness.Little; int buffOff = f.readShort(); int buffIndx = f.readShort(); // //Console.WriteLine($"{AttType} Type = {vertType} Offset = {buffOff} Index = {buffIndx} "); AttrArr.Add(new attdata { attName = AttType, buffIndx = buffIndx, buffOff = buffOff, vertType = vertType }); } //Get RLT real quick for buffer offset f.seek(0x18); int RTLOffset = f.readInt(); f.seek(RTLOffset); f.skip(0x030); int DataStart = f.readInt(); // //Console.WriteLine($"RLT {DataStart}"); List <buffData> BuffArr = new List <buffData>(); f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffArrOff); for (int buff = 0; buff < FVTXArr[FSHPArr[m].fvtxIndx].buffCount; buff++) { buffData data = new buffData(); f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffSizeOff + ((buff) * 0x10)); data.buffSize = f.readInt(); f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffStrideSizeOff + ((buff) * 0x10)); data.strideSize = f.readInt(); //So these work by grabbing the RLT offset first and then adding the buffer offset. Then they keep adding each other by their buffer sizes if (buff == 0) { data.DataOffset = (DataStart + FVTXArr[FSHPArr[m].fvtxIndx].buffOff); } if (buff > 0) { data.DataOffset = BuffArr[buff - 1].DataOffset + BuffArr[buff - 1].buffSize; } if (data.DataOffset % 8 != 0) { data.DataOffset = data.DataOffset + (8 - (data.DataOffset % 8)); } BuffArr.Add(data); // //Console.WriteLine("Data Offset = " + data.DataOffset + " Vertex Buffer Size =" + data.buffSize + " Index = " + buff + " vertexStrideSize size =" + data.strideSize); } for (int v = 0; v < FVTXArr[FSHPArr[m].fvtxIndx].vertCount; v++) { Vertex vert = new Vertex(); for (int attr = 0; attr < AttrArr.Count; attr++) { f.seek(((BuffArr[AttrArr[attr].buffIndx].DataOffset) + (AttrArr[attr].buffOff) + (BuffArr[AttrArr[attr].buffIndx].strideSize * v))); switch (AttrArr[attr].attName) { case "_p0": if (AttrArr[attr].vertType == 1301) { vert.pos = new Vector3 { X = f.readHalfFloat(), Y = f.readHalfFloat(), Z = f.readHalfFloat() } } ; if (AttrArr[attr].vertType == 1304) { vert.pos = new Vector3 { X = f.readFloat(), Y = f.readFloat(), Z = f.readFloat() } } ; break; case "_c0": if (AttrArr[attr].vertType == 1301) { vert.col = new Vector4(f.readHalfFloat(), f.readHalfFloat(), f.readHalfFloat(), f.readHalfFloat()); } if (AttrArr[attr].vertType == 2067) { vert.col = new Vector4 { X = f.readFloat(), Y = f.readFloat(), Z = f.readFloat(), W = f.readFloat() } } ; if (AttrArr[attr].vertType == 267) { vert.col = new Vector4(f.readByte() / 255f, f.readByte() / 255f, f.readByte() / 255f, f.readByte() / 255f); } break; case "_n0": if (AttrArr[attr].vertType == 526) { int normVal = (int)f.readInt(); //Thanks RayKoopa! vert.nrm = new Vector3 { X = sign10Bit((normVal) & 0x3FF) / (float)511, Y = sign10Bit((normVal >> 10) & 0x3FF) / (float)511, Z = sign10Bit((normVal >> 20) & 0x3FF) / (float)511 }; } break; case "_u0": case "color": case "_t0": case "_b0": case "_u1": case "_u2": case "_u3": if (AttrArr[attr].vertType == 265 || AttrArr[attr].vertType == 521) { vert.tx.Add(new Vector2 { X = ((float)f.readByte()) / 255, Y = ((float)f.readByte()) / 255 }); } if (AttrArr[attr].vertType == 274) { vert.tx.Add(new Vector2 { X = ((float)f.readShort()) / 65535, Y = ((float)f.readShort()) / 65535 }); } if (AttrArr[attr].vertType == 530) { vert.tx.Add(new Vector2 { X = ((float)f.readShort()) / 32767, Y = ((float)f.readShort()) / 32767 }); } if (AttrArr[attr].vertType == 1298) { vert.tx.Add(new Vector2 { X = f.readHalfFloat(), Y = f.readHalfFloat() }); } if (AttrArr[attr].vertType == 1303) { vert.tx.Add(new Vector2 { X = f.readFloat(), Y = f.readFloat() }); } break; case "_i0": if (AttrArr[attr].vertType == 770) { vert.node.Add(f.readByte()); vert.weight.Add((float)1.0); } if (AttrArr[attr].vertType == 777) { vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); } if (AttrArr[attr].vertType == 779) { vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); } if (AttrArr[attr].vertType == 523) { vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); vert.node.Add(f.readByte()); } break; case "_w0": if (AttrArr[attr].vertType == 258) { vert.weight.Add((f.readByte()) / (float)255); } if (AttrArr[attr].vertType == 265) { vert.weight.Add((f.readByte()) / (float)255); vert.weight.Add((f.readByte()) / (float)255); } if (AttrArr[attr].vertType == 267) { vert.weight.Add((f.readByte()) / (float)255); vert.weight.Add((f.readByte()) / (float)255); vert.weight.Add((f.readByte()) / (float)255); vert.weight.Add((f.readByte()) / (float)255); } if (AttrArr[attr].vertType == 274) { vert.weight.Add((f.readShort()) / (float)255); vert.weight.Add((f.readShort()) / (float)255); } break; default: // //Console.WriteLine(AttrArr[attr].attName + " Unknown type " + AttrArr[attr].vertType.ToString("x") + " 0x"); break; } } poly.vertices.Add(vert); } int LoadLOD = FSHPArr[m].lodMdlCount - 1; f.seek((int)FSHPArr[m].lodMdlOff); for (int lod = 0; lod < FSHPArr[m].lodMdlCount; lod++) { long SubMeshOff = f.readInt64(); long unk1 = f.readInt64(); long unk2 = f.readInt64(); long indxBuffOff = f.readInt64(); int FaceBuffer = f.readInt(); int PrimativefaceType = f.readInt(); int faceType = f.readInt(); int FaceCount = f.readInt(); int elmSkip = f.readInt(); int subMeshCount = f.readInt(); int temp = f.pos(); f.seek(FaceBuffer + DataStart); if (faceType == 1) { FaceCount = FaceCount / 3; } if (faceType == 2) { FaceCount = FaceCount / 6; } if (lod == LoadLOD) { for (int face = 0; face < FaceCount; face++) { if (faceType == 1) { poly.faces.Add(new List <int> { elmSkip + f.readShort(), elmSkip + f.readShort(), elmSkip + f.readShort() }); } else if (faceType == 2) { poly.faces.Add(new List <int> { elmSkip + f.readInt(), elmSkip + f.readInt(), elmSkip + f.readInt() }); } else { Console.Write("UnkFaceFormat"); } } } f.seek(temp); } f.seek((int)FMATheaders[FSHPArr[m].fmatIndx].texSelOff); List <string> MatTexList = new List <string>(); for (int tex = 0; FMATheaders[FSHPArr[m].fmatIndx].texAttSelCount > tex; tex++) { string TextureName = f.readString((int)f.readInt64() + 2, -1).ToLower(); MatTexList.Add(TextureName); } if (MatTexList.Count > 0) { poly.texNames.Add(MatTexList[0]); } //Console.WriteLine(String.Join(",",MatTexList)); model.poly.Add(poly); } models.Add(model); f.seek(NextFMDL); } } }
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); 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? int size1 = f.readInt(); Console.Write(size1 + "\t"); for (int j = 0; j < (size1 / 4) - 1; j++) { Console.Write(f.readShort() + " " + f.readShort() + "\t"); } Console.WriteLine(); int size2 = f.readInt(); Console.Write(size2 + "\t"); for (int j = 0; j < (size2 / 4) - 1; j++) { Console.Write(f.readShort() + " " + f.readShort() + "\t"); } Console.WriteLine(); int size3 = f.readInt(); Console.Write(size3 + "\t"); for (int j = 0; j < (size3 / 4) - 1; j++) { Console.Write(f.readShort() + " " + f.readShort() + "\t"); } Console.WriteLine(); int size4 = f.readInt(); Console.Write(size4 + "\t"); for (int j = 0; j < (size4 / 4) - 1; j++) { Console.Write(f.readShort() + " " + f.readShort() + "\t"); } Console.WriteLine(); int size5 = f.readInt(); Console.Write(size5 + "\t"); for (int j = 0; j < (size5 / 4) - 1; j++) { Console.Write(f.readShort() + " " + f.readShort() + "\t"); } Console.WriteLine(); f.skip(8); } Console.WriteLine("0x" + f.pos().ToString("X")); f.skip(8); int hashSize = f.readInt(); int unk = f.readInt(); for (int i = 0; i < hashCount; i++) { Console.WriteLine(f.readInt().ToString("X")); } }
public void OpenMBN(FileData f) { f.Endian = Endianness.Little; f.seek(0); int format = f.readShort(); 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.readShort(); } f.align(32); } } }
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.readShort(); 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.readShort(); int addressCount = f.readShort(); } // 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.readShort(); 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.readShort(); int rootRightNode = f.readShort(); 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 = (short)f.readShort(); short rightNode = (short)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.readShort(); int mflags = f.readShort(); int meshId = f.readShort(); 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.readShort(); 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 = (short)f.readShort(); short boneSpace = (short)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 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.readShort(); 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.readShort(); header.addressCount = f.readShort(); } // 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(); } //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); //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X")); f.seek(textureCommandsOffset); //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X")); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt(); //Debug.WriteLine("doffset: " + doffset.ToString("X")); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // 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.readShort(); 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); model.materialsTableOffset = f.readInt(); model.materialsTableEntries = f.readInt(); model.materialsNameOffset = f.readInt(); model.verticesTableOffset = f.readInt(); //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); model.verticesTableEntries = f.readInt(); f.skip(0x28); model.skeletonOffset = f.readInt(); model.skeletonEntries = f.readInt(); model.skeletonNameOffset = f.readInt(); model.objectsNodeVisibilityOffset = f.readInt(); model.objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt(), -1); model.objectsNodeNameEntries = f.readInt(); model.objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 model.metaDataPointerOffset = f.readInt(); f.seek(model.objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[model.objectsNodeNameEntries]; f.seek(model.objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + header.mainHeaderOffset; for (int i = 0; i < model.objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[model.materialsTableEntries]; for (int index = 0; index < model.materialsTableEntries; index++) { f.seek(model.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(model.verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < model.verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); 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.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); 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] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(model.skeletonOffset); for (int index = 0; index < model.skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)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 model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
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(); for (int j = 0; j < csv.ids.Count; j++) { if (csv.ids[j] == hash) { Console.WriteLine(csv.names[j]); bonename.Add(csv.names[j]); break; } } } 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++) { Console.Write("\t" + f.readShort() + " " + f.readShort() + "\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 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 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 override void Read(string filename) { FileData f = new FileData(filename); //Header f.skip(0x4); version = f.readInt(); frameCount = f.readInt(); if (version == 4) { frameDuration = 1; } else if (version == 5) { frameDuration = f.readInt(); } else { throw new NotImplementedException($"Unknown light.bin version {version}"); } int[] offsets = new int[6]; for (int i = 0; i < 6; i++) { offsets[i] = f.readInt(); } //RGB properties for (int i = 0; i < 5; i++) { RgbProperty temp = new RgbProperty(); temp.enabled = (offsets[i + 1] != 0); if (temp.enabled) { f.seek(offsets[i + 1]); for (int j = 0; j < frameCount; j++) { byte[] frame = new byte[3]; for (int k = 0; k < 3; k++) { frame[k] = (byte)f.readByte(); } temp.frames.Add(frame); } } rgbProperties.Add(temp); } //Light data f.seek(offsets[0]); for (int i = 0; i < frameCount; i++) { LightFrame temp = new LightFrame(); for (int j = 0; j < 17; j++) { for (int k = 0; k < 4; k++) { temp.lightSets[j].lights[k].enabled = f.readInt(); for (int l = 0; l < 3; l++) { temp.lightSets[j].lights[k].angle[l] = f.readFloat(); } temp.lightSets[j].lights[k].colorHue = f.readFloat(); temp.lightSets[j].lights[k].colorSat = f.readFloat(); temp.lightSets[j].lights[k].colorVal = f.readFloat(); } temp.lightSets[j].fog.unknown = (byte)f.readByte(); for (int k = 0; k < 3; k++) { temp.lightSets[j].fog.color[k] = (byte)f.readByte(); } } temp.effect.unknown = (byte)f.readByte(); for (int j = 0; j < 3; j++) { temp.effect.color[j] = (byte)f.readByte(); } for (int j = 0; j < 3; j++) { temp.effect.position[j] = f.readFloat(); } lightFrames.Add(temp); } }
public static AnimationGroupNode Read(string filename, ResFile TargetWiiUBFRES) { FileData f = new FileData(filename); f.seek(0); f.Endian = Endianness.Little; Console.WriteLine("Reading Animations ..."); f.seek(4); // magic check int SwitchCheck = f.readInt(); //Switch version only has padded magic f.skip(4); if (SwitchCheck == 0x20202020) { // SwitchAnim2WiiU(path); //Hacky auto convert switch anims to wii u ResNSW.ResFile b = new ResNSW.ResFile(filename); AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = "Skeleton Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (ResNSW.SkeletalAnim ska in b.SkeletalAnims) { Animation a = new Animation(ska.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = ska.FrameCount; i++; try { foreach (Syroot.NintenTools.NSW.Bfres.BoneAnim bn in ska.BoneAnims) { FSKANode bonean = new FSKANode(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == ResNSW.SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0 && Runtime.HasNoAnimationBaseValues == false) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } return(ThisAnimation); } else { f.eof(); TargetWiiUBFRES = new ResFile(filename); ThisAnimation = new AnimationGroupNode() { Text = "Skeleton Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (SkeletalAnim ska in TargetWiiUBFRES.SkeletalAnims.Values) { Animation a = new Animation(ska.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = ska.FrameCount; i++; try { foreach (BoneAnim bn in ska.BoneAnims) { FSKANodeWiiU bonean = new FSKANodeWiiU(bn); Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); if (ska.FlagsRotate == SkeletalAnimFlagsRotate.EulerXYZ) { bone.RotType = Animation.RotationType.EULER; } else { bone.RotType = Animation.RotationType.QUATERNION; } bone.Text = bonean.Text; for (int Frame = 0; Frame < ska.FrameCount; Frame++) { //Set base/start values for bones. //Note. BOTW doesn't use base values as it uses havok engine. Need to add option to disable these if (Frame == 0 && Runtime.HasNoAnimationBaseValues == false) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.X }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Y }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.sca.Z }); bone.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.X }); bone.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Y }); bone.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.rot.Z }); bone.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.X }); bone.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Y }); bone.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = bonean.pos.Z }); } foreach (FSKATrack track in bonean.tracks) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.HERMITE; frame.Frame = Frame; FSKAKey left = track.GetLeft(Frame); FSKAKey right = track.GetRight(Frame); float value; value = Animation.Hermite(Frame, left.frame, right.frame, 0, 0, left.unk1, right.unk1); // interpolate the value and apply switch (track.flag) { case (int)TrackType.XPOS: frame.Value = value; bone.XPOS.Keys.Add(frame); break; case (int)TrackType.YPOS: frame.Value = value; bone.YPOS.Keys.Add(frame); break; case (int)TrackType.ZPOS: frame.Value = value; bone.ZPOS.Keys.Add(frame); break; case (int)TrackType.XROT: frame.Value = value; bone.XROT.Keys.Add(frame); break; case (int)TrackType.YROT: frame.Value = value; bone.YROT.Keys.Add(frame); break; case (int)TrackType.ZROT: frame.Value = value; bone.ZROT.Keys.Add(frame); break; case (int)TrackType.XSCA: frame.Value = value; bone.XSCA.Keys.Add(frame); break; case (int)TrackType.YSCA: frame.Value = value; bone.YSCA.Keys.Add(frame); break; case (int)TrackType.ZSCA: frame.Value = value; bone.ZSCA.Keys.Add(frame); break; } } } } } catch { } } return(ThisAnimation); } }
public static AnimationGroupNode Read(string filename, ResFile TargetWiiUBFRES, BFRES bfres) { string path = filename; FileData f = new FileData(filename); int Magic = f.readInt(); if (Magic == 0x59617A30) //YAZO compressed { using (FileStream input = new FileStream(path, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read)) { Yaz0Compression.Decompress(path, TEMP_FILE); path = TEMP_FILE; } } f = new FileData(path); f.seek(0); f.Endian = Endianness.Little; Console.WriteLine("Reading Animations ..."); f.seek(4); // magic check int SwitchCheck = f.readInt(); //Switch version only has padded magic f.skip(4); // SwitchAnim2WiiU(path); //Hacky auto convert switch anims to wii u Syroot.NintenTools.NSW.Bfres.ResFile b = new Syroot.NintenTools.NSW.Bfres.ResFile(path); AnimationGroupNode ThisAnimation = new AnimationGroupNode() { Text = "Bone Visual Animations" }; TreeNode dummy = new TreeNode() { Text = "Animation Set" }; int i = 0; foreach (Syroot.NintenTools.NSW.Bfres.VisibilityAnim vis in b.BoneVisibilityAnims) { Animation a = new Animation(vis.Name); ThisAnimation.Nodes.Add(a); a.FrameCount = vis.FrameCount; i++; int boneindx = 0; if (vis.Names != null) { foreach (string nm in vis.Names) //Loop through every bone. Not all have base and curve data { Animation.KeyNode bone = new Animation.KeyNode(""); a.Bones.Add(bone); bone.Text = vis.Names[boneindx]; if (boneindx < vis.BaseDataList.Length) { bool bas = vis.BaseDataList[boneindx]; if (bas == true) { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 1 }); } else { bone.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); bone.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); bone.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = 0 }); } } if (vis.Curves.Count != 0) { if (boneindx < vis.Curves.Count) { Syroot.NintenTools.NSW.Bfres.AnimCurve cr = vis.Curves[boneindx]; Console.WriteLine($"{vis.Name} {vis.Names[boneindx]}"); int frm = 0; foreach (bool bn in cr.KeyStepBoolData) { Animation.KeyFrame frame = new Animation.KeyFrame(); frame.InterType = Animation.InterpolationType.STEP; frame.Frame = cr.Frames[frm]; Console.WriteLine(vis.Name + " " + vis.Names[boneindx] + " " + bn); switch (bn) { case true: frame.Value = 1; bone.XSCA.Keys.Add(frame); frame.Value = 1; bone.YSCA.Keys.Add(frame); frame.Value = 1; bone.ZSCA.Keys.Add(frame); break; case false: frame.Value = 0; bone.XSCA.Keys.Add(frame); frame.Value = 0; bone.YSCA.Keys.Add(frame); frame.Value = 0; bone.ZSCA.Keys.Add(frame); break; } frm++; } } } boneindx++; } } } return(ThisAnimation); }
public void Read(FileData f, BNTX bntx) //Docs thanks to AboodXD!! { ImageKey = "texture"; SelectedImageKey = "texture"; f.skip(4); int BRTISize1 = f.readInt(); long BRTISize2 = f.readInt64(); surf = new TegraX1Swizzle.Surface(); ushort Flags = (ushort)f.readShort(); surf.dim = (sbyte)f.readByte(); surf.tileMode = (sbyte)f.readByte(); surf.swizzle = (ushort)f.readShort(); surf.numMips = (ushort)f.readShort(); uint numSamples = (uint)f.readInt(); surf.format = (uint)f.readInt(); DataType = (byte)(surf.format & 0xFF); uint accessFlags = (uint)f.readInt(); surf.width = f.readInt(); surf.height = f.readInt(); surf.depth = f.readInt(); int FaceCount = f.readInt(); surf.sizeRange = f.readInt(); uint unk38 = (uint)f.readInt(); uint unk3C = (uint)f.readInt(); uint unk40 = (uint)f.readInt(); uint unk44 = (uint)f.readInt(); uint unk48 = (uint)f.readInt(); uint unk4C = (uint)f.readInt(); surf.imageSize = f.readInt(); surf.alignment = f.readInt(); int ChannelType = f.readInt(); int TextureType = f.readInt(); Text = f.readString((int)f.readInt64() + BNTX.temp + 2, -1); long ParentOffset = f.readInt64(); long PtrsOffset = f.readInt64(); format = surf.format; surf.data = new List <byte[]>(); uint blk_dim = Formats.blk_dims(surf.format >> 8); blkWidth = blk_dim >> 4; blkHeight = blk_dim & 0xF; f.seek((int)PtrsOffset + BNTX.temp); long firstMipOffset = f.readInt64(); surf.data.Add(f.getSection((int)firstMipOffset + BNTX.temp, surf.imageSize)); for (int mipLevel = 1; mipLevel < surf.numMips; mipLevel++) { long dataOff = f.readInt64(); surf.data.Add(f.getSection((int)dataOff + BNTX.temp, (int)firstMipOffset + surf.imageSize - (int)dataOff)); // Debug.WriteLine($"{Name} Height {surf.height}wdith = {surf.width}allignment = {surf.alignment}blkwidth = {blkWidth}blkheight = {blkHeight}blkdims = {blk_dim} format = {surf.format} datatype = {DataType} dataoffset = {dataOff}"); } bpp = Formats.bpps(surf.format >> 8); int target = 0; if (bntx.target == "NX ") { target = 1; } int blockHeightLog2 = surf.sizeRange & 7; int linesPerBlockHeight = (1 << blockHeightLog2) * 8; int blockHeightShift = 0; for (int mipLevel = 0; mipLevel < surf.numMips; mipLevel++) { uint width = (uint)Math.Max(1, surf.width >> mipLevel); uint height = (uint)Math.Max(1, surf.height >> mipLevel); uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp; if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight) { blockHeightShift += 1; } byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, target, bpp, (uint)surf.tileMode, (uint)surf.alignment, Math.Max(0, blockHeightLog2 - blockHeightShift), surf.data[mipLevel], 0); //Create a copy and use that to remove uneeded data result_ = new byte[size]; Array.Copy(result, 0, result_, 0, size); texture.mipmaps.Add(result_); } LoadFormats(texture, surf.format, 0, surf.width, surf.height); texture.width = surf.width; texture.height = surf.height; Width = surf.width; Height = surf.height; }
private static byte[] YAZ0(byte[] data) { FileData f = new FileData(data); f.Endian = Endianness.Big; f.seek(4); int uncompressedSize = f.readInt(); f.seek(0x10); byte[] src = f.read(data.Length - 0x10); byte[] dst = new byte[uncompressedSize]; int srcPlace = 0, dstPlace = 0; //current read/write positions uint validBitCount = 0; //number of valid bits left in "code" byte byte currCodeByte = 0; while (dstPlace < uncompressedSize) { //read new "code" byte if the current one is used up if (validBitCount == 0) { currCodeByte = src[srcPlace]; ++srcPlace; validBitCount = 8; } if ((currCodeByte & 0x80) != 0) { //straight copy dst[dstPlace] = src[srcPlace]; dstPlace++; srcPlace++; } else { //RLE part byte byte1 = src[srcPlace]; byte byte2 = src[srcPlace + 1]; srcPlace += 2; uint dist = (uint)(((byte1 & 0xF) << 8) | byte2); uint copySource = (uint)(dstPlace - (dist + 1)); uint numBytes = (uint)(byte1 >> 4); if (numBytes == 0) { numBytes = (uint)(src[srcPlace] + 0x12); srcPlace++; } else { numBytes += 2; } //copy run for (int i = 0; i < numBytes; ++i) { dst[dstPlace] = dst[copySource]; copySource++; dstPlace++; } } //use next bit from "code" byte currCodeByte <<= 1; validBitCount -= 1; } return(dst); }
public override void Read(string filename) { FileData d = new FileData(filename); FilePath = filename; d.Endian = Endianness.Little; // characters are little d.seek(8); // skip magic and version? int count = d.readInt(); // entry count for (int i = 0; i < count; i++) { SBEntry sb = new SBEntry() { hash = (uint)d.readInt(), param1_1 = d.readFloat(), param1_2 = d.readInt(), param1_3 = d.readInt(), param2_1 = d.readFloat(), param2_2 = d.readFloat(), param2_3 = d.readInt(), rx1 = d.readFloat(), rx2 = d.readFloat(), ry1 = d.readFloat(), ry2 = d.readFloat(), rz1 = d.readFloat(), rz2 = d.readFloat() }; for (int j = 0; j < 8; j++) { sb.boneHashes[j] = (uint)d.readInt(); } for (int j = 0; j < 4; j++) { sb.unks1[j] = d.readFloat(); } for (int j = 0; j < 6; j++) { sb.unks2[j] = d.readFloat(); } sb.factor = d.readFloat(); for (int j = 0; j < 3; j++) { sb.ints[j] = d.readInt(); } bones.Add(sb); /*Console.WriteLine(sb.hash.ToString("x")); * Console.WriteLine(d.readFloat() + " " + d.readInt() + " " + d.readInt()); * Console.WriteLine(d.readFloat() + " " + d.readInt() + " " + d.readInt()); * * //28 floats? * Console.WriteLine(d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readFloat() + " " + d.readFloat() + " " + d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readFloat() + " " + d.readFloat() + " " + d.readFloat() + " " + d.readFloat()); * * Console.WriteLine(d.readFloat() + " " + d.readFloat() + " " + d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readFloat() + " " + d.readFloat() + " " + d.readFloat() + " " + d.readFloat()); * * Console.WriteLine(d.readFloat() + " " + d.readFloat()); * Console.WriteLine(d.readInt() + " " + d.readInt()); * Console.WriteLine(d.readInt() + " " + d.readInt()); * Console.WriteLine();*/ } }
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 override void Read(string filename) { FileData file = new FileData(filename); if (file != null) { file.Endian = Endianness.Little; Endian = Endianness.Little; string magic = file.readString(0, 4); if (magic == "VBN ") { file.Endian = Endianness.Big; Endian = Endianness.Big; } file.seek(4); unk_1 = file.readShort(); unk_2 = file.readShort(); totalBoneCount = (UInt32)file.readInt(); boneCountPerType[0] = (UInt32)file.readInt(); boneCountPerType[1] = (UInt32)file.readInt(); boneCountPerType[2] = (UInt32)file.readInt(); boneCountPerType[3] = (UInt32)file.readInt(); int[] pi = new int[totalBoneCount]; for (int i = 0; i < totalBoneCount; i++) { Bone temp = new Bone(this); temp.Text = file.readString(file.pos(), -1); file.skip(64); temp.boneType = (UInt32)file.readInt(); pi[i] = file.readInt(); temp.boneId = (UInt32)file.readInt(); temp.position = new float[3]; temp.rotation = new float[3]; temp.scale = new float[3]; //temp.isSwingBone = temp.Text.Contains("__swing"); bones.Add(temp); } for (int i = 0; i < bones.Count; i++) { bones[i].position[0] = file.readFloat(); bones[i].position[1] = file.readFloat(); bones[i].position[2] = file.readFloat(); bones[i].rotation[0] = file.readFloat(); bones[i].rotation[1] = file.readFloat(); bones[i].rotation[2] = file.readFloat(); bones[i].scale[0] = file.readFloat(); bones[i].scale[1] = file.readFloat(); bones[i].scale[2] = file.readFloat(); Bone temp = bones[i]; temp.parentIndex = pi[i]; //Debug.Write(temp.parentIndex); //if (temp.parentIndex != 0x0FFFFFFF && temp.parentIndex > -1) // bones[temp.parentIndex].children.Add(i); bones[i] = temp; } reset(); } }
private static void getAnimationKeyFrame(FileData input, Animation.KeyGroup group, out float endFrame) { float startFrame = input.readFloat(); endFrame = input.readFloat(); uint frameFlags = (uint)input.readInt(); //Debug.WriteLine(frameFlags.ToString("x")); //int preRepeat = (RenderBase.ORepeatMethod)(frameFlags & 0xf); //int postRepeat = (RenderBase.ORepeatMethod)((frameFlags >> 8) & 0xf); uint segmentFlags = (uint)input.readInt(); int interpolation = ((int)segmentFlags & 0xf); uint quantization = ((segmentFlags >> 8) & 0xff); uint entries = segmentFlags >> 16; float valueScale = input.readFloat(); float valueOffset = input.readFloat(); float frameScale = input.readFloat(); float frameOffset = input.readFloat(); uint offset = (uint)input.readInt(); if (offset < input.size()) { input.seek((int)offset); } for (int key = 0; key < entries; key++) { Animation.KeyFrame keyFrame = new Animation.KeyFrame(); //Console.WriteLine(quantization); switch (quantization) { /*case RenderBase.OSegmentQuantization.hermite128: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = input.ReadSingle(); * break; * case RenderBase.OSegmentQuantization.hermite64: * uint h64Value = input.ReadUInt32(); * keyFrame.frame = h64Value & 0xfff; * keyFrame.value = h64Value >> 12; * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = input.ReadInt16() / 256f; * break; * case RenderBase.OSegmentQuantization.hermite48: * keyFrame.frame = input.ReadByte(); * keyFrame.value = input.ReadUInt16(); * byte slope0 = input.ReadByte(); * byte slope1 = input.ReadByte(); * byte slope2 = input.ReadByte(); * keyFrame.inSlope = IOUtils.signExtend(slope0 | ((slope1 & 0xf) << 8), 12) / 32f; * keyFrame.outSlope = IOUtils.signExtend((slope1 >> 4) | (slope2 << 4), 12) / 32f; * break; * case RenderBase.OSegmentQuantization.unifiedHermite96: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * keyFrame.inSlope = input.ReadSingle(); * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite48: * keyFrame.frame = input.ReadUInt16() / 32f; * keyFrame.value = input.ReadUInt16(); * keyFrame.inSlope = input.ReadInt16() / 256f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.unifiedHermite32: * keyFrame.frame = input.ReadByte(); * ushort uH32Value = input.ReadUInt16(); * keyFrame.value = uH32Value & 0xfff; * keyFrame.inSlope = IOUtils.signExtend((uH32Value >> 12) | (input.ReadByte() << 4), 12) / 32f; * keyFrame.outSlope = keyFrame.inSlope; * break; * case RenderBase.OSegmentQuantization.stepLinear64: * keyFrame.frame = input.ReadSingle(); * keyFrame.value = input.ReadSingle(); * break;*/ case 7: // RenderBase.OSegmentQuantization.stepLinear32: uint sL32Value = (uint)input.readInt(); keyFrame.Frame = sL32Value & 0xfff; keyFrame.Value = sL32Value >> 12; break; default: Console.WriteLine("Unknown type " + quantization); break; } keyFrame.Frame = (keyFrame.Frame * frameScale) + frameOffset; keyFrame.Value = (keyFrame.Value * valueScale) + valueOffset; group.Keys.Add(keyFrame); } }
/** * 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 static SkelAnimation 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 numOfBones = d.readShort(); int frameSize = d.readShort(); int frameStart = d.readShort(); int offset1 = d.readInt(); int offset2 = d.readInt(); int offset3 = d.readInt(); SkelAnimation anim = new SkelAnimation(); anim.Tag = d; //anim.setModel(m); // base frames // These are linked to bones somehow, hash?? d.seek(offset1); // int[] framekey = new int[numOfBones]; KeyNode[] baseNode = new KeyNode[numOfBones]; for (int i = 0; i < numOfBones; i++) { 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()); } } if (hasRot) { if ((rFlag & 0xF) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0) { //Console.WriteLine(rFlag); } if ((rFlag & 0xF0) == 0xA0) { node.r_type = 3; } 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) == 0x70 || (rFlag & 0xF0) == 0x60) { // constant node.r_type = KeyNode.CONSTANT; node.rv = new Vector3(d.readFloat(), d.readFloat(), d.readFloat()); if ((rFlag & 0xF0) == 0x60) { d.skip(4); } } } 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()); } 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); } d.seek(offset3); for (int i = 0; i < frameSize; i++) { KeyFrame key = new KeyFrame(); key.frame = i; int off = d.pos(); for (int j = 0; j < numOfBones; j++) { KeyNode node = new KeyNode(); node.t_type = baseNode[j].t_type; node.r_type = baseNode[j].r_type; node.s_type = baseNode[j].s_type; node.id = baseNode[j].id; node.hash = baseNode[j].hash; d.seek(off + framekey[j]); if (baseNode[j].t_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / 0xffff); float i2 = ((float)d.readShort() / 0xffff); float i3 = ((float)d.readShort() / 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); } else { node.t = baseNode[j].t; } if (baseNode[j].r_type == 3) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (0xffff)); float i4 = ((float)d.readShort() / (0xffff)); node.r = new Quaternion(new Vector3(i1, i2, i3), i4); //Console.WriteLine(node.r.ToString()); //node.r = VBN.FromEulerAngles(i4 * i1, i4 * i2, i4 * i3); node.r_type = KeyNode.INTERPOLATED; //node.r.Normalize(); } else if (baseNode[j].r_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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))); node.r = new Quaternion(new Vector3(x, y, z), w); node.r.Normalize(); } else { float x = baseNode[j].rv.X; float y = baseNode[j].rv.Y; float z = baseNode[j].rv.Z; float w = (float)Math.Sqrt(1 - (x * x + y * y + z * z)); node.r = new Quaternion(baseNode[j].rv, w); } if (baseNode[j].s_type == KeyNode.INTERPOLATED) { float i1 = ((float)d.readShort() / (0xffff)); float i2 = ((float)d.readShort() / (0xffff)); float i3 = ((float)d.readShort() / (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); } else { node.s = baseNode[j].s; } key.addNode(node); } d.seek(off + frameStart); anim.addKeyframe(key); } return(anim); }