Add UV2 support

This commit is contained in:
ackwell 2024-01-02 12:41:14 +11:00
parent 215f807483
commit d85cbd8051

View file

@ -63,8 +63,10 @@ public class MeshExporter
_boneIndexMap = BuildBoneIndexMap(boneNameMap); _boneIndexMap = BuildBoneIndexMap(boneNameMap);
var usages = _mdl.VertexDeclarations[_meshIndex].VertexElements var usages = _mdl.VertexDeclarations[_meshIndex].VertexElements
.Select(element => (MdlFile.VertexUsage)element.Usage) .ToImmutableDictionary(
.ToImmutableHashSet(); element => (MdlFile.VertexUsage)element.Usage,
element => (MdlFile.VertexType)element.Type
);
_geometryType = GetGeometryType(usages); _geometryType = GetGeometryType(usages);
_materialType = GetMaterialType(usages); _materialType = GetMaterialType(usages);
@ -263,15 +265,15 @@ public class MeshExporter
} }
/// <summary> Get the vertex geometry type for this mesh's vertex usages. </summary> /// <summary> Get the vertex geometry type for this mesh's vertex usages. </summary>
private Type GetGeometryType(IReadOnlySet<MdlFile.VertexUsage> usages) private Type GetGeometryType(IReadOnlyDictionary<MdlFile.VertexUsage, MdlFile.VertexType> usages)
{ {
if (!usages.Contains(MdlFile.VertexUsage.Position)) if (!usages.ContainsKey(MdlFile.VertexUsage.Position))
throw new Exception("Mesh does not contain position vertex elements."); throw new Exception("Mesh does not contain position vertex elements.");
if (!usages.Contains(MdlFile.VertexUsage.Normal)) if (!usages.ContainsKey(MdlFile.VertexUsage.Normal))
return typeof(VertexPosition); return typeof(VertexPosition);
if (!usages.Contains(MdlFile.VertexUsage.Tangent1)) if (!usages.ContainsKey(MdlFile.VertexUsage.Tangent1))
return typeof(VertexPositionNormal); return typeof(VertexPositionNormal);
return typeof(VertexPositionNormalTangent); return typeof(VertexPositionNormalTangent);
@ -302,20 +304,32 @@ public class MeshExporter
} }
/// <summary> Get the vertex material type for this mesh's vertex usages. </summary> /// <summary> Get the vertex material type for this mesh's vertex usages. </summary>
private Type GetMaterialType(IReadOnlySet<MdlFile.VertexUsage> usages) private Type GetMaterialType(IReadOnlyDictionary<MdlFile.VertexUsage, MdlFile.VertexType> usages)
{ {
// TODO: IIUC, xiv's uv2 is usually represented as the second two components of a vec4 uv attribute - add support. var uvCount = 0;
if (usages.TryGetValue(MdlFile.VertexUsage.UV, out var type))
uvCount = type switch
{
MdlFile.VertexType.Half2 => 1,
MdlFile.VertexType.Half4 => 2,
_ => throw new Exception($"Unexpected UV vertex type {type}.")
};
var materialUsages = ( var materialUsages = (
usages.Contains(MdlFile.VertexUsage.UV), uvCount,
usages.Contains(MdlFile.VertexUsage.Color) usages.ContainsKey(MdlFile.VertexUsage.Color)
); );
return materialUsages switch return materialUsages switch
{ {
(true, true) => typeof(VertexColor1Texture1), (2, true) => typeof(VertexColor1Texture2),
(true, false) => typeof(VertexTexture1), (2, false) => typeof(VertexTexture2),
(false, true) => typeof(VertexColor1), (1, true) => typeof(VertexColor1Texture1),
(false, false) => typeof(VertexEmpty), (1, false) => typeof(VertexTexture1),
(0, true) => typeof(VertexColor1),
(0, false) => typeof(VertexEmpty),
_ => throw new Exception("Unreachable."),
}; };
} }
@ -337,13 +351,34 @@ public class MeshExporter
ToVector2(attributes[MdlFile.VertexUsage.UV]) ToVector2(attributes[MdlFile.VertexUsage.UV])
); );
// XIV packs two UVs into a single vec4 attribute.
if (_materialType == typeof(VertexTexture2))
{
var uv = ToVector4(attributes[MdlFile.VertexUsage.UV]);
return new VertexTexture2(
new Vector2(uv.X, uv.Y),
new Vector2(uv.Z, uv.W)
);
}
if (_materialType == typeof(VertexColor1Texture2))
{
var uv = ToVector4(attributes[MdlFile.VertexUsage.UV]);
return new VertexColor1Texture2(
ToVector4(attributes[MdlFile.VertexUsage.Color]),
new Vector2(uv.X, uv.Y),
new Vector2(uv.Z, uv.W)
);
}
throw new Exception($"Unknown material type {_skinningType}"); throw new Exception($"Unknown material type {_skinningType}");
} }
/// <summary> Get the vertex skinning type for this mesh's vertex usages. </summary> /// <summary> Get the vertex skinning type for this mesh's vertex usages. </summary>
private Type GetSkinningType(IReadOnlySet<MdlFile.VertexUsage> usages) private Type GetSkinningType(IReadOnlyDictionary<MdlFile.VertexUsage, MdlFile.VertexType> usages)
{ {
if (usages.Contains(MdlFile.VertexUsage.BlendWeights) && usages.Contains(MdlFile.VertexUsage.BlendIndices)) if (usages.ContainsKey(MdlFile.VertexUsage.BlendWeights) && usages.ContainsKey(MdlFile.VertexUsage.BlendIndices))
return typeof(VertexJoints4); return typeof(VertexJoints4);
return typeof(VertexEmpty); return typeof(VertexEmpty);