void ReadMaterial() { if (clyt.Materials.Count > 0) { throw new FormatException("Expecting just one mat1 section"); } long baseOffset = reader.Stream.Position - 8; int numMaterials = reader.ReadInt32(); while (numMaterials > 0) { // Read from table and jump to material long offset = baseOffset + reader.ReadUInt32(); reader.Stream.PushToPosition(offset); var material = new Material(); material.Name = reader.ReadString(0x14).Replace("\0", string.Empty); for (int i = 0; i < material.TevConstantColors.Length; i++) { // TODO: Convert to RGBA material.TevConstantColors[i] = reader.ReadUInt32(); } uint flags = reader.ReadUInt32(); uint numTexMap = flags & 0x3; uint numTexMatrix = (flags >> 2) & 0x3; uint numTexCoordGen = (flags >> 4) & 0x3; uint numTevStage = (flags >> 6) & 0x7; bool hasAlphaCompare = ((flags >> 9) & 0x01) == 1; bool hasBlendMode = ((flags >> 10) & 0x01) == 1; material.UseTextureOnly = ((flags >> 11) & 0x01) == 1; bool separateBlendMode = ((flags >> 12) & 0x01) == 1; bool hasIndirectParam = ((flags >> 13) & 0x01) == 1; uint numProjTexGenParam = (flags >> 14) & 0x03; bool hasFontShadowParam = ((flags >> 16) & 0x01) == 1; for (int i = 0; i < numTexMap; i++) { var entry = new TextureMapEntry(); entry.Index = reader.ReadUInt16(); byte flag1 = reader.ReadByte(); byte flag2 = reader.ReadByte(); entry.WrapS = (WrapMode)(flag1 & 0x3); entry.WrapT = (WrapMode)(flag2 & 0x3); entry.MinFilter = (TextureFilter)((flag1 >> 2) & 0x3); entry.MagFilter = (TextureFilter)((flag2 >> 2) & 0x3); material.TexMapEntries.Add(entry); } for (int i = 0; i < numTexMatrix; i++) { var entry = new TextureMatrixEntry(); entry.Translation = new Vector2(reader.ReadSingle(), reader.ReadSingle()); entry.Rotation = reader.ReadSingle(); entry.Scale = new Vector2(reader.ReadSingle(), reader.ReadSingle()); material.TexMatrixEntries.Add(entry); } for (int i = 0; i < numTexCoordGen; i++) { material.TextureCoordGen.Add(reader.ReadSingle()); } for (int i = 0; i < numTevStage; i++) { var stage = new TevStage(); stage.Param1 = reader.ReadUInt32(); stage.Param2 = reader.ReadUInt32(); stage.Param3 = reader.ReadUInt32(); material.TevStages.Add(stage); } if (hasAlphaCompare) { material.AlphaCompare = new AlphaCompare { Function = reader.ReadUInt32(), Reference = reader.ReadSingle(), }; } if (hasBlendMode) { material.ColorBlendMode = new BlendMode { BlendOperator = reader.ReadByte(), SourceFactor = reader.ReadByte(), DestinationFactor = reader.ReadByte(), LogicOperator = reader.ReadByte(), }; } if (separateBlendMode) { material.AlphaBlendMode = new BlendMode { BlendOperator = reader.ReadByte(), SourceFactor = reader.ReadByte(), DestinationFactor = reader.ReadByte(), LogicOperator = reader.ReadByte(), }; } if (hasIndirectParam || numProjTexGenParam > 0 || hasFontShadowParam) { Console.WriteLine($"WARN: Material ({material.Name}) with unknown sections."); } clyt.Materials.Add(material); reader.Stream.PopPosition(); numMaterials--; } }
void ReadMaterial() { if (clyt.Materials.Count > 0) { throw new FormatException("Expecting just one mat1 section"); } long baseOffset = reader.Stream.Position - 8; int numMaterials = reader.ReadInt32(); while (numMaterials > 0) { // Read from table and jump to material long offset = baseOffset + reader.ReadUInt32(); reader.Stream.PushToPosition(offset); var material = new Material(); material.Name = reader.ReadString(0x14).Replace("\0", string.Empty); for (int i = 0; i < material.TevConstantColors.Length; i++) { // TODO: Convert to RGBA material.TevConstantColors[i] = reader.ReadUInt32(); } uint flags = reader.ReadUInt32(); uint numTexMap = flags & 0x3; uint numTexMatrix = (flags >> 2) & 0x3; uint numTexCoordGen = (flags >> 4) & 0x3; uint numTevStage = (flags >> 6) & 0x7; uint hasAlphaCompare = (flags >> 9) & 0x01; uint hasBlendMode = (flags >> 10) & 0x01; material.UseTextureOnly = ((flags >> 11) & 0x01) == 1; uint separateBlendMode = (flags >> 12) & 0x01; uint hasIndirectParam = (flags >> 13) & 0x01; uint numProjTexGenParam = (flags >> 14) & 0x03; uint hasFontShadowParam = (flags >> 16) & 0x01; uint texMapOffset = 0x34; uint texMatrixOffset = texMapOffset + (numTexMap * 4); uint texCoordGenOffset = texMatrixOffset + (numTexMatrix * 0x14); uint tevStageOffset = texCoordGenOffset + (numTexCoordGen * 4); uint alphaCompareOffset = tevStageOffset + (numTevStage * 0xC); uint blendModeOffset = alphaCompareOffset + 0x8; reader.Stream.Seek(offset + texMapOffset); for (int i = 0; i < numTexMap; i++) { var entry = new TextureMapEntry(); entry.Index = reader.ReadUInt16(); byte flag1 = reader.ReadByte(); byte flag2 = reader.ReadByte(); entry.WrapS = (WrapMode)(flag1 & 0x3); entry.WrapT = (WrapMode)(flag2 & 0x3); entry.MinFilter = (TextureFilter)((flag1 >> 2) & 0x3); entry.MagFilter = (TextureFilter)((flag2 >> 2) & 0x3); material.TexMapEntries.Add(entry); } reader.Stream.Seek(offset + texMatrixOffset); for (int i = 0; i < numTexMatrix; i++) { var entry = new TextureMatrixEntry(); entry.Translation = new Vector2(reader.ReadSingle(), reader.ReadSingle()); entry.Rotation = reader.ReadSingle(); entry.Scale = new Vector2(reader.ReadSingle(), reader.ReadSingle()); material.TexMatrixEntries.Add(entry); } reader.Stream.Seek(offset + texCoordGenOffset); for (int i = 0; i < numTexCoordGen; i++) { material.TextureCoordGen.Add(reader.ReadSingle()); } // TODO: Find a bclyt with the rest of sections clyt.Materials.Add(material); reader.Stream.PopPosition(); numMaterials--; } }