using System; namespace NW4RTools { public struct GXIndexedVertex { public int Position; public int Normal; public int[] Colors; public int[] TexCoords; public byte PosMtxIndex; public byte[] TexCoordMtxIndex; public void LoadFrom(InputStream ins, VertexSettings vs) { if (vs.PNMatrixIndexExists) PosMtxIndex = ins.ReadByte(); for (int i = 0; i < 8; i++) { if (vs.TexCoordMatrixIndexExists[i]) { if (TexCoordMtxIndex == null) TexCoordMtxIndex = new byte[8]; TexCoordMtxIndex[i] = ins.ReadByte(); } } switch (vs.PositionDesc) { case VertexSettings.DescType.Direct: throw new NotImplementedException(); case VertexSettings.DescType.None: throw new NotImplementedException(); case VertexSettings.DescType.Index8: Position = ins.ReadByte(); if (Position == 0xFF) Position = -1; break; case VertexSettings.DescType.Index16: Position = ins.ReadUInt16(); if (Position == 0xFFFF) Position = -1; break; } // not sure how to detect NBT3 yet -- or if it's even relevant? switch (vs.NormalDesc) { case VertexSettings.DescType.Direct: throw new NotImplementedException(); case VertexSettings.DescType.None: Normal = -1; break; case VertexSettings.DescType.Index8: Normal = ins.ReadByte(); if (Normal == 0xFF) Normal = -1; break; case VertexSettings.DescType.Index16: Normal = ins.ReadUInt16(); if (Normal == 0xFFFF) Normal = -1; break; } Colors = new int[2]; for (int i = 0; i < 2; i++) { switch (vs.ColorDesc[i]) { case VertexSettings.DescType.Direct: throw new NotImplementedException(); case VertexSettings.DescType.None: Colors[i] = -1; break; case VertexSettings.DescType.Index8: Colors[i] = ins.ReadByte(); if (Colors[i] == 0xFF) Colors[i] = -1; break; case VertexSettings.DescType.Index16: Colors[i] = ins.ReadUInt16(); if (Colors[i] == 0xFFFF) Colors[i] = -1; break; } } TexCoords = new int[8]; for (int i = 0; i < 8; i++) { switch (vs.TexCoordDesc[i]) { case VertexSettings.DescType.Direct: throw new NotImplementedException(); case VertexSettings.DescType.None: TexCoords[i] = -1; break; case VertexSettings.DescType.Index8: TexCoords[i] = ins.ReadByte(); if (TexCoords[i] == 0xFF) TexCoords[i] = -1; break; case VertexSettings.DescType.Index16: TexCoords[i] = ins.ReadUInt16(); if (TexCoords[i] == 0xFFFF) TexCoords[i] = -1; break; } } } } public class VertexSettings { public enum DescType { None, Direct, Index8, Index16 } public enum CompCount { Position2 = 0, Position3 = 1, Normal3 = 0, NBT = 1, NBT3 = 2, Color3 = 0, Color4 = 1, TexCoord1 = 0, TexCoord2 = 1 } public enum CompType { UInt8 = 0, Int8 = 1, UInt16 = 2, Int16 = 3, Float32 = 4 } public enum CompClrType { RGB565 = 0, RGB8 = 1, RGBX8 = 2, RGBA4 = 3, RGBA6 = 4, RGBA8 = 5 } public bool PNMatrixIndexExists; public bool[] TexCoordMatrixIndexExists; public DescType PositionDesc, NormalDesc; public DescType[] ColorDesc, TexCoordDesc; public CompCount PositionCount, NormalCount; public CompCount[] ColorCount, TexCoordCount; public CompType PositionFormat, NormalFormat; public CompClrType[] ColorFormat; public CompType[] TexCoordFormat; public byte PositionFrac; public byte[] TexCoordFrac; public VertexSettings() { TexCoordMatrixIndexExists = new bool[8]; ColorDesc = new DescType[2]; TexCoordDesc = new DescType[8]; ColorCount = new CompCount[2]; TexCoordCount = new CompCount[8]; ColorFormat = new CompClrType[2]; TexCoordFormat = new CompType[8]; TexCoordFrac = new byte[8]; } public void GetDesc(out UInt32 val1, out UInt32 val2) { val1 = 0; val1 |= (uint)(PNMatrixIndexExists ? 1 : 0); for (int i = 0; i < 8; i++) val1 |= (TexCoordMatrixIndexExists[i] ? (uint)(2 << i) : 0); val1 |= ((uint)PositionDesc) << 9; val1 |= ((uint)NormalDesc) << 11; val1 |= ((uint)ColorDesc[0]) << 13; val1 |= ((uint)ColorDesc[1]) << 15; val2 = 0; for (int i = 0; i < 8; i++) val2 |= ((uint)TexCoordDesc[i]) << (i * 2); } public void SetDesc(UInt32 val1, UInt32 val2) { PNMatrixIndexExists = ((val1 & 1) != 0); for (int i = 0; i < 8; i++) TexCoordMatrixIndexExists[i] = ((val1 & (2 << i)) != 0); PositionDesc = (DescType)((val1 & 0x600) >> 9); NormalDesc = (DescType)((val1 & 0x1800) >> 11); ColorDesc[0] = (DescType)((val1 & 0x6000) >> 13); ColorDesc[1] = (DescType)((val1 & 0x18000) >> 15); for (int i = 0; i < 8; i++) TexCoordDesc[i] = (DescType)((val2 & (3 << (i * 2))) >> (i * 2)); } public void GetAttrFmt(out UInt32 val1, out UInt32 val2, out UInt32 val3) { val1 = 0; val2 = 0; val3 = 0; val1 |= (uint)PositionCount; val1 |= ((uint)PositionFormat) << 1; val1 |= ((uint)PositionFrac) << 4; if (PositionFrac > 0) val1 |= 0x40000000; val1 |= ((uint)NormalFormat) << 10; if (NormalCount == VertexSettings.CompCount.NBT || NormalCount == VertexSettings.CompCount.NBT3) val1 |= 0x200; if (NormalCount == VertexSettings.CompCount.NBT3) val1 |= 0x80000000; val1 |= ((uint)ColorCount[0]) << 13; val1 |= ((uint)ColorFormat[0]) << 14; val1 |= ((uint)ColorCount[1]) << 17; val1 |= ((uint)ColorFormat[1]) << 18; for (int i = 0; i < 8; i++) { if (TexCoordFrac[i] > 0) val1 |= 0x40000000; } val1 |= ((uint)TexCoordCount[0]) << 21; val1 |= ((uint)TexCoordFormat[0]) << 22; val1 |= ((uint)TexCoordFrac[0]) << 25; val2 |= ((uint)TexCoordCount[1]); val2 |= ((uint)TexCoordFormat[1]) << 1; val2 |= ((uint)TexCoordFrac[1]) << 4; val2 |= ((uint)TexCoordCount[2]) << 9; val2 |= ((uint)TexCoordFormat[2]) << 10; val2 |= ((uint)TexCoordFrac[2]) << 13; val2 |= ((uint)TexCoordCount[3]) << 18; val2 |= ((uint)TexCoordFormat[3]) << 19; val2 |= ((uint)TexCoordFrac[3]) << 22; val2 |= ((uint)TexCoordCount[4]) << 27; val2 |= ((uint)TexCoordFormat[4]) << 28; val3 |= ((uint)TexCoordFrac[4]); val3 |= ((uint)TexCoordCount[5]) << 5; val3 |= ((uint)TexCoordFormat[5]) << 6; val3 |= ((uint)TexCoordFrac[5]) << 9; val3 |= ((uint)TexCoordCount[6]) << 14; val3 |= ((uint)TexCoordFormat[6]) << 15; val3 |= ((uint)TexCoordFrac[6]) << 18; val3 |= ((uint)TexCoordCount[7]) << 23; val3 |= ((uint)TexCoordFormat[7]) << 24; val3 |= ((uint)TexCoordFrac[7]) << 27; } public void SetAttrFmt(UInt32 val1, UInt32 val2, UInt32 val3) { PositionCount = (CompCount)(val1 & 1); PositionFormat = (CompType)((val1 & 0xE) >> 1); PositionFrac = (byte)((val1 & 0x1F0) >> 4); // note: this field is special bool IsNormalSet = ((val1 & 0x200) != 0); bool UseNormalIndex3 = ((val1 & 0x80000000) != 0); NormalCount = IsNormalSet ? (UseNormalIndex3 ? CompCount.NBT3 : CompCount.NBT) : CompCount.Normal3; NormalFormat = (CompType)((val1 & 0x1C00) >> 10); ColorCount[0] = (CompCount)((val1 & 0x2000) >> 13); ColorFormat[0] = (CompClrType)((val1 & 0x1C000) >> 14); ColorCount[1] = (CompCount)((val1 & 0x20000) >> 17); ColorFormat[1] = (CompClrType)((val1 & 0x1C0000) >> 18); TexCoordCount[0] = (CompCount)((val1 & 0x200000) >> 21); TexCoordFormat[0] = (CompType)((val1 & 0x1C00000) >> 22); TexCoordFrac[0] = (byte)((val1 & 0x3E000000) >> 25); // set in various cases, see libogc gx.c for info bool ByteDequant = ((val1 & 0x40000000) != 0); TexCoordCount[1] = (CompCount)(val2 & 0x1); TexCoordFormat[1] = (CompType)((val2 & 0xE) >> 1); TexCoordFrac[1] = (byte)((val2 & 0x1F0) >> 4); TexCoordCount[2] = (CompCount)((val2 & 0x200) >> 9); TexCoordFormat[2] = (CompType)((val2 & 0x1C00) >> 10); TexCoordFrac[2] = (byte)((val2 & 0x3E000) >> 13); TexCoordCount[3] = (CompCount)((val2 & 0x40000) >> 18); TexCoordFormat[3] = (CompType)((val2 & 0x380000) >> 19); TexCoordFrac[3] = (byte)((val2 & 0x3E000000) >> 22); TexCoordCount[4] = (CompCount)((val2 & 0x8000000) >> 27); TexCoordFormat[4] = (CompType)((val2 & 0x70000000) >> 28); TexCoordFrac[4] = (byte)(val3 & 0x1F); TexCoordCount[5] = (CompCount)((val3 & 0x20) >> 5); TexCoordFormat[5] = (CompType)((val3 & 0x1C0) >> 6); TexCoordFrac[5] = (byte)((val3 & 0x3E00) >> 9); TexCoordCount[6] = (CompCount)((val3 & 0x4000) >> 14); TexCoordFormat[6] = (CompType)((val3 & 0x38000) >> 15); TexCoordFrac[6] = (byte)((val3 & 0x7C0000) >> 18); TexCoordCount[7] = (CompCount)((val3 & 0x800000) >> 23); TexCoordFormat[7] = (CompType)((val3 & 0x7000000) >> 24); TexCoordFrac[7] = (byte)((val3 & 0xF8000000) >> 27); } } }