Support additional UV channels in GLB export

This commit is contained in:
ds5678 2024-08-17 09:19:08 -07:00
parent 87b4383a92
commit bec23c5f43
3 changed files with 131 additions and 34 deletions

View File

@ -60,6 +60,16 @@ namespace AssetRipper.Export.Modules.Models
case GlbMeshType.PositionNormalTangent | GlbMeshType.Color1Texture2 | GlbMeshType.Empty:
return BuildSubMeshes<VertexPositionNormalTangent, VertexColor1Texture2, VertexEmpty>(parameters);
case GlbMeshType.Position | GlbMeshType.TextureN | GlbMeshType.Empty:
case GlbMeshType.Position | GlbMeshType.Color1TextureN | GlbMeshType.Empty:
return BuildSubMeshes<VertexPosition, VertexVariable, VertexEmpty>(parameters);
case GlbMeshType.PositionNormal | GlbMeshType.TextureN | GlbMeshType.Empty:
case GlbMeshType.PositionNormal | GlbMeshType.Color1TextureN | GlbMeshType.Empty:
return BuildSubMeshes<VertexPositionNormal, VertexVariable, VertexEmpty>(parameters);
case GlbMeshType.PositionNormalTangent | GlbMeshType.TextureN | GlbMeshType.Empty:
case GlbMeshType.PositionNormalTangent | GlbMeshType.Color1TextureN | GlbMeshType.Empty:
return BuildSubMeshes<VertexPositionNormalTangent, VertexVariable, VertexEmpty>(parameters);
case GlbMeshType.Position | GlbMeshType.Empty | GlbMeshType.Joints4:
return BuildSubMeshes<VertexPosition, VertexEmpty, VertexJoints4>(parameters);
case GlbMeshType.PositionNormal | GlbMeshType.Empty | GlbMeshType.Joints4:
@ -102,6 +112,16 @@ namespace AssetRipper.Export.Modules.Models
case GlbMeshType.PositionNormalTangent | GlbMeshType.Color1Texture2 | GlbMeshType.Joints4:
return BuildSubMeshes<VertexPositionNormalTangent, VertexColor1Texture2, VertexJoints4>(parameters);
case GlbMeshType.Position | GlbMeshType.TextureN | GlbMeshType.Joints4:
case GlbMeshType.Position | GlbMeshType.Color1TextureN | GlbMeshType.Joints4:
return BuildSubMeshes<VertexPosition, VertexVariable, VertexJoints4>(parameters);
case GlbMeshType.PositionNormal | GlbMeshType.TextureN | GlbMeshType.Joints4:
case GlbMeshType.PositionNormal | GlbMeshType.Color1TextureN | GlbMeshType.Joints4:
return BuildSubMeshes<VertexPositionNormal, VertexVariable, VertexJoints4>(parameters);
case GlbMeshType.PositionNormalTangent | GlbMeshType.TextureN | GlbMeshType.Joints4:
case GlbMeshType.PositionNormalTangent | GlbMeshType.Color1TextureN | GlbMeshType.Joints4:
return BuildSubMeshes<VertexPositionNormalTangent, VertexVariable, VertexJoints4>(parameters);
default:
throw new ArgumentOutOfRangeException(nameof(meshData), meshData.MeshType, "Mesh type not supported.");
}
@ -316,6 +336,22 @@ namespace AssetRipper.Export.Modules.Models
{
return Cast<VertexColor1Texture2, TvM>(new VertexColor1Texture2(meshData.TryGetColorAtIndex(index).Vector, meshData.TryGetUV0AtIndex(index), meshData.TryGetUV1AtIndex(index)));
}
else if (typeof(TvM) == typeof(VertexVariable))
{
VertexVariable result = new(meshData.HasColors ? 1 : 0, meshData.UVCount)
{
Color = meshData.TryGetColorAtIndex(index).Vector,
TexCoord0 = meshData.TryGetUV0AtIndex(index),
TexCoord1 = meshData.TryGetUV1AtIndex(index),
TexCoord2 = meshData.TryGetUV2AtIndex(index),
TexCoord3 = meshData.TryGetUV3AtIndex(index),
TexCoord4 = meshData.TryGetUV4AtIndex(index),
TexCoord5 = meshData.TryGetUV5AtIndex(index),
TexCoord6 = meshData.TryGetUV6AtIndex(index),
TexCoord7 = meshData.TryGetUV7AtIndex(index),
};
return Cast<VertexVariable, TvM>(result);
}
else
{
return default;

View File

@ -29,9 +29,9 @@ namespace AssetRipper.Export.Modules.Models
{
GlbMeshType meshType = default;
if (Normals != null && Normals.Length == Vertices.Length)
if (HasNormals)
{
if (Tangents != null && Tangents.Length == Vertices.Length)
if (HasTangents)
{
meshType |= GlbMeshType.PositionNormalTangent;
}
@ -41,33 +41,20 @@ namespace AssetRipper.Export.Modules.Models
}
}
if (UV0 != null && UV0.Length == Vertices.Length)
meshType |= UVCount switch
{
if (UV1 != null && UV1.Length == Vertices.Length)
{
if (UV2 != null && UV2.Length == Vertices.Length)
{
//TODO: Not implemented yet. Defines a vertex with up to 8 UV channels.
//meshType |= GlbMeshType.TextureN;
meshType |= GlbMeshType.Texture2;
}
else
{
meshType |= GlbMeshType.Texture2;
}
}
else
{
meshType |= GlbMeshType.Texture1;
}
}
0 => default,
1 => GlbMeshType.Texture1,
2 => GlbMeshType.Texture2,
_ => GlbMeshType.TextureN,
};
if (Colors != null && Colors.Length == Vertices.Length)
if (HasColors)
{
meshType |= GlbMeshType.Color1;
}
if (Skin != null && Skin.Length == Vertices.Length)
if (HasSkin)
{
meshType |= GlbMeshType.Joints4;
}
@ -76,6 +63,57 @@ namespace AssetRipper.Export.Modules.Models
}
}
public bool HasNormals => Normals != null && Normals.Length == Vertices.Length;
public bool HasTangents => Tangents != null && Tangents.Length == Vertices.Length;
public bool HasColors => Colors != null && Colors.Length == Vertices.Length;
public bool HasSkin => Skin != null && Skin.Length == Vertices.Length;
public int UVCount
{
get
{
if (UV0 is null || UV0.Length != Vertices.Length)
{
return 0;
}
else if (UV1 is null || UV1.Length != Vertices.Length)
{
return 1;
}
else if (UV2 is null || UV2.Length != Vertices.Length)
{
return 2;
}
else if (UV3 is null || UV3.Length != Vertices.Length)
{
return 3;
}
else if (UV4 is null || UV4.Length != Vertices.Length)
{
return 4;
}
else if (UV5 is null || UV5.Length != Vertices.Length)
{
return 5;
}
else if (UV6 is null || UV6.Length != Vertices.Length)
{
return 6;
}
else if (UV7 is null || UV7.Length != Vertices.Length)
{
return 7;
}
else
{
return 8;
}
}
}
public Vector3 TryGetVertexAtIndex(uint index) => Vertices[index];
public Vector3 TryGetNormalAtIndex(uint index) => TryGetAtIndex(Normals, index);
public Vector4 TryGetTangentAtIndex(uint index)
@ -92,6 +130,12 @@ namespace AssetRipper.Export.Modules.Models
public ColorFloat TryGetColorAtIndex(uint index) => TryGetAtIndex(Colors, index);
public Vector2 TryGetUV0AtIndex(uint index) => FlipY(TryGetAtIndex(UV0, index));
public Vector2 TryGetUV1AtIndex(uint index) => FlipY(TryGetAtIndex(UV1, index));
public Vector2 TryGetUV2AtIndex(uint index) => FlipY(TryGetAtIndex(UV2, index));
public Vector2 TryGetUV3AtIndex(uint index) => FlipY(TryGetAtIndex(UV3, index));
public Vector2 TryGetUV4AtIndex(uint index) => FlipY(TryGetAtIndex(UV4, index));
public Vector2 TryGetUV5AtIndex(uint index) => FlipY(TryGetAtIndex(UV5, index));
public Vector2 TryGetUV6AtIndex(uint index) => FlipY(TryGetAtIndex(UV6, index));
public Vector2 TryGetUV7AtIndex(uint index) => FlipY(TryGetAtIndex(UV7, index));
public BoneWeight4 TryGetSkinAtIndex(uint index)
{
BoneWeight4 s = TryGetAtIndex(Skin, index);

View File

@ -12,6 +12,14 @@ internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
{
#region constructors
public VertexVariable(
int maxColors,
int maxTextCoords)
{
MaxColors = int.Clamp(maxColors, 0, 1);
MaxTextCoords = int.Clamp(maxTextCoords, 0, 8);
}
public VertexVariable(
int maxColors,
int maxTextCoords,
@ -83,7 +91,7 @@ internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
public readonly int MaxColors { get; }
public readonly int MaxTextCoords { get; }
IEnumerable<KeyValuePair<string, AttributeFormat>> IVertexReflection.GetEncodingAttributes()
readonly IEnumerable<KeyValuePair<string, AttributeFormat>> IVertexReflection.GetEncodingAttributes()
{
if (MaxColors == 1)
{
@ -141,7 +149,21 @@ internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
{
throw new NotSupportedException();
if (MaxTextCoords <= 4)
{
return new()
{
Color0Delta = baseValue.MaxColors > 0 ? Color - baseValue.GetColor(0) : default,
TexCoord0Delta = baseValue.MaxTextCoords > 0 ? TexCoord0 - baseValue.GetTexCoord(0) : default,
TexCoord1Delta = baseValue.MaxTextCoords > 1 ? TexCoord1 - baseValue.GetTexCoord(1) : default,
TexCoord2Delta = baseValue.MaxTextCoords > 2 ? TexCoord2 - baseValue.GetTexCoord(2) : default,
TexCoord3Delta = baseValue.MaxTextCoords > 3 ? TexCoord3 - baseValue.GetTexCoord(3) : default,
};
}
else
{
throw new NotSupportedException();
}
}
public void Add(in VertexMaterialDelta delta)
{
@ -153,10 +175,8 @@ internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
}
void IVertexMaterial.SetColor(int index, Vector4 color)
{
if (index == 0)
{
Color = color;
}
ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
Color = color;
}
void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
{
@ -174,11 +194,8 @@ internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
}
public readonly Vector4 GetColor(int index)
{
return index switch
{
0 => Color,
_ => throw new ArgumentOutOfRangeException(nameof(index)),
};
ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
return Color;
}
public readonly Vector2 GetTexCoord(int index)
{