/// <summary> /// Read a primitive object from a file /// </summary> /// <param name="file">The files contents as a byte array</param> /// <param name="address">The starting address of the primitive</param> /// <param name="indexFlags">How the indices of the loops are structured</param> public GCPrimitive(byte[] file, int address, GCIndexAttributeFlags indexFlags, out int end) { primitiveType = (GCPrimitiveType)file[address]; bool wasBigEndian = ByteConverter.BigEndian; ByteConverter.BigEndian = true; ushort vtxCount = ByteConverter.ToUInt16(file, address + 1); // checking the flags bool hasFlag(GCIndexAttributeFlags flag) { return(indexFlags.HasFlag(flag)); } // position always exists bool has_color = hasFlag(GCIndexAttributeFlags.HasColor); bool has_normal = hasFlag(GCIndexAttributeFlags.HasNormal); bool has_uv = hasFlag(GCIndexAttributeFlags.HasUV); //whether any of the indices use 16 bits instead of 8 bool pos16bit = hasFlag(GCIndexAttributeFlags.Position16BitIndex); bool col16bit = hasFlag(GCIndexAttributeFlags.Color16BitIndex); bool nrm16bit = hasFlag(GCIndexAttributeFlags.Normal16BitIndex); bool uv16bit = hasFlag(GCIndexAttributeFlags.UV16BitIndex); int tmpaddr = address + 3; loops = new List <Loop>(); for (ushort i = 0; i < vtxCount; i++) { Loop l = new Loop(); // reading position, which should always exist if (pos16bit) { l.PositionIndex = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.PositionIndex = file[tmpaddr]; tmpaddr++; } // reading normals if (has_normal) { if (nrm16bit) { l.NormalIndex = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.NormalIndex = file[tmpaddr]; tmpaddr++; } } // reading colors if (has_color) { if (col16bit) { l.Color0Index = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.Color0Index = file[tmpaddr]; tmpaddr++; } } // reading uvs if (has_uv) { if (uv16bit) { l.UV0Index = ByteConverter.ToUInt16(file, tmpaddr); tmpaddr += 2; } else { l.UV0Index = file[tmpaddr]; tmpaddr++; } } loops.Add(l); } end = tmpaddr; ByteConverter.BigEndian = wasBigEndian; }
/// <summary> /// Write the contents /// </summary> /// <param name="writer">The output stream</param> /// <param name="indexFlags">How the indices of the loops are structured</param> public void Write(BinaryWriter writer, GCIndexAttributeFlags indexFlags) { writer.Write((byte)primitiveType); byte[] bytes = BitConverter.GetBytes((ushort)loops.Count); // writing count as big endian writer.Write(bytes[1]); writer.Write(bytes[0]); // checking the flags bool hasFlag(GCIndexAttributeFlags flag) { return(indexFlags.HasFlag(flag)); } // position always exists bool has_color = hasFlag(GCIndexAttributeFlags.HasColor); bool has_normal = hasFlag(GCIndexAttributeFlags.HasNormal); bool has_uv = hasFlag(GCIndexAttributeFlags.HasUV); bool is_position_16bit = hasFlag(GCIndexAttributeFlags.Position16BitIndex); bool is_color_16bit = hasFlag(GCIndexAttributeFlags.Color16BitIndex); bool is_normal_16bit = hasFlag(GCIndexAttributeFlags.Normal16BitIndex); bool is_uv_16bit = hasFlag(GCIndexAttributeFlags.UV16BitIndex); foreach (Loop v in loops) { // Position should always exist if (is_position_16bit) { bytes = BitConverter.GetBytes(v.PositionIndex); // writing big endian writer.Write(bytes[1]); writer.Write(bytes[0]); } else { writer.Write((byte)v.PositionIndex); } if (has_normal) { if (is_normal_16bit) { bytes = BitConverter.GetBytes(v.NormalIndex); // writing big endian writer.Write(bytes[1]); writer.Write(bytes[0]); } else { writer.Write((byte)v.NormalIndex); } } if (has_color) { if (is_color_16bit) { bytes = BitConverter.GetBytes(v.Color0Index); // writing big endian writer.Write(bytes[1]); writer.Write(bytes[0]); } else { writer.Write((byte)v.Color0Index); } } if (has_uv) { if (is_uv_16bit) { bytes = BitConverter.GetBytes(v.UV0Index); // writing big endian writer.Write(bytes[1]); writer.Write(bytes[0]); } else { writer.Write((byte)v.UV0Index); } } } }