/// <summary> /// Creates a new empty vertex attribute using the default struct setups /// </summary> /// <param name="attributeType">The attribute type of the vertex attribute</param> public GCVertexSet(GCVertexAttribute attributeType) { attribute = attributeType; switch (attribute) { case GCVertexAttribute.Position: dataType = GCDataType.Float32; structType = GCStructType.Position_XYZ; break; case GCVertexAttribute.Normal: dataType = GCDataType.Float32; structType = GCStructType.Normal_XYZ; break; case GCVertexAttribute.Color0: dataType = GCDataType.RGBA8; structType = GCStructType.Color_RGBA; break; case GCVertexAttribute.Tex0: dataType = GCDataType.Signed16; structType = GCStructType.TexCoord_ST; break; default: throw new ArgumentException($"Datatype { attribute } is not a valid vertex type for SA2"); } data = new List <IOVtx>(); }
/// <summary> /// Create a custom empty vertex attribute /// </summary> /// <param name="attribute"></param> /// <param name="dataType"></param> /// <param name="structType"></param> /// <param name="fractionalBitCount"></param> public GCVertexSet(GCVertexAttribute attribute, GCDataType dataType, GCStructType structType) { this.attribute = attribute; this.dataType = dataType; this.structType = structType; data = new List <IOVtx>(); }
/// <summary> /// Read an entire vertex data set /// </summary> /// <param name="file">The files contents</param> /// <param name="address">The starting address of the file</param> /// <param name="imageBase">The image base of the addresses</param> public GCVertexSet(byte[] file, uint address, uint imageBase) { attribute = (GCVertexAttribute)file[address]; if (attribute == GCVertexAttribute.Null) { return; } uint structure = ByteConverter.ToUInt32(file, (int)address + 4); structType = (GCStructType)(structure & 0x0F); dataType = (GCDataType)((structure >> 4) & 0x0F); if (file[address + 1] != StructSize) { throw new Exception($"Read structure size doesnt match calculated structure size: {file[address + 1]} != {StructSize}"); } // reading the data int count = ByteConverter.ToUInt16(file, (int)address + 2); int tmpaddr = (int)(ByteConverter.ToUInt32(file, (int)address + 8) - imageBase); data = new List <IOVtx>(); switch (attribute) { case GCVertexAttribute.Position: case GCVertexAttribute.Normal: for (int i = 0; i < count; i++) { data.Add(new Vector3(file, tmpaddr)); tmpaddr += 12; } break; case GCVertexAttribute.Color0: for (int i = 0; i < count; i++) { data.Add(new Color(file, tmpaddr, dataType, out tmpaddr)); } break; case GCVertexAttribute.Tex0: for (int i = 0; i < count; i++) { data.Add(new UV(file, tmpaddr)); tmpaddr += 4; } break; default: throw new ArgumentException($"Attribute type not valid sa2 type: {attribute}"); } }
public Color(byte[] file, int address, GCDataType dataType, out int endaddr) { switch (dataType) { case GCDataType.RGB565: short colorShort = ByteConverter.ToInt16(file, address); red = (byte)((colorShort & 0xF800) >> 8); green = (byte)((colorShort & 0x07E0) >> 3); blue = (byte)((colorShort & 0x001F) << 3); endaddr = address + 2; return; case GCDataType.RGBA4: ushort colorShortA = ByteConverter.ToUInt16(file, address); // multiplying all by 0x11, so that e.g. 0xF becomes 0xFF red = (byte)(((colorShortA & 0xF000) >> 12) * 0x11); green = (byte)(((colorShortA & 0x0F00) >> 8) * 0x11); blue = (byte)(((colorShortA & 0x00F0) >> 4) * 0x11); alpha = (byte)((colorShortA & 0x000F) * 0x11); endaddr = address + 2; return; case GCDataType.RGBA6: uint colorInt = ByteConverter.ToUInt32(file, address); // shifting all 2 less to the left, so that they are more accurate to the color that they should represent red = (byte)((colorInt & 0xFC0000) >> 16); green = (byte)((colorInt & 0x03F000) >> 10); blue = (byte)((colorInt & 0x000FC0) >> 4); alpha = (byte)((colorInt & 0x00003F) << 2); endaddr = address + 3; return; case GCDataType.RGB8: case GCDataType.RGBX8: case GCDataType.RGBA8: RGBA = ByteConverter.ToUInt32(file, address); if (dataType != GCDataType.RGBA8) { alpha = 255; } endaddr = address + 4; return; default: throw new ArgumentException($"{dataType} is not a valid color type"); } }
/// <summary> /// Write the color data to a stream /// </summary> /// <param name="writer"></param> /// <param name="attrib"></param> public void Write(BinaryWriter writer, GCDataType dataType, GCStructType structType) { switch (dataType) { case GCDataType.RGB8: writer.Write(red); writer.Write(green); writer.Write(blue); writer.Write((byte)255); break; case GCDataType.RGBA8: writer.Write(red); writer.Write(green); writer.Write(blue); writer.Write(alpha); break; default: throw new ArgumentException($"{dataType} is not a valid output color type"); } }
public void Write(BinaryWriter writer, GCDataType dataType, GCStructType structType) { writer.Write(x); writer.Write(y); }