/// <summary> /// Read a PrmEntry from PRM. /// </summary> /// <param name="br">Binary Reader to use.</param> public PrmEntry(DhBinaryReader br) { // Read Hash. Hash = br.ReadU16(); // Read NameLength. NameLength = br.ReadU16(); // Read Name. Name = br.ReadStr(NameLength); // Read ValueLength. ValueLength = br.ReadU32(); // Resolve Type from Hash. Type = PRMUtils.HashToType(Hash); // Check Type. switch (Type) { case PrmType.BYTE: // Read Value as a byte. Value = br.Read(); break; case PrmType.SHORT: // Read Value as a short. Value = br.ReadS16(); break; case PrmType.INT: // Read Value as a int. Value = br.ReadS32(); break; case PrmType.FLOAT: // Read Value as a float. Value = br.ReadF32(); break; case PrmType.RGBA: // Read Value as a Clr4. Value = br.ReadClr4(); break; case PrmType.VECTOR3: // Read Value as a Vector3. Value = br.ReadVec3(); break; default: throw new NotImplementedException("PRM parameter entry type is unknown!"); } }
/// <summary> /// Read a single graph object from BIN. /// </summary> /// <param name="br">Binary Reader to use.</param> /// <param name="graphObjectOffset">Offset to the graph objects.</param> public GraphObject(DhBinaryReader br, uint graphObjectOffset) // 112 bytes long { // Read Parent Index. ParentIndex = br.ReadS16(); // Read Child Index. ChildIndex = br.ReadS16(); // Read Next Index. NextIndex = br.ReadS16(); // Read Previous Index. PreviousIndex = br.ReadS16(); // Read Render Flags. RenderFlags = (GraphObjectRenderFlags)br.ReadU16(); // Unknown 1. (Padding?) Unknown1 = br.ReadU16(); // Read Scale. Scale = br.ReadVec3(); // Read Rotation. Rotation = br.ReadVec3(); // Read Position Position = br.ReadVec3(); // Read Bounding Box Minimum. BoundingBoxMinimum = br.ReadVec3(); // Read Bounding Box Maximum. BoundingBoxMaximum = br.ReadVec3(); // Read Bounding Sphere Radius. BoundingSphereRadius = br.ReadF32(); // Read Parent Index. PartCount = br.ReadS16(); // Unknown 3. (Padding?) Unknown3 = br.ReadU16(); // Read Parent Index. PartOffset = br.ReadS32(); // Unknown 4. (Padding?) Unknown4 = br.ReadU32s(7); // Initialize a new list to hold parts. Parts = new List <BinGraphObjectPart>(); // Offset to continue reading from. long currentPosition = br.Position(); // Goto graphobject's parts. br.Goto(graphObjectOffset + PartOffset); // Loop through parts. for (int i = 0; i < PartCount; i++) { // Read part and add it to the list of parts. Parts.Add(new BinGraphObjectPart(br)); } // Go back to return offset we saved earlier. br.Goto(currentPosition); }
/// <summary> /// Reads BIN from a byte array. /// </summary> /// <param name="data">The byte array containing the BIN data.</param> public BIN(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read bin version. Version = br.Read(); // Make sure the bin version is either 0x01 or 0x02. if (Version == 0x00 || Version > 0x02) { throw new Exception($"[BIN] {Version} is not a valid version!"); } // Read bin model name. ModelName = br.ReadFixedStr(11); // Define a new list to hold the bin's offsets. Offsets = br.ReadU32s(21); // Go to the bin graph object offset. br.Goto(Offsets[12]); // Get first graph object, then all of it's attached graph objects. GraphObjects = GetGraphObjects(br, 0); // Make sure bin batches has a offset. if (Offsets[11] != 0) { // Go to the bin batches offset. br.Goto(Offsets[11]); // Define a new list to hold the bin's batches. Batches = new List <Batch>(); // Loop through batches. for (int i = 0; i < GetBatchCount(); i++) { // Read a batch and add it to the batch list. Batches.Add(new Batch(br, Offsets[11])); } } // Make sure bin shaders has a offset. if (Offsets[10] != 0) { // Go to the bin shaders offset. br.Goto(Offsets[10]); // Define a new list to hold the bin's shaders. Shaders = new List <Shader>(); // Loop through shaders. for (int i = 0; i < GetShaderCount(); i++) { // Read a shader and add it to the shader list. Shaders.Add(new Shader(br)); } } // Make sure bin texture coordinates 1 has a offset. if (Offsets[7] != 0) { // Go to the bin texture coordinates 1 offset. br.Goto(Offsets[7]); // Define a new list to hold the bin's texture coordinates 1. TextureCoordinates1 = new List <Vec2>(); // Loop through texture coordinates 1. for (int i = 0; i < GetTexCoordinate1Count(); i++) { // Read a bin texture coordinates and add it to the texture coordinates 1 list. TextureCoordinates1.Add(br.ReadVec2()); } } // Make sure bin texture coordinates 0 has a offset. if (Offsets[6] != 0) { // Go to the bin texture coordinates 0 offset. br.Goto(Offsets[6]); // Define a new list to hold the bin's texture coordinates 0. TextureCoordinates0 = new List <Vec2>(); // Loop through texture coordinates 0. for (int i = 0; i < GetTexCoordinate0Count(); i++) { // Read a bin texture coordinates 0 and add it to the texture coordinates 0 list. TextureCoordinates0.Add(br.ReadVec2()); } } // WE'RE SKIPPING COLOR0 AND COLOR1! (Offset5 and Offset4) // Make sure bin normals has a offset. if (Offsets[3] != 0) { // Go to the bin normals offset. br.Goto(Offsets[3]); // Define a new list to hold the bin's normals. Normals = new List <Vec3>(); // Loop through normals. for (int i = 0; i < GetNormalCount(); i++) { // Read a bin normal and add it to the normals list. Normals.Add(br.ReadVec3()); } } // Make sure bin positions has a offset. if (Offsets[2] != 0) { // Go to the bin positions offset. br.Goto(Offsets[2]); // Define a new list to hold the bin's positions. Positions = new List <Vec3>(); // Loop through positions. for (int i = 0; i < GetPositionCount(); i++) { // Read a bin position and add it to the positions list. Positions.Add(new Vec3(br.ReadF16() / 256.0f, br.ReadF16() / 256.0f, br.ReadF16() / 256.0f)); } } // Make sure bin materials has a offset. if (Offsets[1] != 0) { // Go to the bin materials offset. br.Goto(Offsets[1]); // Define a new list to hold the bin's materials. Materials = new List <Material>(); // Loop through materials. for (int i = 0; i < GetMaterialCount(); i++) { // Read a bin material and add it to the materials list. Materials.Add(new Material(br)); } } // Make sure bin textures has a offset. if (Offsets[0] != 0) { // Go to the bin textures offset. br.Goto(Offsets[0]); // Define a new list to hold the bin's textures. Textures = new List <BTI>(); // Loop through textures. for (int i = 0; i < GetTextureCount(); i++) { // Read a bin textures and add it to the textures list. Textures.Add(new BTI(br, Offsets[0])); } } }
/// <summary> /// Reads MP from a byte array. /// </summary> /// <param name="data">The byte array containing the MP data.</param> public MP(byte[] data) { // Define a binary reader to read with. DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big); // Read Grid Scale. GridScale = br.ReadVec3(); // Read Minimum Bounds. MinimumBounds = br.ReadVec3(); // Read Axis Lengths. AxisLengths = br.ReadVec3(); // Define new array to hold offsets. Offsets = new int[7]; // Loop through our offsets. for (int i = 0; i < 7; i++) { // Read offset and store it to the offsets array. Offsets[i] = br.ReadS32(); } // Go to mp's vertex data offset. br.Goto(Offsets[0]); // Calculate amount of vertices. int verticeCount = (Offsets[1] - Offsets[0]) / 12; // Define new list to hold vertices. Vertices = new List <Vec3>(); // Loop through vertices. for (int i = 0; i < verticeCount; i++) { // Read vertex and add it to the list of vertices. Vertices.Add(br.ReadVec3()); } // Go to mp's normals offset. br.Goto(Offsets[1]); // Calculate amount of normals. int normalCount = (Offsets[2] - Offsets[1]) / 12; // Define new list to hold normals. Normals = new List <Vec3>(); // Loop through normals. for (int i = 0; i < normalCount; i++) { // Read normal and add it to the normal list. Normals.Add(br.ReadVec3()); } // Go to mp's triangle data offset. br.Goto(Offsets[2]); // Calculate amount of triangles. int triangleDataCount = (Offsets[3] - Offsets[2]) / 24; // Define new list to hold triangle data. TriangleData = new List <TriangleData>(); // Loop through triangles. for (int i = 0; i < triangleDataCount; i++) { // Read triangle and add it to the triangle data list. TriangleData.Add(new TriangleData(br)); } // Go to mp's triangle group offset. br.Goto(Offsets[3]); // Define new list to hold triangle groups. TriangleGroups = new List <TriangleGroup>(); // Make sure first ushort is 0xFFFF. if (br.ReadU16() != 0xFFFF) { throw new FormatException("Start of triangle groups section was not 0xFFFF!"); } // We'll read triangle groups as long as we're not entering the next section. while (br.Position() < Offsets[4] - 2) { // Read group and add it to the groups list. TriangleGroups.Add(new TriangleGroup(br)); } // Make sure last ushort is 0xFFFF. if (br.ReadU16() != 0xFFFF) { throw new FormatException("End of triangle groups section was not 0xFFFF!"); } // Go to mp's grid index offset. br.Goto(Offsets[4]); // Calculate amount of grid index entries. (Offset 5 is a duplicate of offset 4) int gridIndexCount = (Offsets[6] - Offsets[4]) / 8; // Define new list to hold grid indices. GridIndices = new List <GridIndex>(); // Loop through grid indices. for (int i = 0; i < gridIndexCount; i++) { GridIndices.Add(new GridIndex(br)); } // Go to mp's unknown offset. br.Goto(Offsets[6]); // Define new list to hold unknown data. Unknowns = new List <Unknown>(); // We'll read unknowns as long as we're not reading padding EOF. while (br.Position() < br.GetStream().Length) { // Check if next byte is 0xFF. (More data) if (br.Read() == 0xFF) { // Jump back a byte, since we checked for data. br.Sail(-1); // Read unknown and add it to the unknowns list. Unknowns.Add(new Unknown(br)); } else { // We've reached padding, stop reading. break; } } }