public void ReadBNTX(FileData f) { textures.Clear(); BFRES b = new BFRES(); temp = f.pos(); f.skip(8); //Magic int Version = f.readInt(); int ByteOrderMark = f.readShort(); int FormatRevision = f.readShort(); Text = f.readString(f.readInt() + temp, -1); f.skip(2); int strOffset = f.readShort(); int relocOffset = f.readInt(); int FileSize = f.readInt(); f.skip(4); //NX Magic int TexturesCount = f.readInt(); int InfoPtrsOffset = f.readInt(); int DataBlockOffset = f.readInt(); int DictOffset = f.readInt(); int strDictSize = f.readInt(); Text = Text + ".bntx"; BNTXFile = f.getSection(temp, FileSize); for (int i = 0; i < TexturesCount; i++) { f.seek(InfoPtrsOffset + temp + i * 8); BRTIOffset = f.readInt(); f.seek(BRTIOffset + temp); // textures.Add(new BRTI(f)); BRTI texture = new BRTI(f); if (!textured.ContainsKey(texture.Text)) { textured.Add(texture.Text, texture); } textures.Add(texture); } Nodes.AddRange(textures.ToArray()); }
public void read(FileData f) { f.skip(0xC); f.skip(1); name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1); subname = f.readString(f.pos(), 0x40); f.skip(0x40); f.skip(1); for (int i = 0; i < 3; i++) { startPos[i] = f.readFloat(); } useStartPos = Convert.ToBoolean(f.readByte()); f.skip(1); unk1 = f.readInt(); //Some kind of count? Only seen it as 0 so I don't know what it's for //Not sure what this is for, but it seems like an x,y,z followed by a hash f.skip(1); for (int i = 0; i < 3; i++) { unk2[i] = f.readFloat(); } unk3 = f.readInt(); f.skip(1); boneName = new char[0x40]; for (int i = 0; i < 0x40; i++) { boneName[i] = (char)f.readByte(); } }
public override void Read(string filename) { FileData buf = new FileData(filename); buf.Endian = Endianness.Little; buf.seek(0x06); short numAtlases = buf.readShort(); short numTextures = buf.readShort(); short flagsOffset = buf.readShort(); short entriesOffset = buf.readShort(); short stringsOffset = buf.readShort(); buf.seek(flagsOffset); for (int i = 0; i < numAtlases; i++) { atlases.Add((AtlasFlag)buf.readInt()); } buf.seek(entriesOffset); for (int i = 0; i < numTextures; i++) { Texture entry = new Texture(); int nameOffset = buf.readInt(); int nameOffset2 = buf.readInt(); // I have yet to see this. if (nameOffset != nameOffset2) { throw new NotImplementedException("texlist name offsets don't match?"); } buf.seek(stringsOffset + nameOffset); entry.name = buf.readString(); entry.topLeft = new Vector2(buf.readFloat(), buf.readFloat()); entry.botRight = new Vector2(buf.readFloat(), buf.readFloat()); entry.width = buf.readShort(); entry.height = buf.readShort(); entry.atlasId = buf.readShort(); textures.Add(entry); buf.skip(0x02); // Padding. } }
public void Read(FileData d) { hash = d.readInt(); unk1 = d.readInt(); int s = d.readByte(); name = d.readString(d.pos(), s - 1); d.skip(s); d.align(4); data = new float[0x2c]; for (int i = 0; i < 0x2c; i++) { data[i] = d.readFloat(); } }
public void ReadBNTX(FileData f) { ImageKey = "UVPattern"; SelectedImageKey = "UVPattern"; textures.Clear(); textured.Clear(); temp = f.pos(); f.skip(8); //Magic int Version = f.readInt(); int ByteOrderMark = f.readShort(); int FormatRevision = f.readShort(); Text = f.readString(f.readInt() + temp, -1); f.skip(2); int strOffset = f.readShort(); int relocOffset = f.readInt(); int FileSize = f.readInt(); f.skip(4); //NX Magic int TexturesCount = f.readInt(); int InfoPtrsOffset = f.readInt(); int DataBlockOffset = f.readInt(); int DictOffset = f.readInt(); int strDictSize = f.readInt(); for (int i = 0; i < TexturesCount; i++) { f.seek(InfoPtrsOffset + temp + i * 8); BRTIOffset = f.readInt(); f.seek(BRTIOffset + temp); // textures.Add(new BRTI(f)); BRTI texture = new BRTI(f); textured.Add(texture.Text, texture); textures.Add(texture); } Nodes.AddRange(textures.ToArray()); }
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 static Animation readAnim(FileData d, VBN m) { int offset = d.readInt(); int nameoff = d.readInt(); d.skip(4); int fCount = d.readShort(); int animDataCount = d.readShort(); d.skip(8); Animation anim = new Animation(d.readString(nameoff, -1)); anim.FrameCount = fCount; //anim.setModel(m); d.seek(offset); int sectionOffset = d.readInt() + offset; int size = d.readInt(); // size again for (int i = 0; i < size; i++) { // System.out.print(d.readShort()); // id d.skip(4); // id and unknown d.readShort(); //left d.readShort(); //right int nameOffset = d.readInt() + offset; int dataOffset = d.readInt() + offset; if (dataOffset == offset) { i--; continue; // d.skip(8); // nameOffset = d.readInt() + 4; // dataOffset = d.readInt() + offset; } int temp = d.pos(); d.seek(dataOffset); int pos = d.pos(); int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4; int flags = d.readInt(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; Animation.KeyNode node = new Animation.KeyNode(d.readString(nameOff, -1)); anim.Bones.Add(node); node.RotType = Animation.RotationType.EULER; if (hasS == 1) { if (Siso == 1) { float iss = d.readFloat(); node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (SXfixed == 1) { node.XSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SX", false, anim); } if (SYfixed == 1) { node.YSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SY", false, anim); } if (SZfixed == 1) { node.ZSCA.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, s_type, pos, node, "SZ", false, anim); } } } if (hasR == 1) { if (Riso == 1) { float iss = (float)((d.readFloat()) * Math.PI / 180f); node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (RXfixed == 1) { node.XROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RX", false, anim); } if (RYfixed == 1) { node.YROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RY", false, anim); } if (RZfixed == 1) { node.ZROT.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat()) }); } else { process(d, r_type, pos, node, "RZ", false, anim); } } } if (hasT == 1) { if (Tiso == 1) { float iss = d.readFloat(); node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = iss }); } else { if (Xfixed == 1) { node.XPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "X", false, anim); } if (Yfixed == 1) { node.YPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Y", false, anim); } if (Zfixed == 1) { node.ZPOS.Keys.Add(new Animation.KeyFrame() { Frame = 0, Value = d.readFloat() }); } else { process(d, t_type, pos, node, "Z", false, anim); } } } d.seek(temp); } return(anim); }
public void Read(ResFile TargetSwitchBFRES, FileData f) { Nodes.Add(TModels); Nodes.Add(TMaterialAnim); Nodes.Add(TVisualAnim); Nodes.Add(TShapeAnim); Nodes.Add(TSceneAnim); Nodes.Add(TEmbedded); ImageKey = "bfres"; SelectedImageKey = "bfres"; FSKACount = TargetSwitchBFRES.SkeletalAnims.Count; FVISCount = TargetSwitchBFRES.BoneVisibilityAnims.Count; FMAACount = TargetSwitchBFRES.MaterialAnims.Count; Console.WriteLine("Name = " + TargetSwitchBFRES.Name); foreach (ExternalFile ext in TargetSwitchBFRES.ExternalFiles) { f = new FileData(ext.Data); f.Endian = Endianness.Little; string EmMagic = f.readString(f.pos(), 4); if (EmMagic.Equals("BNTX")) //Textures { int temp = f.pos(); BNTX t = new BNTX(); t.ReadBNTX(f); TEmbedded.Nodes.Add(t); } } int ModelCur = 0; //FMDLs -Models- foreach (Model mdl in TargetSwitchBFRES.Models) { FMDL_Model model = new FMDL_Model(); //This will store VBN data and stuff model.Text = mdl.Name; TModels.Nodes.Add(model); ReadSkeleton(model, mdl); model.skeleton.reset(); model.skeleton.update(); //MeshTime!! foreach (Shape shp in mdl.Shapes) { Mesh poly = new Mesh(); poly.Text = shp.Name; poly.MaterialIndex = shp.MaterialIndex; poly.matrFlag = shp.VertexSkinCount; poly.fsklindx = shp.BoneIndex; TModels.Nodes[ModelCur].Nodes.Add(poly); ReadVertexBuffer(mdl, shp, poly); // int LODCount = shp.Meshes.Count - 1; //For going to the lowest poly LOD mesh int LODCount = 0; uint FaceCount = FaceCount = shp.Meshes[LODCount].IndexCount; uint[] indicesArray = shp.Meshes[LODCount].GetIndices().ToArray(); poly.BoundingCount = shp.SubMeshBoundings.Count; for (int face = 0; face < FaceCount; face++) { poly.faces.Add((int)indicesArray[face] + (int)shp.Meshes[LODCount].FirstVertex); } foreach (Bounding bnd in shp.SubMeshBoundings) { Mesh.BoundingBox box = new Mesh.BoundingBox(); box.Center = new Vector3(bnd.Center.X, bnd.Center.Y, bnd.Center.Z); box.Extent = new Vector3(bnd.Extent.X, bnd.Extent.Y, bnd.Extent.Z); poly.boundingBoxes.Add(box); //Each box is by LOD mesh. This will be in a seperate class later so only one will be added } foreach (float r in shp.RadiusArray) { poly.radius.Add(r); } // Read materials Material mat = mdl.Materials[shp.MaterialIndex]; poly.material.Name = mat.Name; ReadTextureRefs(mat, poly); ReadShaderParams(mat, poly); ReadRenderInfo(mat, poly); foreach (Sampler smp in mdl.Materials[shp.MaterialIndex].Samplers) { SamplerInfo s = new SamplerInfo(); s.WrapModeU = (int)smp.WrapModeU; s.WrapModeV = (int)smp.WrapModeV; s.WrapModeW = (int)smp.WrapModeW; poly.material.samplerinfo.Add(s); } model.poly.Add(poly); } models.Add(model); ModelCur++; } }
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 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) { 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(); } // TODO: Finished Relocation table stuff 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.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Texture * case 0x25: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Vertex * // Trying to understand the mess first * case 0x26: f.writeInt((off * 4) + header.mainHeaderOffset, Convert.ToInt32(((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000)); break; //Index 16 bits mode * //case 0x27: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 8) * { * switch (flag) * { * case 0x24: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 0x21) * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x27: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x29: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + 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: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset * case 0x2b: writer.Write(peek(input) + 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: writer.Write((peek(input) + 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); Debug.WriteLine("dOffset: " + dOffset.ToString("X")); 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.boneName = f.readString(f.readInt(), -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); /* //Skeletal Animations * * SkelAnimation anim = new SkelAnimation(); * * for (int index = 0; index < content.skeletalAnimationsPointerTableEntries; index++) * { * f.seek(content.skeletalAnimationsPointerTableOffset + (index * 4)); * int dataOffset = f.readInt(); * f.seek(dataOffset); * * RenderBase.OSkeletalAnimation skeletalAnimation = new RenderBase.OSkeletalAnimation(); * * skeletalAnimation.name = f.readString(f.readInt(), -1); * int animationFlags = f.readInt(); * skeletalAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * skeletalAnimation.frameSize = f.readFloat(); * int boneTableOffset = f.readInt(); * int boneTableEntries = f.readInt(); * int metaDataPointerOffset = f.readInt(); * * // /*if (metaDataPointerOffset != 0) * // { * // data.Seek(metaDataPointerOffset, SeekOrigin.Begin); * // skeletalAnimation.userData = getMetaData(input); * // } * * for (int i = 0; i < boneTableEntries; i++) * { * f.seek(boneTableOffset + (i * 4)); * int offset = f.readInt(); * * RenderBase.OSkeletalAnimationBone bone = new RenderBase.OSkeletalAnimationBone(); * * f.seek(offset); * bone.name = f.readString(f.readInt(), -1); * int animationTypeFlags = f.readInt(); * * int flags = f.readInt(); * * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * switch (segmentType) * { * case RenderBase.OSegmentType.transform: * f.seek(offset + 0x18); * * uint notExistMask = 0x80000; * uint 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; * * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * frame.exists = !notExist; * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * int frameOffset = f.readInt(); * long position = data.Position; * f.seek(frameOffset); * getAnimationKeyFrame(input, frame); * f.seek(position); * } * } * else * data.Seek(4, SeekOrigin.Current); * * 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 RenderBase.OSegmentType.transformQuaternion: * bone.isFrameFormat = true; * * uint scaleOffset = input.ReadUInt32(); * uint rotationOffset = input.ReadUInt32(); * uint translationOffset = input.ReadUInt32(); * * if ((flags & 0x20) == 0) * { * bone.scale.exists = true; * data.Seek(scaleOffset, SeekOrigin.Begin); * * if ((flags & 4) > 0) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.scale.startFrame = input.ReadSingle(); * bone.scale.endFrame = input.ReadSingle(); * * uint scaleFlags = input.ReadUInt32(); * uint scaleDataOffset = input.ReadUInt32(); * uint scaleEntries = input.ReadUInt32(); * * data.Seek(scaleDataOffset, SeekOrigin.Begin); * for (int j = 0; j < scaleEntries; j++) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * if ((flags & 0x10) == 0) * { * bone.rotationQuaternion.exists = true; * data.Seek(rotationOffset, SeekOrigin.Begin); * * if ((flags & 2) > 0) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * else * { * bone.rotationQuaternion.startFrame = input.ReadSingle(); * bone.rotationQuaternion.endFrame = input.ReadSingle(); * * uint rotationFlags = input.ReadUInt32(); * uint rotationDataOffset = input.ReadUInt32(); * uint rotationEntries = input.ReadUInt32(); * * data.Seek(rotationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < rotationEntries; j++) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * } * } * * if ((flags & 8) == 0) * { * bone.translation.exists = true; * data.Seek(translationOffset, SeekOrigin.Begin); * * if ((flags & 1) > 0) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.translation.startFrame = input.ReadSingle(); * bone.translation.endFrame = input.ReadSingle(); * * uint translationFlags = input.ReadUInt32(); * uint translationDataOffset = input.ReadUInt32(); * uint translationEntries = input.ReadUInt32(); * * data.Seek(translationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < translationEntries; j++) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * break; * case RenderBase.OSegmentType.transformMatrix: * bone.isFullBakedFormat = true; * * input.ReadUInt32(); * input.ReadUInt32(); * uint matrixOffset = input.ReadUInt32(); * uint entries = input.ReadUInt32(); * * data.Seek(matrixOffset, SeekOrigin.Begin); * for (int j = 0; j < entries; j++) * { * RenderBase.OMatrix transform = new RenderBase.OMatrix(); * transform.M11 = input.ReadSingle(); * transform.M21 = input.ReadSingle(); * transform.M31 = input.ReadSingle(); * transform.M41 = input.ReadSingle(); * * transform.M12 = input.ReadSingle(); * transform.M22 = input.ReadSingle(); * transform.M32 = input.ReadSingle(); * transform.M42 = input.ReadSingle(); * * transform.M13 = input.ReadSingle(); * transform.M23 = input.ReadSingle(); * transform.M33 = input.ReadSingle(); * transform.M43 = input.ReadSingle(); * * 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); * } * * models.skeletalAnimation.list.Add(skeletalAnimation); * } * * //Material Animations * for (int index = 0; index < contentHeader.materialAnimationsPointerTableEntries; index++) * { * data.Seek(contentHeader.materialAnimationsPointerTableOffset + (index * 4), SeekOrigin.Begin); * uint dataOffset = input.ReadUInt32(); * data.Seek(dataOffset, SeekOrigin.Begin); * * RenderBase.OMaterialAnimation materialAnimation = new RenderBase.OMaterialAnimation(); * * materialAnimation.name = readString(input); * uint animationFlags = input.ReadUInt32(); * materialAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * materialAnimation.frameSize = input.ReadSingle(); * uint dataTableOffset = input.ReadUInt32(); * uint dataTableEntries = input.ReadUInt32(); * input.ReadUInt32(); * uint textureNameTableOffset = input.ReadUInt32(); * uint textureNameTableEntries = input.ReadUInt32(); * * data.Seek(textureNameTableOffset, SeekOrigin.Begin); * for (int i = 0; i < textureNameTableEntries; i++) * { * string name = readString(input); * materialAnimation.textureName.Add(name); * } * * for (int i = 0; i < dataTableEntries; i++) * { * data.Seek(dataTableOffset + (i * 4), SeekOrigin.Begin); * uint offset = input.ReadUInt32(); * * RenderBase.OMaterialAnimationData animationData = new RenderBase.OMaterialAnimationData(); * * data.Seek(offset, SeekOrigin.Begin); * animationData.name = readString(input); * uint animationTypeFlags = input.ReadUInt32(); * uint flags = input.ReadUInt32(); * * animationData.type = (RenderBase.OMaterialAnimationType)(animationTypeFlags & 0xff); * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * * int segmentCount = 0; * switch (segmentType) * { * case RenderBase.OSegmentType.rgbaColor: segmentCount = 4; break; * case RenderBase.OSegmentType.vector2: segmentCount = 2; break; * case RenderBase.OSegmentType.single: segmentCount = 1; break; * case RenderBase.OSegmentType.integer: segmentCount = 1; break; * } * * for (int j = 0; j < segmentCount; j++) * { * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * * data.Seek(offset + 0xc + (j * 4), SeekOrigin.Begin); * * frame.exists = (flags & (0x100 << j)) == 0; * bool constant = (flags & (1 << j)) > 0; * * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * uint frameOffset = input.ReadUInt32(); * data.Seek(frameOffset, SeekOrigin.Begin); * getAnimationKeyFrame(input, frame); * } * } * * animationData.frameList.Add(frame); * } * * materialAnimation.data.Add(animationData); * } * * models.materialAnimation.list.Add(materialAnimation); * } * */ } }
/*type 1 - collisions * type 2 - spawns * type 3 - respawns * type 4 - camera bounds * type 5 - death boundaries * type 6 - ??? * type 7 - ITEMPT_transform * type 8 - enemyGenerator * type 9 - ITEMPT * type 10 - fsAreaCam (and other fsArea's ? ) * type 11 - fsCamLimit * type 12 - damageShapes (damage sphere and damage capsule are the only ones I've seen, type 2 and 3 respectively) * type 13 - item spawners * type 14 - general shapes (general rect, general path, etc.) * type 15 - general points * type 16 - ??? * type 17 - FsStartPoint * type 18 - ??? * type 19 - ???*/ public override void Read(string filename) { FileData f = new FileData(filename); f.seek(0xB);//It's magic int collisionCount = f.readInt(); for (int i = 0; i < collisionCount; i++) { Collision temp = new Collision(); temp.read(f); collisions.Add(temp); } f.skip(1); //Seperation char int spawnCount = f.readInt(); for (int i = 0; i < spawnCount; i++) { Point temp = new Point(); f.skip(0xD); temp.name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char temp.subname = f.readString(f.pos(), 0x40); f.skip(0xA6); temp.x = f.readFloat(); temp.y = f.readFloat(); spawns.Add(temp); } f.skip(1);//Seperation char int respawnCount = f.readInt(); for (int i = 0; i < respawnCount; i++) { Point temp = new Point(); f.skip(0xD); temp.name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char temp.subname = f.readString(f.pos(), 0x40); f.skip(0xA6); temp.x = f.readFloat(); temp.y = f.readFloat(); respawns.Add(temp); } f.skip(1);//Seperation char int cameraCount = f.readInt(); for (int i = 0; i < cameraCount; i++) { Bounds temp = new Bounds(); f.skip(0xD); temp.name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char temp.subname = f.readString(f.pos(), 0x40); f.skip(0xA6); temp.left = f.readFloat(); temp.right = f.readFloat(); temp.top = f.readFloat(); temp.bottom = f.readFloat(); cameraBounds.Add(temp); } f.skip(1);//Seperation char int blastzoneCount = f.readInt(); for (int i = 0; i < blastzoneCount; i++) { Bounds temp = new Bounds(); f.skip(0xD); temp.name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char temp.subname = f.readString(f.pos(), 0x40); f.skip(0xA6); temp.left = f.readFloat(); temp.right = f.readFloat(); temp.top = f.readFloat(); temp.bottom = f.readFloat(); blastzones.Add(temp); } f.skip(1); //Seperation char if (f.readInt() != 0) //1 { return; } f.skip(1); //Seperation char if (f.readInt() != 0) //2 { return; } f.skip(1);//Seperation char int enemyGeneratorCount = f.readInt(); if (enemyGeneratorCount != 0) { return; } f.skip(1); //Seperation char if (f.readInt() != 0) //4 { return; } f.skip(1);//Seperation char int fsAreaCamCount = f.readInt(); if (fsAreaCamCount != 0) { return; } f.skip(1);//Seperation char int fsCamLimitCount = f.readInt(); if (fsCamLimitCount != 0) { return; } f.skip(1);//Seperation char int damageShapeCount = f.readInt(); for (int i = 0; i < damageShapeCount; i++) { f.skip(0xD); string tempName = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char string tempSubname = f.readString(f.pos(), 0x40); f.skip(0xA6); int shapeType = f.readInt(); if (shapeType == 2) { Sphere temp = new Sphere(); temp.name = tempName; temp.subname = tempSubname; temp.x = f.readFloat(); temp.y = f.readFloat(); temp.z = f.readFloat(); temp.radius = f.readFloat(); f.skip(0x11); damageSpheres.Add(temp); } else if (shapeType == 3) { Capsule temp = new Capsule(); temp.name = tempName; temp.subname = tempSubname; temp.x = f.readFloat(); temp.y = f.readFloat(); temp.z = f.readFloat(); temp.dx = f.readFloat(); temp.dy = f.readFloat(); temp.dz = f.readFloat(); temp.r = f.readFloat(); temp.unk = f.readFloat(); f.skip(1); damageCapsules.Add(temp); } else { throw new NotImplementedException(); } } f.skip(1);//Seperation char int itemCount = f.readInt(); for (int i = 0; i < itemCount; i++) { ItemSpawner temp = new ItemSpawner(); temp.read(f); items.Add(temp); } f.skip(1);//Seperation char int generalShapeCount = f.readInt(); for (int i = 0; i < generalShapeCount; i++) { f.skip(0xD); string tempName = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char string tempSubname = f.readString(f.pos(), 0x40); f.skip(0xAB); int shapeType = f.readInt(); LVDGeneralShape p; if (shapeType == 1) { p = new GeneralPoint(); } else if (shapeType == 3) { p = new GeneralRect(); } else if (shapeType == 4) { p = new GeneralPath(); } else { throw new Exception($"Unknown shape type {shapeType} at offset {f.pos() - 4}"); } p.name = tempName; p.subname = tempSubname; p.Read(f); generalShapes.Add(p); } f.skip(1); int generalPointCount = f.readInt(); for (int i = 0; i < generalPointCount; i++) { Point temp = new Point(); f.skip(0xD); temp.name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char temp.subname = f.readString(f.pos(), 0x40); f.skip(0xAF); temp.x = f.readFloat(); temp.y = f.readFloat(); f.skip(0x14); generalPoints.Add(temp); } if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); if (f.readInt() != 0) //8 { return; //no clue how to be consistent in reading these so... } f.skip(1); //LVD doesn't end here and neither does my confusion, will update this part later }
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; }
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 override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++) { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Debug.WriteLine("Animation Name: " + skeletalAnimationName); //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X")); //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X")); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); OSkeletalAnimationBone bone = new OSkeletalAnimationBone(); f.seek(offset); bone.name = f.readString(f.readInt(), -1); Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); int flags = f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0x18); int notExistMask = 0x80000; int constantMask = 0x200; for (int j = 0; j < 2; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup(); frame.exists = !notExist; if (frame.exists) { if (constant) { frame.interpolation = OInterpolationMode.linear; frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0)); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); //getAnimationKeyFrame(input, frame); f.seek(position); } } else { f.seek(f.pos() + 0x04); } if (j == 0) { switch (axis) { case 0: bone.rotationX = frame; break; case 1: bone.rotationY = frame; break; case 2: bone.rotationZ = frame; break; } } else { switch (axis) { case 0: bone.translationX = frame; break; case 1: bone.translationY = frame; break; case 2: bone.translationZ = frame; break; } } notExistMask <<= 1; constantMask <<= 1; } constantMask <<= 1; } break; case OSegmentType.transformQuaternion: bone.isFrameFormat = true; int scaleOffset = f.readInt(); int rotationOffset = f.readInt(); int translationOffset = f.readInt(); if ((flags & 0x20) == 0) { bone.scale.exists = true; f.seek(scaleOffset); if ((flags & 4) > 0) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.scale.startFrame = f.readFloat(); bone.scale.endFrame = f.readFloat(); int scaleFlags = f.readInt(); int scaleDataOffset = f.readInt(); int scaleEntries = f.readInt(); f.seek(scaleDataOffset); for (int j = 0; j < scaleEntries; j++) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } if ((flags & 0x10) == 0) { bone.rotationQuaternion.exists = true; f.seek(rotationOffset); if ((flags & 2) > 0) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } else { bone.rotationQuaternion.startFrame = f.readFloat(); bone.rotationQuaternion.endFrame = f.readFloat(); int rotationFlags = f.readInt(); int rotationDataOffset = f.readInt(); int rotationEntries = f.readInt(); f.seek(rotationDataOffset); for (int j = 0; j < rotationEntries; j++) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } } } if ((flags & 8) == 0) { bone.translation.exists = true; f.seek(translationOffset); if ((flags & 1) > 0) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.translation.startFrame = f.readFloat(); bone.translation.endFrame = f.readFloat(); int translationFlags = f.readInt(); int translationDataOffset = f.readInt(); int translationEntries = f.readInt(); f.seek(translationDataOffset); for (int j = 0; j < translationEntries; j++) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } break; case OSegmentType.transformMatrix: bone.isFullBakedFormat = true; f.readInt(); f.readInt(); int matrixOffset = f.readInt(); int entries = f.readInt(); f.seek(matrixOffset); for (int j = 0; j < entries; j++) { /*OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform);*/ } break; default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); } //skeletalAnimation.bone.Add(bone); } } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.Height = f.readUShort(); tex.Width = f.readUShort(); f.skip(12); int doffset = f.readInt(); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type); //Texture texture = new Texture2D(tex.texture); //tex.display = texture.Id; } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readUShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); String name = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readUShort(); int rootRightNode = f.readUShort(); int rootNameOffset = f.readInt(); for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = f.readShort(); short rightNode = f.readShort(); objectName[i] = f.readString(f.readInt(), -1); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readUShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readUShort(); mbn.mesh[index].Text = objectName[nameId]; // node visibility TODO: finish... mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readUShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = f.readShort(); short boneSpace = f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data bones.bones.Add(bone); model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public static SkelAnimation readAnim(FileData d, VBN m) { int offset = d.readInt(); int nameoff = d.readInt(); d.skip(4); int fCount = d.readShort(); int animDataCount = d.readShort(); d.skip(8); SkelAnimation anim = new SkelAnimation(); //anim.setModel(m); d.seek(offset); int sectionOffset = d.readInt() + offset; int size = d.readInt(); // size again for (int i = 0; i < size; i++) { // System.out.print(d.readShort()); // id d.skip(4); // id and unknown d.readShort(); //left d.readShort(); //right int nameOffset = d.readInt() + offset; int dataOffset = d.readInt() + offset; if (dataOffset == offset) { i--; continue; // d.skip(8); // nameOffset = d.readInt() + 4; // dataOffset = d.readInt() + offset; } int temp = d.pos(); d.seek(dataOffset); int pos = d.pos(); int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4; int flags = d.readInt(); int t_type = (flags >> 0x1e) & 0x3; int r_type = (flags >> 0x1b) & 0x7; int s_type = (flags >> 0x19) & 0x3; int hasT = (flags >> 0x18) & 0x1; int hasR = (flags >> 0x17) & 0x1; int hasS = (flags >> 0x16) & 0x1; int Zfixed = (flags >> 0x15) & 0x1; int Yfixed = (flags >> 0x14) & 0x1; int Xfixed = (flags >> 0x13) & 0x1; int RZfixed = (flags >> 0x12) & 0x1; int RYfixed = (flags >> 0x11) & 0x1; int RXfixed = (flags >> 0x10) & 0x1; int SZfixed = (flags >> 0xf) & 0x1; int SYfixed = (flags >> 0xe) & 0x1; int SXfixed = (flags >> 0xd) & 0x1; int Tiso = (flags >> 0x6) & 0x1; int Riso = (flags >> 0x5) & 0x1; int Siso = (flags >> 0x4) & 0x1; if (hasS == 1) { if (Siso == 1) { //System.out.println("S is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.s_type = 1; float iss = d.readFloat(); node.s = new OpenTK.Vector3(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.s_type = 1; // System.out.println("Scale: " + SXfixed + " " + SYfixed + " " + SZfixed + " " + s_type); node.s = new OpenTK.Vector3(-99, -99, -99); if (SXfixed == 1) { node.s.X = d.readFloat(); } else { process(d, s_type, pos, anim, "SX", nid, false, m); } if (SYfixed == 1) { node.s.Y = d.readFloat(); } else { process(d, s_type, pos, anim, "SY", nid, false, m); } if (SZfixed == 1) { node.s.Z = d.readFloat(); } else { process(d, s_type, pos, anim, "SZ", nid, false, m); } } } if (hasR == 1) { if (Riso == 1) { //System.out.println("R is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); Console.WriteLine(nid.ToString("x")); KeyNode node = anim.getNode(0, nid); node.r_type = 1; float iss = (float)((d.readFloat()) * Math.PI / 180f); node.r = VBN.FromEulerAngles(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); // System.out.println("Rot: " + RXfixed + " " + RYfixed + " " + RZfixed); node.r = new OpenTK.Quaternion(-99, -99, -99, 0); if (RXfixed == 1) { node.r.X = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RX", nid, false, m); } if (RYfixed == 1) { node.r.Y = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RY", nid, false, m); } if (RZfixed == 1) { node.r.Z = (float)(Math.PI / 180f) * (d.readFloat()); } else { process(d, r_type, pos, anim, "RZ", nid, false, m); } } } if (hasT == 1) { if (Tiso == 1) { //System.out.println("T is ISO"); int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.t_type = 1; float iss = d.readFloat(); node.t = new OpenTK.Vector3(iss, iss, iss); } else { int nid = anim.getNodeIndex(d.readString(nameOff, -1), m); KeyNode node = anim.getNode(0, nid); node.t_type = 1; // System.out.println("Trans: " + Xfixed + " " + Yfixed + " " + Zfixed); node.t = new OpenTK.Vector3(-99, -99, -99); if (Xfixed == 1) { node.t.X = d.readFloat(); } else { process(d, t_type, pos, anim, "X", nid, false, m); } if (Yfixed == 1) { node.t.Y = d.readFloat(); } else { process(d, t_type, pos, anim, "Y", nid, false, m); } if (Zfixed == 1) { node.t.Z = d.readFloat(); } else { process(d, t_type, pos, anim, "Z", nid, false, m); } } } d.seek(temp); } // keynode rotations need caluclation foreach (KeyFrame f in anim.frames) { foreach (KeyNode n in f.nodes) { n.r = VBN.FromEulerAngles(n.r.Z, n.r.Y, n.r.X); } } //anim.calcMax(); return(anim); }
public VBN GetVBN(FileData d) { VBN v = new VBN(); d.Endian = Endianness.Big; d.seek(8); int ver = d.readInt(); d.skip(4); //outer offset to brres int boneHeader = 0x40; // for version 9 only int dlist = d.readInt(); int boneSec = d.readInt(); int vertSec = d.readInt(); int normSec = d.readInt(); int colrSec = d.readInt(); int texcSec = d.readInt(); d.skip(8); int polySec = d.readInt(); d.seek(0x40); d.skip(16); int vertCount = d.readInt(); int faceCount = d.readInt(); d.skip(4); int boneCount = d.readInt(); v.totalBoneCount = (uint)boneCount; for (int i = 0; i < 3; i++) { v.boneCountPerType[i + 1] = 0; } d.skip(4); int bonetableoff = d.readInt() + boneHeader; d.seek(bonetableoff); int bcount = d.readInt(); int[] nodeIndex = new int[bcount]; for (int i = 0; i < bcount; i++) { nodeIndex[i] = d.readInt(); } Random rng = new Random(); uint boneID = (uint)rng.Next(1, 0xFFFFFF); // BONES----------------------------------------------- d.seek(boneSec); d.skip(4); // length int bseccount = d.readInt(); for (int i = 0; i < bseccount; i++) { Debug.Write(i); d.skip(4); // entry id and unknown d.skip(4); // left and right index int name = d.readInt() + boneSec; int data = d.readInt() + boneSec; int temp = d.pos(); if (name != boneSec && data != boneSec) { // read bone data d.seek(data); d.skip(8); int nameOff = d.readInt() + data; int index = d.readInt(); // id d.skip(4); // index d.skip(8); // idk billboard settings and padding Bone n = new Bone(v); n.scale = new float[3]; n.position = new float[3]; n.rotation = new float[3]; d.skip(4); // index n.scale[0] = d.readFloat(); n.scale[1] = d.readFloat(); n.scale[2] = d.readFloat(); n.rotation[0] = toRadians(d.readFloat()); n.rotation[1] = toRadians(d.readFloat()); n.rotation[2] = toRadians(d.readFloat()); n.position[0] = d.readFloat(); n.position[1] = d.readFloat(); n.position[2] = d.readFloat(); n.pos = new Vector3(n.position[0], n.position[1], n.position[2]); n.sca = new Vector3(n.scale[0], n.scale[1], n.scale[2]); n.rot = (VBN.FromEulerAngles(n.rotation [2], n.rotation [1], n.rotation [0])); d.skip(24); d.seek(data + 0x5C); d.seek(d.readInt() + data + 12); int parentid = 0x0FFFFFFF; if (d.pos() != data + 12) { parentid = d.readInt(); } n.parentIndex = (int)parentid; n.boneName = d.readString(nameOff, -1).ToCharArray(); n.boneId = boneID; boneID++; v.bones.Add(n); } else { bseccount++; } d.seek(temp); } v.update(); //v.updateChildren(); v.boneCountPerType[0] = (uint)v.bones.Count; return(v); }
public void Read(FileData d) { d.Endian = System.IO.Endianness.Big; d.seek(4); // skip filesize int dataSize = d.readInt(); int offsetTableCount = d.readInt(); int rootA = d.readInt(); int headerSize = 0x20; int rootOffset = headerSize + dataSize + offsetTableCount * 4; d.seek(rootOffset); int figtree = d.readInt() + headerSize; d.skip(4); String name = d.readString(d.pos(), -1); this.Name = name; d.seek(figtree); d.skip(8); float frameCount = d.readFloat(); int keyOffset = d.readInt(); if (Debug) { Console.WriteLine(name + "\tCount: " + frameCount); } this.frameCount = (int)frameCount; int temp = d.pos(); d.seek(keyOffset + 0x20); //int boneCount = 0x2E; // TODO: Use actual bone count 0x35 List <int> keyFrameCount = new List <int>(); int bid = d.readByte(); while (bid != 0xFF) { keyFrameCount.Add(bid); bid = d.readByte(); nodes.Add(new List <DATAnimTrack>()); } int boneCount = keyFrameCount.Count; if (Debug) { Console.WriteLine(boneCount); } d.seek(temp); int animDataOffset = 0; int[] trackcount = new int[offsetTableCount]; for (int i = 0; i < offsetTableCount; i++) { trackcount[i] = d.readInt(); if (i == 0) { animDataOffset = trackcount[i]; } } d.seek(animDataOffset + 0x20); for (int i = 0; i < boneCount; i++) { // bonecount if (Debug) { Console.WriteLine("Bone " + i + ": " + keyFrameCount[i] + "\t" + d.pos().ToString("x")); } for (int j = 0; j < keyFrameCount[i]; j++) { int length = d.readShort(); d.skip(2); int trackType = d.readByte(); int valueFormat = d.readByte(); int tanFormat = d.readByte(); d.skip(1); int dataoff = d.readInt() + 0x20; if (Debug) { Console.WriteLine((AnimType)trackType + "\tLength: " + length + "\tOffset: " + dataoff.ToString("x") + " " + valueFormat.ToString("x") + " " + tanFormat.ToString("x")); } // System.out.println(valueFormat + " " + tanFormat); readKeyFrame(d, length, dataoff, valueFormat, tanFormat, keyFrameCount[i], i, trackType); } } }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(8); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendOffset = f.readInt(); int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandLength = f.readInt(); int dataLength = f.readInt(); int dataExtendLength = f.readInt(); int relocationTableLength = f.readInt(); int datsSecLength = f.readInt(); int desSecLength = f.readInt(); int flags = f.readShort(); int addressCount = f.readShort(); // TODO: Finished Relocation table stuff 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); break; } } // Content Header f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt() + mainHeaderOffset; int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt() + mainHeaderOffset; int scenePointerTableOffset = f.readInt() + mainHeaderOffset; int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt() + mainHeaderOffset; // Textures // WIP Section for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset + mainHeaderOffset); int textureCommandsOffset = f.readInt() + gpuCommandOffset; int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt() + stringTableOffset, -1); f.seek(textureCommandsOffset); 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() + dataOffset; 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 < modelsPointerTableEntries; modelIndex++) { f.seek(modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt() + mainHeaderOffset; // 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); int materialsTableOffset = f.readInt() + mainHeaderOffset; int materialsTableEntries = f.readInt(); int materialsNamesOffset = f.readInt() + mainHeaderOffset; int verticesTableOffset = f.readInt() + mainHeaderOffset; //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt() + mainHeaderOffset; int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt() + mainHeaderOffset; int objectsNodeVisibilityOffset = f.readInt() + mainHeaderOffset; int objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt() + stringTableOffset, -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt() + mainHeaderOffset; f.readInt(); //0x0 int metaDataPointerOffset = f.readInt() + mainHeaderOffset; f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + mainHeaderOffset; 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() + stringTableOffset, -1); //Debug.WriteLine(objectName[i]); } // 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() + stringTableOffset, -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); 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.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; 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() + mainHeaderOffset; des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt() + mainHeaderOffset; des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt() + mainHeaderOffset; 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(skeletonOffset); for (int index = 0; index < 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.boneName = f.readString(f.readInt() + stringTableOffset, -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
public override void Read(string filename) { FileData f = new FileData(filename); header.magic = f.readInt(); header.unk0 = f.readInt(); if (header.unk0 == 0x10000000) { f.Endian = Endianness.Little; f.skip(f.pos() - 4); header.unk0 = f.readInt(); } header.unk1 = f.readInt(); header.unk2 = f.readInt(); header.unk3 = f.readInt(); header.unk4 = f.readInt(); header.unk5 = f.readInt(); header.filesize = f.readInt(); header.unk6 = f.readInt(); header.unk7 = f.readInt(); header.unk8 = f.readInt(); header.unk9 = f.readInt(); header.unk10 = f.readInt(); header.unk11 = f.readInt(); header.unk12 = f.readInt(); header.unk13 = f.readInt(); bool done = false; while (!done) { int tagOffset = f.pos(); TagType tagType = (TagType)f.readInt(); int tagSize = f.readInt(); // in dwords! switch (tagType) { case TagType.Invalid: { // uhhh. i think there's a specific exception for this throw new Exception("Malformed file"); } case TagType.Symbols: { int numSymbols = f.readInt(); while (Strings.Count < numSymbols) { int len = f.readInt(); Strings.Add(f.readString()); f.skip(4 - (f.pos() % 4)); } break; } case TagType.Colors: { int numColors = f.readInt(); for (int i = 0; i < numColors; i++) { AddColor(new Vector4(f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f)); } break; } case TagType.Fonts: { unk000A = new UnhandledTag(tagType, tagSize, f); break; } case TagType.UnkF00A: { unkF00A = new UnhandledTag(tagType, tagSize, f); break; } case TagType.UnkF00B: { unkF00B = new UnhandledTag(tagType, tagSize, f); break; } case TagType.UnkF008: { unkF008 = new UnhandledTag(tagType, tagSize, f); break; } case TagType.UnkF009: { unkF009 = new UnhandledTag(tagType, tagSize, f); break; } case TagType.Defines: { Defines = new Properties2(f); break; } case TagType.ActionScript: { Actionscript = new UnhandledTag(tagType, tagSize, f); break; } case TagType.ActionScript2: { Actionscript2 = new UnhandledTag(tagType, tagSize, f); break; } case TagType.End: { done = true; break; } case TagType.Transforms: { int numTransforms = f.readInt(); for (int i = 0; i < numTransforms; i++) { float a = f.readFloat(); float b = f.readFloat(); float c = f.readFloat(); float d = f.readFloat(); float x = f.readFloat(); float y = f.readFloat(); var mat = new Matrix4( a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, x, y, 0, 1 ); Transforms.Add(mat); } break; } case TagType.Positions: { int numPositions = f.readInt(); for (int i = 0; i < numPositions; i++) { Positions.Add(new Vector2(f.readFloat(), f.readFloat())); } break; } case TagType.Bounds: { int numBounds = f.readInt(); for (int i = 0; i < numBounds; i++) { Bounds.Add(new Rect(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } break; } case TagType.Properties: { properties = new Properties(f); break; } case TagType.TextureAtlases: { int numAtlases = f.readInt(); for (int i = 0; i < numAtlases; i++) { TextureAtlas atlas = new TextureAtlas(); atlas.id = f.readInt(); atlas.nameId = f.readInt(); atlas.width = f.readFloat(); atlas.height = f.readFloat(); Atlases.Add(atlas); } break; } case TagType.Shape: { Shapes.Add(new Shape(f)); break; } case TagType.DynamicText: { Texts.Add(new DynamicText(f)); break; } case TagType.DefineSprite: { Sprites.Add(new Sprite(f)); break; } default: { throw new NotImplementedException($"Unhandled tag id: 0x{(uint)tagType:X} @ 0x{tagOffset:X}"); } } } } // Read()
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(); } }
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(); } }
/** * Reading and saving -------------------- **/ public override void Read(string filename) { FileData d = new FileData(filename); d.seek(0); d.Endian = Endianness.Little; format = d.readUShort(); unknown = d.readUShort(); flags = d.readInt(); mode = d.readInt(); bool hasNameTable = (flags & 2) > 0; int polyCount = d.readInt(); mesh = new List <Mesh>(); descript = new List <Descriptor>(); List <List <int> > prim = new List <List <int> >(); for (int i = 0; i < polyCount; i++) { if (i == 0 && mode == 1) { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } Mesh m = new Mesh(); mesh.Add(m); int faceCount = d.readInt(); List <int> prims = new List <int>(); prim.Add(prims); for (int j = 0; j < faceCount; j++) { int nodeCount = d.readInt(); List <int> nodeList = new List <int>(); m.nodeList.Add(nodeList); for (int k = 0; k < nodeCount; k++) { nodeList.Add(d.readInt()); // for a node list? } int primitiveCount = d.readInt(); prims.Add(primitiveCount); if (hasNameTable) { int nameId = d.readInt(); } if (mode == 0) { if (format == 4) { int[] buffer = new int[primitiveCount]; for (int k = 0; k < primitiveCount; k++) { buffer[k] = d.readUShort(); } d.align(4); List <int> buf = new List <int>(); buf.AddRange(buffer); m.faces.Add(buf); } else { Descriptor des = new Descriptor(); des.ReadDescription(d); descript.Add(des); } } } } if (mode == 0) { //Console.WriteLine("Extra!"); } // TODO: STRING TABLE if (hasNameTable) { for (int i = 0; i < mesh.Count; i++) { int index = d.readByte(); nameTable.Add(d.readString()); } } if (format != 4) { d.align(32); } // Vertex Bank int start = d.pos(); for (int i = 0; i < 1; i++) { if (mode == 0 || i == 0) { Descriptor des = descript[i]; if (format != 4) { while (d.pos() < start + des.length) { Vertex v = new Vertex(); vertices.Add(v); for (int k = 0; k < des.type.Length; k++) { d.align(2); switch (des.type[k]) { case 0: //Position v.pos.X = readType(d, des.format[k], des.scale[k]); v.pos.Y = readType(d, des.format[k], des.scale[k]); v.pos.Z = readType(d, des.format[k], des.scale[k]); break; case 1: //Normal v.nrm.X = readType(d, des.format[k], des.scale[k]); v.nrm.Y = readType(d, des.format[k], des.scale[k]); v.nrm.Z = readType(d, des.format[k], des.scale[k]); break; case 2: //Color v.col.X = (int)(readType(d, des.format[k], des.scale[k])); v.col.Y = (int)(readType(d, des.format[k], des.scale[k])); v.col.Z = (int)(readType(d, des.format[k], des.scale[k])); v.col.W = (int)(readType(d, des.format[k], des.scale[k])); break; case 3: //Tex0 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 4: //Tex1 v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k]))); break; case 5: //Bone Index v.node.Add(d.readByte()); v.node.Add(d.readByte()); break; case 6: //Bone Weight v.weight.Add(readType(d, des.format[k], des.scale[k])); v.weight.Add(readType(d, des.format[k], des.scale[k])); break; //default: // Console.WriteLine("WTF is this"); } } } d.align(32); } } for (int j = 0; j < mesh.Count; j++) { foreach (int l in prim[j]) { List <int> face = new List <int>(); mesh[j].faces.Add(face); for (int k = 0; k < l; k++) { face.Add(d.readUShort()); } d.align(32); } } } PreRender(); }
public void read(FileData f) { f.skip(0xD); name = f.readString(f.pos(), 0x38); f.skip(0x38); f.skip(1);//Seperation char subname = f.readString(f.pos(), 0x40); f.skip(0x40); f.skip(1);//Seperation char startPos[0] = f.readFloat(); startPos[1] = f.readFloat(); startPos[2] = f.readFloat(); useStartPos = (f.readByte() != 0); f.skip(1);//Seperation char unk2 = f.readInt(); f.skip(1); unk3 = f.read(0xC); f.skip(4); //FF FF FF FF f.skip(1); //Seperation char unk4 = new char[0x40]; for (int i = 0; i < 0x40; i++) { unk4[i] = (char)f.readByte(); } flag1 = Convert.ToBoolean(f.readByte()); flag2 = Convert.ToBoolean(f.readByte()); flag3 = Convert.ToBoolean(f.readByte()); flag4 = Convert.ToBoolean(f.readByte()); f.skip(1);//Seperation char //f.skip(0xAA); //Console.WriteLine(f.pos()); int vertCount = f.readInt(); for (int i = 0; i < vertCount; i++) { f.skip(1);//Seperation char Vector2D temp = new Vector2D(); temp.x = f.readFloat(); temp.y = f.readFloat(); verts.Add(temp); } f.skip(1);//Seperation char int normalCount = f.readInt(); for (int i = 0; i < normalCount; i++) { f.skip(1);//Seperation char Vector2D temp = new Vector2D(); temp.x = f.readFloat(); temp.y = f.readFloat(); normals.Add(temp); } f.skip(1); //Seperation char int cliffCount = f.readInt(); //CLIFFS tend to be useless f.skip(0xFC * cliffCount); //Standard CLIFFS are 0xFC in length, just skip em all f.skip(1); //Seperation char int materialCount = f.readInt(); for (int i = 0; i < materialCount; i++) { f.skip(1); //Seperation char CollisionMat temp = new CollisionMat(); temp.material = f.read(0xC); //Temporary, will work on fleshing out material more later materials.Add(temp); } }