private void ReadParameters(byte[] file, int address, int count) { for (int i = 0; i < count; i++) { switch ((ParameterType)ByteConverter.ToInt32(file, address)) { case ParameterType.VtxAttrFmt: VtxAttrFmtParameter vtx_param = new VtxAttrFmtParameter(); vtx_param.Read(file, address + 4); Parameters.Add(vtx_param); break; case ParameterType.IndexAttributeFlags: IndexAttributeParameter index_param = new IndexAttributeParameter(); index_param.Read(file, address + 4); Parameters.Add(index_param); break; case ParameterType.Lighting: LightingParameter light_param = new LightingParameter(); light_param.Read(file, address + 4); Parameters.Add(light_param); break; case ParameterType.BlendAlpha: BlendAlphaParameter blend_param = new BlendAlphaParameter(); blend_param.Read(file, address + 4); Parameters.Add(blend_param); break; case ParameterType.AmbientColor: AmbientColorParameter ambient_param = new AmbientColorParameter(); ambient_param.Read(file, address + 4); Parameters.Add(ambient_param); break; case ParameterType.Texture: TextureParameter texture_param = new TextureParameter(); texture_param.Read(file, address + 4); Parameters.Add(texture_param); break; case ParameterType.Unknown_9: Unknown9Parameter unk9_param = new Unknown9Parameter(); unk9_param.Read(file, address + 4); Parameters.Add(unk9_param); break; case ParameterType.TexCoordGen: TexCoordGenParameter mip_param = new TexCoordGenParameter(); mip_param.Read(file, address + 4); Parameters.Add(mip_param); break; } address += 8; } }
/// <summary> /// Create a parameter object from a file and address /// </summary> /// <param name="file">The file contents</param> /// <param name="address">The address at which the parameter is located</param> /// <returns>Any of the parameter types</returns> public static GCParameter Read(byte[] file, int address) { GCParameter result = null; ParameterType paramType = (ParameterType)BitConverter.ToUInt32(file, address); switch (paramType) { case ParameterType.VtxAttrFmt: result = new VtxAttrFmtParameter(GCVertexAttribute.Null); break; case ParameterType.IndexAttributeFlags: result = new IndexAttributeParameter(); break; case ParameterType.Lighting: result = new LightingParameter(); break; case ParameterType.BlendAlpha: result = new BlendAlphaParameter(); break; case ParameterType.AmbientColor: result = new AmbientColorParameter(); break; case ParameterType.Texture: result = new TextureParameter(); break; case ParameterType.Unknown_9: result = new Unknown9Parameter(); break; case ParameterType.TexCoordGen: result = new TexCoordGenParameter(); break; } result.data = ByteConverter.ToUInt32(file, address + 4); return(result); }
public Mesh(byte[] file, int address, uint imageBase, IndexAttributeParameter index = null) { Parameters = new List <Parameter>(); Primitives = new List <Primitive>(); int parameters_offset = (int)(ByteConverter.ToInt32(file, address) - imageBase); int parameters_count = ByteConverter.ToInt32(file, address + 4); int primitives_offset = (int)(ByteConverter.ToInt32(file, address + 8) - imageBase); int primitives_size = ByteConverter.ToInt32(file, address + 12); ReadParameters(file, parameters_offset, parameters_count); IndexAttributeParameter index_param = (IndexAttributeParameter)Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags); if (index_param == null) { index_param = index; } ReadPrimitives(file, primitives_offset, primitives_size, index_param); }
public void Load(byte[] file, int address, uint imageBase, int count, GeometryType geometry_type) { for (int i = 0; i < count; i++) { Mesh new_mesh = new Mesh(file, address, imageBase, cur_attributes); if (new_mesh.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags)) { cur_attributes = (IndexAttributeParameter)new_mesh.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags); } if (geometry_type == GeometryType.Translucent) { TranslucentMeshes.Add(new_mesh); } else { OpaqueMeshes.Add(new_mesh); } address += 16; } }
public void WriteGeometryData(BinaryWriter writer, uint imageBase) { using (MemoryStream opaque = new MemoryStream(), translucent = new MemoryStream()) { BinaryWriter opaque_writer = new BinaryWriter(opaque); BinaryWriter trans_writer = new BinaryWriter(translucent); // First, write the mesh parameters for the two groups. foreach (Mesh m in OpaqueMeshes) { opaque_writer.Write((int)(writer.BaseStream.Length + imageBase)); opaque_writer.Write((int)m.Parameters.Count); opaque_writer.Write((int)0); // Placeholder for index data pointer opaque_writer.Write((int)0); // Placeholder for index data size foreach (Parameter p in m.Parameters) { p.Write(writer); } } foreach (Mesh m in TranslucentMeshes) { trans_writer.Write((int)(writer.BaseStream.Length + imageBase)); trans_writer.Write((int)m.Parameters.Count); trans_writer.Write((int)0); // Placeholder for index data pointer trans_writer.Write((int)0); // Placeholder for index data size foreach (Parameter p in m.Parameters) { p.Write(writer); } } // Reset the geometry header writers opaque_writer.Seek(0, SeekOrigin.Begin); trans_writer.Seek(0, SeekOrigin.Begin); // Second, write the primitive data for each mesh. IndexAttributeParameter cur_index_param = null; // This will hold the index parameters that are currently in use foreach (Mesh m in OpaqueMeshes) { long init_file_pos = writer.BaseStream.Position; opaque_writer.Seek(8, SeekOrigin.Current); opaque_writer.Write((int)(init_file_pos + imageBase)); // Switch the index parameters if this mesh specifies new ones if (m.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags)) { cur_index_param = (IndexAttributeParameter)m.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags); } foreach (Primitive p in m.Primitives) { p.Write(writer, cur_index_param); } PadMesh(writer, writer.BaseStream.Position - init_file_pos); // Write the primitive data size opaque_writer.Write((int)(writer.BaseStream.Position - init_file_pos)); } foreach (Mesh m in TranslucentMeshes) { long init_file_pos = writer.BaseStream.Position; trans_writer.Seek(8, SeekOrigin.Current); trans_writer.Write((int)(init_file_pos + imageBase)); // Switch the index parameters if this mesh specifies new ones if (m.Parameters.Exists(x => x.ParameterType == ParameterType.IndexAttributeFlags)) { cur_index_param = (IndexAttributeParameter)m.Parameters.Find(x => x.ParameterType == ParameterType.IndexAttributeFlags); } foreach (Primitive p in m.Primitives) { p.Write(writer, cur_index_param); } PadMesh(writer, writer.BaseStream.Position - init_file_pos); // Write the primitive data size trans_writer.Write((int)(writer.BaseStream.Position - init_file_pos)); } // Lastly, append the mesh header data and update the file header. if (OpaqueMeshes.Count > 0) { writer.Seek(8, SeekOrigin.Begin); writer.Write((int)(writer.BaseStream.Length + imageBase)); writer.Seek(0, SeekOrigin.End); writer.Write(opaque.ToArray()); } if (TranslucentMeshes.Count > 0) { writer.Seek(12, SeekOrigin.Begin); writer.Write((int)(writer.BaseStream.Length + imageBase)); writer.Seek(0, SeekOrigin.End); writer.Write(translucent.ToArray()); } } }
public void Write(BinaryWriter writer, IndexAttributeParameter attribute_parameters) { writer.Write((byte)PrimitiveType); byte[] big_endian_count = BitConverter.GetBytes((ushort)Vertices.Count); Array.Reverse(big_endian_count); writer.Write(big_endian_count); bool has_color = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasColor); bool has_normal = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasNormal); bool has_uv = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasUV); bool is_position_16bit = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Position16BitIndex); bool is_color_16bit = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Color16BitIndex); bool is_normal_16bit = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.Normal16BitIndex); bool is_uv_16bit = attribute_parameters.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.UV16BitIndex); foreach (Vertex v in Vertices) { // Position should always exist if (is_position_16bit) { byte[] big_endian_pos = BitConverter.GetBytes((ushort)v.PositionIndex); Array.Reverse(big_endian_pos); writer.Write(big_endian_pos); } else { writer.Write((byte)v.PositionIndex); } if (has_normal) { if (is_normal_16bit) { byte[] big_endian_nrm = BitConverter.GetBytes((ushort)v.NormalIndex); Array.Reverse(big_endian_nrm); writer.Write(big_endian_nrm); } else { writer.Write((byte)v.NormalIndex); } } if (has_color) { if (is_color_16bit) { byte[] big_endian_col = BitConverter.GetBytes((ushort)v.Color0Index); Array.Reverse(big_endian_col); writer.Write(big_endian_col); } else { writer.Write((byte)v.Color0Index); } } if (has_uv) { if (is_uv_16bit) { byte[] big_endian_uv = BitConverter.GetBytes((ushort)v.UVIndex); Array.Reverse(big_endian_uv); writer.Write(big_endian_uv); } else { writer.Write((byte)v.UVIndex); } } } }
private void ReadPrimitives(byte[] file, int address, int size, IndexAttributeParameter index_parameter) { int end_pos = address + size; while (address < end_pos) { if (file[address] == 0) { address++; continue; } Primitive prim = new Primitive((GXPrimitiveType)file[address]); short raw_index_count = ByteConverter.ToInt16(file, address + 1); byte[] raw_index_bytes = ByteConverter.GetBytes(raw_index_count); int real_index_count = ByteConverter.ToInt16(new byte[] { raw_index_bytes[1], raw_index_bytes[0] }, 0); address += 3; for (int i = 0; i < real_index_count; i++) { Vertex vert = new Vertex(); if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasPosition)) { bool is_16bit = index_parameter.IndexAttributes.HasFlag( IndexAttributeParameter.IndexAttributeFlags.Position16BitIndex); ushort raw_pos_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address]; if (!is_16bit) { vert.PositionIndex = raw_pos_index; address++; } else { byte[] pos_bytes = BitConverter.GetBytes(raw_pos_index); Array.Reverse(pos_bytes); vert.PositionIndex = BitConverter.ToUInt16(pos_bytes, 0); address += 2; } } if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasNormal)) { bool is_16bit = index_parameter.IndexAttributes.HasFlag( IndexAttributeParameter.IndexAttributeFlags.Normal16BitIndex); ushort raw_nrm_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address]; if (!is_16bit) { vert.NormalIndex = raw_nrm_index; address++; } else { byte[] nrm_bytes = BitConverter.GetBytes(raw_nrm_index); Array.Reverse(nrm_bytes); vert.Color0Index = BitConverter.ToUInt16(nrm_bytes, 0); address += 2; } } if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasColor)) { bool is_16bit = index_parameter.IndexAttributes.HasFlag( IndexAttributeParameter.IndexAttributeFlags.Color16BitIndex); ushort raw_col_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address]; if (!is_16bit) { vert.Color0Index = raw_col_index; address++; } else { byte[] col_bytes = BitConverter.GetBytes(raw_col_index); Array.Reverse(col_bytes); vert.Color0Index = BitConverter.ToUInt16(col_bytes, 0); address += 2; } } if (index_parameter.IndexAttributes.HasFlag(IndexAttributeParameter.IndexAttributeFlags.HasUV)) { bool is_16bit = index_parameter.IndexAttributes.HasFlag( IndexAttributeParameter.IndexAttributeFlags.UV16BitIndex); ushort raw_tex_index = is_16bit ? ByteConverter.ToUInt16(file, address) : file[address]; if (!is_16bit) { vert.UVIndex = raw_tex_index; address++; } else { byte[] tex_bytes = BitConverter.GetBytes(raw_tex_index); Array.Reverse(tex_bytes); vert.UVIndex = BitConverter.ToUInt16(tex_bytes, 0); address += 2; } } prim.Vertices.Add(vert); } Primitives.Add(prim); } }