diff --git a/FinModelUtility/Fin/Fin.Ui/src/rendering/gl/material/BGlMaterialShader.cs b/FinModelUtility/Fin/Fin.Ui/src/rendering/gl/material/BGlMaterialShader.cs index 4742c8f57..3f702a5c1 100644 --- a/FinModelUtility/Fin/Fin.Ui/src/rendering/gl/material/BGlMaterialShader.cs +++ b/FinModelUtility/Fin/Fin.Ui/src/rendering/gl/material/BGlMaterialShader.cs @@ -1,7 +1,9 @@ using System.Numerics; using fin.math; +using fin.math.matrix.four; using fin.math.matrix.three; +using fin.math.rotations; using fin.model; using fin.shaders.glsl; @@ -12,13 +14,16 @@ public class CachedTextureUniformData { public required int TextureIndex { get; init; } public required ITexture? FinTexture { get; init; } public required GlTexture GlTexture { get; init; } - public required IReadOnlyFinMatrix3x2 Transform { get; init; } + + public required IReadOnlyFinMatrix3x2? Transform2d { get; init; } + public required IReadOnlyFinMatrix4x4? Transform3d { get; init; } public required bool HasFancyData { get; init; } public required int SamplerLocation { get; init; } public required int ClampMinLocation { get; init; } public required int ClampMaxLocation { get; init; } - public required int TransformLocation { get; init; } + public required int Transform2dLocation { get; init; } + public required int Transform3dLocation { get; init; } } public abstract class BGlMaterialShader : IGlMaterialShader @@ -221,7 +226,8 @@ protected void SetUpTexture( int samplerLocation; int clampMinLocation = -1; int clampMaxLocation = -1; - int transformLocation = -1; + int transform2dLocation = -1; + int transform3dLocation = -1; var hasFancyData = GlslUtil.RequiresFancyTextureData(finTexture); if (!hasFancyData) { @@ -233,26 +239,36 @@ protected void SetUpTexture( this.impl_.GetUniformLocation($"{textureName}.clampMin"); clampMaxLocation = this.impl_.GetUniformLocation($"{textureName}.clampMax"); - transformLocation = - this.impl_.GetUniformLocation($"{textureName}.transform"); + transform2dLocation = + this.impl_.GetUniformLocation($"{textureName}.transform2d"); + transform3dLocation = + this.impl_.GetUniformLocation($"{textureName}.transform3d"); } + var isTransform3d = finTexture?.IsTransform3d ?? false; + var cachedTextureUniformData = new CachedTextureUniformData { TextureIndex = textureIndex, FinTexture = finTexture, GlTexture = glTexture, - Transform = CalculateTextureTransform_(finTexture), + Transform2d = isTransform3d + ? null + : CalculateTextureTransform2d_(finTexture), + Transform3d = isTransform3d + ? CalculateTextureTransform3d_(finTexture) + : null, HasFancyData = hasFancyData, SamplerLocation = samplerLocation, ClampMinLocation = clampMinLocation, ClampMaxLocation = clampMaxLocation, - TransformLocation = transformLocation, + Transform2dLocation = transform2dLocation, + Transform3dLocation = transform3dLocation, }; this.cachedTextureUniformDatas_.AddLast(cachedTextureUniformData); } - private static IReadOnlyFinMatrix3x2 CalculateTextureTransform_( + private static IReadOnlyFinMatrix3x2 CalculateTextureTransform2d_( ITexture? texture) { if (texture == null) { return FinMatrix3x2.IDENTITY; @@ -279,11 +295,48 @@ private static IReadOnlyFinMatrix3x2 CalculateTextureTransform_( } return FinMatrix3x2Util.FromTrss(offset, - textureRotationRadians, + textureRotationRadians?.Z, scale, null); } + private static IReadOnlyFinMatrix4x4 CalculateTextureTransform3d_( + ITexture? texture) { + if (texture == null) { + return FinMatrix4x4.IDENTITY; + } + + var textureOffset = texture.Offset; + var textureScale = texture.Scale; + var textureRotationRadians = texture.RotationRadians; + + if (textureOffset == null && + textureScale == null && + textureRotationRadians == null) { + return FinMatrix4x4.IDENTITY; + } + + Position? offset = null; + if (textureOffset != null) { + offset = + new Position(textureOffset.X, textureOffset.Y, textureOffset.Z); + } + + Quaternion? rotation = null; + if (textureRotationRadians != null) { + rotation = QuaternionUtil.CreateZyx(textureRotationRadians.X, + textureRotationRadians.Y, + textureRotationRadians.Z); + } + + Scale? scale = null; + if (textureScale != null) { + scale = new(textureScale.X, textureScale.Y, textureScale.Z); + } + + return FinMatrix4x4Util.FromTrs(offset, rotation, scale); + } + private unsafe void BindTextureAndSetUpUniforms_( CachedTextureUniformData uniformData) { uniformData.GlTexture.Bind(uniformData.TextureIndex); @@ -319,9 +372,14 @@ private unsafe void BindTextureAndSetUpUniforms_( GL.Uniform2(uniformData.ClampMinLocation, clampMin); GL.Uniform2(uniformData.ClampMaxLocation, clampMax); - var mat = uniformData.Transform.Impl; - var ptr = (float*) &mat; - GL.UniformMatrix2x3(uniformData.TransformLocation, 1, true, ptr); + if (!(uniformData.FinTexture?.IsTransform3d ?? false)) { + var mat2d = uniformData.Transform2d!.Impl; + var ptr = (float*) &mat2d; + GL.UniformMatrix2x3(uniformData.Transform2dLocation, 1, true, ptr); + } else { + var mat3d = uniformData.Transform3d!.Impl; + GlTransform.UniformMatrix4(uniformData.Transform3dLocation, mat3d); + } } } } diff --git a/FinModelUtility/Fin/Fin/src/math/rotations/QuaternionUtil.cs b/FinModelUtility/Fin/Fin/src/math/rotations/QuaternionUtil.cs index 08c48d2e9..ccf116c03 100644 --- a/FinModelUtility/Fin/Fin/src/math/rotations/QuaternionUtil.cs +++ b/FinModelUtility/Fin/Fin/src/math/rotations/QuaternionUtil.cs @@ -4,14 +4,27 @@ using fin.model; +using Quaternion = System.Numerics.Quaternion; + namespace fin.math.rotations { public static class QuaternionUtil { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion Create(IRotation rotation) => QuaternionUtil.CreateZyx(rotation.XRadians, - rotation.YRadians, - rotation.ZRadians); + rotation.YRadians, + rotation.ZRadians); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Quaternion CreateXyz( + float xRadians, + float yRadians, + float zRadians) { + return Quaternion.CreateFromAxisAngle(Vector3.UnitX, xRadians) * + Quaternion.CreateFromAxisAngle(Vector3.UnitY, yRadians) * + Quaternion.CreateFromAxisAngle(Vector3.UnitZ, zRadians); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Quaternion CreateZyx( float xRadians, float yRadians, diff --git a/FinModelUtility/Fin/Fin/src/model/MaterialInterfaces.cs b/FinModelUtility/Fin/Fin/src/model/MaterialInterfaces.cs index d4b99670e..24d845141 100644 --- a/FinModelUtility/Fin/Fin/src/model/MaterialInterfaces.cs +++ b/FinModelUtility/Fin/Fin/src/model/MaterialInterfaces.cs @@ -351,16 +351,19 @@ public interface ITexture { IReadOnlyVector2? ClampS { get; set; } IReadOnlyVector2? ClampT { get; set; } - IReadOnlyVector2? Offset { get; } - ITexture SetOffset(float x, float y); + bool IsTransform3d { get; } - IReadOnlyVector2? Scale { get; } - ITexture SetScale(float x, float y); + IReadOnlyVector3? Offset { get; } + ITexture SetOffset2d(float x, float y); + ITexture SetOffset3d(float x, float y, float z); - float? RotationRadians { get; } - float? RotationDegrees { get; } - ITexture SetRotationRadians(float rotationRadians); - ITexture SetRotationDegrees(float rotationDegrees); + IReadOnlyVector3? Scale { get; } + ITexture SetScale2d(float x, float y); + ITexture SetScale3d(float x, float y, float z); + + IReadOnlyVector3? RotationRadians { get; } + ITexture SetRotationRadians2d(float rotationRadians); + ITexture SetRotationRadians3d(float xRadians, float yRadians, float zRadians); // TODO: Support fixed # of repeats // TODO: Support animated textures diff --git a/FinModelUtility/Fin/Fin/src/model/impl/material/TextureImpl.cs b/FinModelUtility/Fin/Fin/src/model/impl/material/TextureImpl.cs index 7f4fcb140..5479b064c 100644 --- a/FinModelUtility/Fin/Fin/src/model/impl/material/TextureImpl.cs +++ b/FinModelUtility/Fin/Fin/src/model/impl/material/TextureImpl.cs @@ -71,32 +71,53 @@ public ImageTransparencyType TransparencyType public IReadOnlyVector2? ClampS { get; set; } public IReadOnlyVector2? ClampT { get; set; } - public IReadOnlyVector2? Offset { get; private set; } - public ITexture SetOffset(float x, float y) { - this.Offset = new Vector2f { X = x, Y = y }; + public bool IsTransform3d { get; private set; } + + + public IReadOnlyVector3? Offset { get; private set; } + + public ITexture SetOffset2d(float x, float y) { + this.Offset = new Vector3f { X = x, Y = y }; + return this; + } + + public ITexture SetOffset3d(float x, float y, float z) { + this.Offset = new Vector3f { X = x, Y = y, Z = z }; + this.IsTransform3d = true; return this; } - public IReadOnlyVector2? Scale { get; private set; } + public IReadOnlyVector3? Scale { get; private set; } - public ITexture SetScale(float x, float y) { - this.Scale = new Vector2f { X = x, Y = y }; + public ITexture SetScale2d(float x, float y) { + this.Scale = new Vector3f { X = x, Y = y }; + return this; + } + + public ITexture SetScale3d(float x, float y, float z) { + this.Scale = new Vector3f { X = x, Y = y, Z = z }; + this.IsTransform3d = true; return this; } - public float? RotationRadians { get; private set; } - public float? RotationDegrees => this.RotationRadians / MathF.PI * 180; + public IReadOnlyVector3? RotationRadians { get; private set; } - public ITexture SetRotationRadians(float rotationRadians) { - this.RotationRadians = rotationRadians; + public ITexture SetRotationRadians2d(float rotationRadians) { + this.RotationRadians = new Vector3f { Z = rotationRadians }; return this; } - public ITexture SetRotationDegrees(float rotationDegrees) - => SetRotationRadians(rotationDegrees / 180 * MathF.PI); + public ITexture SetRotationRadians3d(float xRadians, + float yRadians, + float zRadians) { + this.RotationRadians = new Vector3f + { X = xRadians, Y = yRadians, Z = zRadians }; + this.IsTransform3d = true; + return this; + } public override int GetHashCode() => new FluentHash() diff --git a/FinModelUtility/Fin/Fin/src/model/io/exporters/gltf/GltfTextureUtil.cs b/FinModelUtility/Fin/Fin/src/model/io/exporters/gltf/GltfTextureUtil.cs index 7ec4597e9..9833f48a1 100644 --- a/FinModelUtility/Fin/Fin/src/model/io/exporters/gltf/GltfTextureUtil.cs +++ b/FinModelUtility/Fin/Fin/src/model/io/exporters/gltf/GltfTextureUtil.cs @@ -24,7 +24,7 @@ public static TextureBuilder UseTexture(this ChannelBuilder channelBuilder, textureBuilder.WithTransform( new Vector2(finTexture.Offset?.X ?? 0, finTexture.Offset?.Y ?? 0), new Vector2(finTexture.Scale?.X ?? 1, finTexture.Scale?.Y ?? 1), - finTexture.RotationDegrees ?? 0); + finTexture.RotationRadians?.Z ?? 0); return textureBuilder; } diff --git a/FinModelUtility/Fin/Fin/src/shaders/glsl/GlslUtil.cs b/FinModelUtility/Fin/Fin/src/shaders/glsl/GlslUtil.cs index f0a2c860f..0a08bed60 100644 --- a/FinModelUtility/Fin/Fin/src/shaders/glsl/GlslUtil.cs +++ b/FinModelUtility/Fin/Fin/src/shaders/glsl/GlslUtil.cs @@ -159,7 +159,8 @@ struct Texture { sampler2D sampler; vec2 clampMin; vec2 clampMax; - mat2x3 transform; + mat2x3 transform2d; + mat4 transform3d; }; """; } @@ -182,10 +183,16 @@ public static string ReadColorFromTexture( return $"texture({textureName}, {uvConverter(rawUvName)})"; } + string transformedUv; + if (!(finTexture?.IsTransform3d ?? false)) { + transformedUv = $"({textureName}.transform2d * {rawUvName}).xy"; + } else { + transformedUv = $"({textureName}.transform3d * vec4({rawUvName}, 0, 1)).xy"; + } return $"texture({textureName}.sampler, " + "clamp(" + - $"{uvConverter($"({textureName}.transform * {rawUvName}).xy")}, " + + $"{uvConverter(transformedUv)}, " + $"{textureName}.clampMin, " + $"{textureName}.clampMax" + ")" + // clamp diff --git a/FinModelUtility/Formats/Dat/src/api/DatModelImporter.cs b/FinModelUtility/Formats/Dat/src/api/DatModelImporter.cs index edde5cf16..ead07f61a 100644 --- a/FinModelUtility/Formats/Dat/src/api/DatModelImporter.cs +++ b/FinModelUtility/Formats/Dat/src/api/DatModelImporter.cs @@ -3,10 +3,13 @@ using fin.io; using fin.language.equations.fixedFunction; using fin.language.equations.fixedFunction.impl; +using fin.math.matrix.four; +using fin.math.rotations; using fin.model; using fin.model.impl; using fin.model.io.importers; using fin.shaders.glsl; +using fin.util.enumerables; using fin.util.enums; using fin.util.hex; @@ -14,6 +17,8 @@ using schema.binary; +using static schema.binary.BinarySchemaContainerParser; + namespace dat.api { public class DatModelImporter : IModelImporter { public IModel ImportModel(DatModelFileBundle modelFileBundle) { @@ -78,7 +83,8 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { out finMaterial)) { var tObjsAndOffsets = mObj.TObjsAndOffsets.ToArray(); - var finTextures = new ITexture[tObjsAndOffsets.Length]; + var tObjsAndFinTextures = + new (TObj, ITexture)[tObjsAndOffsets.Length]; if (tObjsAndOffsets.Length > 0) { for (var i = 0; i < tObjsAndOffsets.Length; i++) { var (tObjOffset, tObj) = tObjsAndOffsets[i]; @@ -91,12 +97,30 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { finTexture.WrapModeU = tObj.WrapS.ToFinWrapMode(); finTexture.WrapModeV = tObj.WrapT.ToFinWrapMode(); - finTexture.SetScale(tObj.ScaleS, tObj.ScaleT); + // Why tf does Melee have 3D texture transforms...... + // https://github.com/Ploaj/HSDLib/blob/93a906444f34951c6eed4d8c6172bba43d4ada98/HSDRawViewer/Converters/ModelExporter.cs#L526 + + var tObjTranslation = tObj.Translation; + var tObjRotationRadians = tObj.RotationRadians; + var tObjScale = tObj.Scale; + + // TODO: Still isn't working..... + finTexture.SetRotationRadians3d( + -tObjTranslation.X, + -tObjTranslation.Y, + -tObjTranslation.Z); + finTexture.SetOffset3d(-tObjRotationRadians.X, + -tObjRotationRadians.Y, + -tObjRotationRadians.Z); + finTexture.SetScale3d( + tObj.RepeatS / tObjScale.X, + tObj.RepeatT / tObjScale.Y, + 1 / tObjScale.Z); finTexturesByTObjOffset[tObjOffset] = finTexture; } - finTextures[i] = finTexture; + tObjsAndFinTextures[i] = (tObj, finTexture); } } @@ -105,7 +129,7 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { finMaterial = fixedFunctionMaterial; this.PopulateFixedFunctionMaterial_(mObj, - finTextures, + tObjsAndFinTextures, fixedFunctionMaterial); } @@ -124,7 +148,8 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { .Select( pObjWeight => new BoneWeight( finBoneByJObj[pObjWeight.JObj], - pObjWeight.JObj.InverseBindMatrix, + pObjWeight.JObj + .InverseBindMatrix, pObjWeight.Weight )) .ToArray())) @@ -165,8 +190,9 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { .ToArray(); var finPrimitive = datPrimitive.Type switch { - GxOpcode.DRAW_TRIANGLES => finMesh.AddTriangles(finVertices), - GxOpcode.DRAW_QUADS => finMesh.AddQuads(finVertices), + GxOpcode.DRAW_TRIANGLES => + finMesh.AddTriangles(finVertices), + GxOpcode.DRAW_QUADS => finMesh.AddQuads(finVertices), GxOpcode.DRAW_TRIANGLE_STRIP => finMesh.AddTriangleStrip( finVertices) }; @@ -184,7 +210,7 @@ public IModel ImportModel(DatModelFileBundle modelFileBundle) { private void PopulateFixedFunctionMaterial_( MObj mObj, - IReadOnlyList finTextures, + IReadOnlyList<(TObj, ITexture)> tObjsAndFinTextures, IFixedFunctionMaterial fixedFunctionMaterial) { var equations = fixedFunctionMaterial.Equations; @@ -196,25 +222,79 @@ private void PopulateFixedFunctionMaterial_( var vertexAlpha = equations.CreateOrGetScalarInput( FixedFunctionSource.VERTEX_ALPHA_0); - IColorValue textureColor = colorOps.One; - IScalarValue textureAlpha = scalarOps.One; - if (finTextures.Count > 0) { - fixedFunctionMaterial.SetTextureSource(0, finTextures[0]); - textureColor = equations.CreateOrGetColorInput( - FixedFunctionSource.TEXTURE_COLOR_0); - textureAlpha = equations.CreateOrGetScalarInput( - FixedFunctionSource.TEXTURE_ALPHA_0); + (TObj, ITexture)? firstTObjAndFinTexture = + tObjsAndFinTextures.Count > 0 ? tObjsAndFinTextures[0] : null; + if (firstTObjAndFinTexture != null) { + fixedFunctionMaterial.SetTextureSource( + 0, + firstTObjAndFinTexture.Value.Item2); } var renderMode = mObj.RenderMode; var material = mObj.Material; - var outputColor = textureColor; + IColorValue? outputColor = colorOps.One; + if (renderMode.CheckFlag(RenderMode.CONSTANT)) { + var diffuseRgba = material.DiffuseColor; + var diffuseColor = equations.CreateColorConstant(diffuseRgba.Rf, + diffuseRgba.Gf, + diffuseRgba.Bf); + + outputColor = diffuseColor; + } if (renderMode.CheckFlag(RenderMode.VERTEX)) { outputColor = colorOps.Multiply(outputColor, vertexColor); } + if (firstTObjAndFinTexture != null) { + var textureColor0 = equations.CreateOrGetColorInput( + FixedFunctionSource.TEXTURE_COLOR_0); + + var (tObj, _) = firstTObjAndFinTexture.Value; + switch (tObj.Flags.GetColorMap()) { + case ColorMap.NONE: { + // TODO: What should this do? + break; + } + case ColorMap.ALPHA_MASK: { + // TODO: What should this do? + break; + } + case ColorMap.RGB_MASK: { + // TODO: What should this do? + break; + } + case ColorMap.BLEND: { + // TODO: Is this right? + outputColor = colorOps.Multiply(outputColor, textureColor0); + break; + } + case ColorMap.MODULATE: { + // TODO: Is this right? + outputColor = colorOps.Multiply(outputColor, textureColor0); + break; + } + case ColorMap.REPLACE: { + // TODO: Is this right? + outputColor = textureColor0; + break; + } + case ColorMap.PASS: { + // TODO: What should this do? + break; + } + case ColorMap.ADD: { + outputColor = colorOps.Add(outputColor, textureColor0); + break; + } + case ColorMap.SUB: { + outputColor = colorOps.Subtract(outputColor, textureColor0); + break; + } + } + } + // TODO: Is this right?? if (renderMode.CheckFlag(RenderMode.DIFFUSE)) { var ambientRgba = material.AmbientColor; @@ -233,25 +313,25 @@ private void PopulateFixedFunctionMaterial_( var lightColor = colorOps.Add(ambientColor, diffuseColor); outputColor = colorOps.Multiply(outputColor, lightColor); - } else if (renderMode.CheckFlag(RenderMode.CONSTANT)) { - var diffuseRgba = material.DiffuseColor; - var diffuseColor = equations.CreateColorConstant(diffuseRgba.Rf, - diffuseRgba.Gf, - diffuseRgba.Bf); - - outputColor = colorOps.Multiply(outputColor, diffuseColor); } - var outputAlpha = textureAlpha; + IScalarValue? outputAlpha = scalarOps.One; + if (renderMode.CheckFlag(RenderMode.ALPHA_VTX)) { - outputAlpha = scalarOps.Multiply(outputAlpha, vertexAlpha); + outputAlpha = vertexAlpha; } if (renderMode.CheckFlag(RenderMode.ALPHA_MAT)) { outputAlpha = - scalarOps.MultiplyWithConstant(outputAlpha, material.Alpha); + scalarOps.MultiplyWithConstant(outputAlpha, material!.Alpha); } + if (firstTObjAndFinTexture != null) { + outputAlpha = + scalarOps.Multiply(outputAlpha, + equations.CreateOrGetScalarInput( + FixedFunctionSource.TEXTURE_ALPHA_0)); + } equations.CreateColorOutput(FixedFunctionSource.OUTPUT_COLOR, outputColor ?? colorOps.Zero); diff --git a/FinModelUtility/Formats/Dat/src/schema/TObj.cs b/FinModelUtility/Formats/Dat/src/schema/TObj.cs index 17b910f38..2ec6d6ef1 100644 --- a/FinModelUtility/Formats/Dat/src/schema/TObj.cs +++ b/FinModelUtility/Formats/Dat/src/schema/TObj.cs @@ -2,6 +2,7 @@ using fin.image; using fin.image.formats; +using fin.schema.vector; using fin.util.color; using gx; @@ -11,6 +12,70 @@ using SixLabors.ImageSharp.PixelFormats; namespace dat.schema { + [Flags] + public enum TObjFlags { + COORD_UV = (0 << 0), + COORD_REFLECTION = (1 << 0), + COORD_HILIGHT = (2 << 0), + COORD_SHADOW = (3 << 0), + COORD_TOON = (4 << 0), + COORD_GRADATION = (5 << 0), + LIGHTMAP_DIFFUSE = (1 << 4), + LIGHTMAP_SPECULAR = (1 << 5), + LIGHTMAP_AMBIENT = (1 << 6), + LIGHTMAP_EXT = (1 << 7), + LIGHTMAP_SHADOW = (1 << 8), + //COLORMAP_NONE = (0 << 16), + COLORMAP_ALPHA_MASK = (1 << 16), + COLORMAP_RGB_MASK = (2 << 16), + COLORMAP_BLEND = (3 << 16), + COLORMAP_MODULATE = (4 << 16), + COLORMAP_REPLACE = (5 << 16), + COLORMAP_PASS = (6 << 16), + COLORMAP_ADD = (7 << 16), + COLORMAP_SUB = (8 << 16), + //ALPHAMAP_NONE = (0 << 20), + ALPHAMAP_ALPHA_MASK = (1 << 20), + ALPHAMAP_BLEND = (2 << 20), + ALPHAMAP_MODULATE = (3 << 20), + ALPHAMAP_REPLACE = (4 << 20), + ALPHAMAP_PASS = (5 << 20), + ALPHAMAP_ADD = (6 << 20), + ALPHAMAP_SUB = (7 << 20), + BUMP = (1 << 24), + MTX_DIRTY = (1 << 31) + } + + public enum ColorMap { + NONE = 0, + ALPHA_MASK = TObjFlags.COLORMAP_ALPHA_MASK, + RGB_MASK = TObjFlags.COLORMAP_RGB_MASK, + BLEND = TObjFlags.COLORMAP_BLEND, + MODULATE = TObjFlags.COLORMAP_MODULATE, + REPLACE = TObjFlags.COLORMAP_REPLACE, + PASS = TObjFlags.COLORMAP_PASS, + ADD = TObjFlags.COLORMAP_ADD, + SUB = TObjFlags.COLORMAP_SUB, + } + + public static class TObjFlagsExtensions { + public static ColorMap GetColorMap(this TObjFlags flags) { + var mask = 15 << 16; + var maskedFlags = (TObjFlags) ((int) flags & mask); + return maskedFlags switch { + TObjFlags.COLORMAP_ALPHA_MASK => ColorMap.ALPHA_MASK, + TObjFlags.COLORMAP_RGB_MASK => ColorMap.RGB_MASK, + TObjFlags.COLORMAP_BLEND => ColorMap.BLEND, + TObjFlags.COLORMAP_MODULATE => ColorMap.MODULATE, + TObjFlags.COLORMAP_REPLACE => ColorMap.REPLACE, + TObjFlags.COLORMAP_PASS => ColorMap.PASS, + TObjFlags.COLORMAP_ADD => ColorMap.ADD, + TObjFlags.COLORMAP_SUB => ColorMap.SUB, + 0 => ColorMap.NONE, + }; + } + } + /// /// Texture object. /// @@ -22,31 +87,49 @@ namespace dat.schema { public class TObj : IBinaryDeserializable { public uint StringOffset { get; private set; } public string? Name { get; set; } + + public uint NextTObjOffset { get; private set; } + public TObj? NextTObj { get; private set; } - public IImage Image { get; private set; } + public GxTexGenSrc TexGenSrc { get; private set; } + + public Vector3f RotationRadians { get; private set; } + public Vector3f Scale { get; private set; } + public Vector3f Translation { get; private set; } public GxWrapMode WrapS { get; private set; } public GxWrapMode WrapT { get; private set; } - public byte ScaleS { get; private set; } - public byte ScaleT { get; private set; } + public byte RepeatS { get; private set; } + public byte RepeatT { get; private set; } - public uint NextTObjOffset { get; private set; } - public TObj? NextTObj { get; private set; } + public TObjFlags Flags { get; private set; } + + public IImage Image { get; private set; } public unsafe void Read(IBinaryReader br) { this.StringOffset = br.ReadUInt32(); this.NextTObjOffset = br.ReadUInt32(); - br.Position += 4 * 11; + br.Position += 4; + + this.TexGenSrc = (GxTexGenSrc) br.ReadUInt32(); + + this.RotationRadians = br.ReadNew(); + this.Scale = br.ReadNew(); + this.Translation = br.ReadNew(); this.WrapS = (GxWrapMode) br.ReadUInt32(); this.WrapT = (GxWrapMode) br.ReadUInt32(); - this.ScaleS = br.ReadByte(); - this.ScaleT = br.ReadByte(); + this.RepeatS = br.ReadByte(); + this.RepeatT = br.ReadByte(); + + br.Position += 2; + + this.Flags = (TObjFlags) br.ReadUInt32(); - br.Position += 2 + 12; + br.Position += 4 * 2; var imageOffset = br.ReadUInt32(); var paletteOffset = br.ReadUInt32(); diff --git a/FinModelUtility/Formats/J3d/J3d/src/Exporter/BmdMaterialManager.cs b/FinModelUtility/Formats/J3d/J3d/src/Exporter/BmdMaterialManager.cs index 23e7a636c..72c067c79 100644 --- a/FinModelUtility/Formats/J3d/J3d/src/Exporter/BmdMaterialManager.cs +++ b/FinModelUtility/Formats/J3d/J3d/src/Exporter/BmdMaterialManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using fin.data.lazy; @@ -99,11 +100,11 @@ private IList var texTranslation = texMatrix.Translation; var texScale = texMatrix.Scale; - var texRotationDegrees = texMatrix.Rotation / 32768f * 180; + var texRotationRadians = texMatrix.Rotation / 32768f * MathF.PI; - texture.SetOffset(texTranslation.X, texTranslation.Y) - .SetScale(texScale.X, texScale.Y) - .SetRotationDegrees(texRotationDegrees); + texture.SetOffset2d(texTranslation.X, texTranslation.Y) + .SetScale2d(texScale.X, texScale.Y) + .SetRotationRadians2d(texRotationRadians); } return texture;