Skip to content

Commit

Permalink
Strip chunks now being split at conversion when too large
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin113D committed Aug 6, 2024
1 parent 1ed76f8 commit 52b18bb
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 70 deletions.
96 changes: 84 additions & 12 deletions src/SA3D.Modeling/Mesh/Chunk/ChunkTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,6 @@ public static bool CheckHasWeights(this VertexChunkType type)
or VertexChunkType.NormalAttributes;
}

/// <summary>
/// Checks whether a vertex chunktype has diffuse colors
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns></returns>
public static bool CheckStripHasColor(this PolyChunkType type)
{
return type is PolyChunkType.Strip_Color
or PolyChunkType.Strip_TexColor
or PolyChunkType.Strip_HDTexColor;
}

/// <summary>
/// Returns the number of 4-byte values a chunk vertex has.
/// </summary>
Expand Down Expand Up @@ -167,5 +155,89 @@ public static ushort GetIntegerSize(this VertexChunkType type)
throw new ArgumentException($"Invalid vertex chunk type: {type}", nameof(type));
}
}


/// <summary>
/// Checks whether a polychunk type is a type of strip chunk.
/// </summary>
/// <param name="type">The type to check.</param>
public static bool CheckIsStrip(this PolyChunkType type)
{
return (int)type >= _strip && type <= PolyChunkType.Strip_HDTexDouble;
}

/// <summary>
/// Returns the number of texture coordinate sets by strip chunk type.
/// <br/> Throws an error if <paramref name="type"/> is not a strip chunk type.
/// </summary>
/// <param name="type">Type to get the strip chunk texture coordinate set count of.</param>
public static int GetStripTexCoordCount(this PolyChunkType type)
{
if(!type.CheckIsStrip())
{
throw new ArgumentException($"Polychunk type \"{type}\" is not a strip chunk type!", nameof(type));
}
else if(type is PolyChunkType.Strip_Tex
or PolyChunkType.Strip_HDTex
or PolyChunkType.Strip_TexNormal
or PolyChunkType.Strip_HDTexNormal
or PolyChunkType.Strip_TexColor
or PolyChunkType.Strip_HDTexColor)
{
return 1;
}
else if(type is PolyChunkType.Strip_TexDouble
or PolyChunkType.Strip_HDTexDouble)
{
return 2;
}
else
{
return 0;
}
}

/// <summary>
/// Checks whether a strip chunk type contains HD texture coordinates.
/// <br/> Throws an error if <paramref name="type"/> is not a strip chunk type.
/// </summary>
/// <param name="type">Type to check</param>
public static bool CheckStripHasHDTexcoords(this PolyChunkType type)
{
return !type.CheckIsStrip()
? throw new ArgumentException($"Polychunk type \"{type}\" is not a strip chunk type!", nameof(type))
: type is PolyChunkType.Strip_HDTex
or PolyChunkType.Strip_HDTexColor
or PolyChunkType.Strip_HDTexNormal
or PolyChunkType.Strip_HDTexDouble;
}

/// <summary>
/// Checks whether a strip chunk type contains colors.
/// <br/> Throws an error if <paramref name="type"/> is not a strip chunk type.
/// </summary>
/// <param name="type">Type to check</param>
public static bool CheckStripHasColors(this PolyChunkType type)
{
return !type.CheckIsStrip()
? throw new ArgumentException($"Polychunk type \"{type}\" is not a strip chunk type!", nameof(type))
: type is PolyChunkType.Strip_Color
or PolyChunkType.Strip_TexColor
or PolyChunkType.Strip_HDTexColor;
}

/// <summary>
/// Checks whether a strip chunk type contains normals.
/// <br/> Throws an error if <paramref name="type"/> is not a strip chunk type.
/// </summary>
/// <param name="type">Type to check</param>
public static bool CheckStripHasNormals(this PolyChunkType type)
{
return !type.CheckIsStrip()
? throw new ArgumentException($"Polychunk type \"{type}\" is not a strip chunk type!", nameof(type))
: type is PolyChunkType.Strip_Normal
or PolyChunkType.Strip_TexNormal
or PolyChunkType.Strip_HDTexNormal;
}
}
}
43 changes: 5 additions & 38 deletions src/SA3D.Modeling/Mesh/Chunk/PolyChunks/StripChunk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,55 +17,22 @@ public class StripChunk : SizedChunk
/// <summary>
/// The number of texture coordinate sets the polygons utilize.
/// </summary>
public int TexcoordCount
{
get
{
if(Type is PolyChunkType.Strip_Tex
or PolyChunkType.Strip_HDTex
or PolyChunkType.Strip_TexNormal
or PolyChunkType.Strip_HDTexNormal
or PolyChunkType.Strip_TexColor
or PolyChunkType.Strip_HDTexColor)
{
return 1;
}
else if(Type is PolyChunkType.Strip_TexDouble
or PolyChunkType.Strip_HDTexDouble)
{
return 2;
}
else
{
return 0;
}
}
}
public int TexcoordCount => Type.GetStripTexCoordCount();

/// <summary>
/// Whether texture coordinates are in the 0-1023 range, instead of 0-255.
/// </summary>
public bool HasHDTexcoords =>
Type is PolyChunkType.Strip_HDTex
or PolyChunkType.Strip_HDTexColor
or PolyChunkType.Strip_HDTexNormal
or PolyChunkType.Strip_HDTexDouble;
public bool HasHDTexcoords => Type.CheckStripHasHDTexcoords();

/// <summary>
/// Whether polygons utilize normals.
/// </summary>
public bool HasNormals =>
Type is PolyChunkType.Strip_Normal
or PolyChunkType.Strip_TexNormal
or PolyChunkType.Strip_HDTexNormal;
public bool HasNormals => Type.CheckStripHasNormals();

/// <summary>
/// Whether polygons utilize colors.
/// </summary>
public bool HasColors =>
Type is PolyChunkType.Strip_Color
or PolyChunkType.Strip_TexColor
or PolyChunkType.Strip_HDTexColor;
public bool HasColors => Type.CheckStripHasColors();

#endregion

Expand Down Expand Up @@ -222,7 +189,7 @@ public override ushort Size
{
uint result = RawSize;

if(result > ushort.MaxValue)
if(result * 2 > ushort.MaxValue)
{
throw new InvalidOperationException($"Strip chunk size ({result}) exceeds maximum size ({ushort.MaxValue}).");
}
Expand Down
5 changes: 5 additions & 0 deletions src/SA3D.Modeling/Mesh/Chunk/Structs/ChunkStrip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ namespace SA3D.Modeling.Mesh.Chunk.Structs
/// </summary>
public struct ChunkStrip : ICloneable
{
/// <summary>
/// Maximum allowed size of a (collection of) strip chunk(s)
/// </summary>
public const uint MaxByteSize = ushort.MaxValue - 4;

/// <summary>
/// Triangle corners.
/// <br/> The first two corners are only used for their index.
Expand Down
59 changes: 41 additions & 18 deletions src/SA3D.Modeling/Mesh/Converters/ChunkConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -548,31 +548,54 @@ protected override ChunkResult ConvertWeightless(WeightedMesh wba, bool optimize

private static PolyChunk[] CreateStripChunk(ChunkCorner[] corners, BufferMaterial material, bool writeSpecular, byte texcoordPrecision)
{
ChunkCorner[][] stripCorners = TriangleStrippifier.Global.StrippifyNoDegen(corners, out bool[] reversed);
ChunkStrip[] strips = new ChunkStrip[stripCorners.Length];

for(int i = 0; i < strips.Length; i++)
{
strips[i] = new(stripCorners[i], reversed[i]);
}

bool hasUV = material.UseTexture && !material.NormalMapping;
PolyChunkType stripType = !hasUV
? PolyChunkType.Strip_Blank
: texcoordPrecision >= 2
? PolyChunkType.Strip_HDTex
: PolyChunkType.Strip_Tex;

StripChunk stripchunk = new(stripType, strips, 0)
ChunkCorner[][] stripCorners = TriangleStrippifier.Global.StrippifyNoDegen(corners, out bool[] reversed);
List<ChunkStrip[]> stripCollections = [];
List<ChunkStrip> currentStrips = [];
uint currentStripsSize = 0;

int stripTexcoordCount = stripType.GetStripTexCoordCount();
bool stripHasNormals = stripType.CheckStripHasNormals();
bool stripHasColors = stripType.CheckStripHasColors();

for(int i = 0; i < stripCorners.Length; i++)
{
FlatShading = material.Flat,
IgnoreAmbient = material.NoAmbient,
IgnoreLight = material.NoLighting,
IgnoreSpecular = material.NoSpecular,
EnvironmentMapping = material.NormalMapping,
UseAlpha = material.UseAlpha,
DoubleSide = !material.BackfaceCulling
};
ChunkStrip strip = new(stripCorners[i], reversed[i]);

uint stripSize = strip.Size(stripTexcoordCount, stripHasNormals, stripHasColors, 0);
if(currentStripsSize + stripSize > ChunkStrip.MaxByteSize)
{
currentStripsSize = 0;
stripCollections.Add([.. currentStrips]);
currentStrips.Clear();
}

currentStripsSize += stripSize;
currentStrips.Add(strip);
}

stripCollections.Add([.. currentStrips]);

StripChunk[] stripchunks = new StripChunk[stripCollections.Count];
for(int i = 0; i < stripchunks.Length; i++)
{
stripchunks[i] = new(stripType, stripCollections[i], 0)
{
FlatShading = material.Flat,
IgnoreAmbient = material.NoAmbient,
IgnoreLight = material.NoLighting,
IgnoreSpecular = material.NoSpecular,
EnvironmentMapping = material.NormalMapping,
UseAlpha = material.UseAlpha,
DoubleSide = !material.BackfaceCulling
};
}

TextureChunk textureChunk = new()
{
Expand All @@ -599,7 +622,7 @@ private static PolyChunk[] CreateStripChunk(ChunkCorner[] corners, BufferMateria
materialChunk.SpecularExponent = (byte)material.SpecularExponent;
}

return new PolyChunk[] { materialChunk, textureChunk, stripchunk };
return [materialChunk, textureChunk, .. stripchunks];
}

protected override void CorrectSpace(Attach attach, Matrix4x4 vertexMatrix, Matrix4x4 normalMatrix)
Expand Down
1 change: 0 additions & 1 deletion src/SA3D.Modeling/PublicAPI/net8.0/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,6 @@ static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckHasSpecularColor(this S
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckHasWeights(this SA3D.Modeling.Mesh.Chunk.VertexChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckIsNormal32(this SA3D.Modeling.Mesh.Chunk.VertexChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckIsVec4(this SA3D.Modeling.Mesh.Chunk.VertexChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckStripHasColor(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.GetIntegerSize(this SA3D.Modeling.Mesh.Chunk.VertexChunkType type) -> ushort
static SA3D.Modeling.Mesh.Chunk.PolyChunk.Read(SA3D.Common.IO.EndianStackReader! reader, ref uint address, SA3D.Modeling.Structs.PointerLUT! lut) -> SA3D.Modeling.Mesh.Chunk.PolyChunk!
static SA3D.Modeling.Mesh.Chunk.PolyChunk.ReadArray(SA3D.Common.IO.EndianStackReader! reader, uint address, SA3D.Modeling.Structs.PointerLUT! lut) -> SA3D.Modeling.Mesh.Chunk.PolyChunk?[]!
Expand Down
8 changes: 7 additions & 1 deletion src/SA3D.Modeling/PublicAPI/net8.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
SA3D.Modeling.Mesh.Weighted.WeightedMesh.ToAttach(SA3D.Modeling.Mesh.AttachFormat format, bool optimize, out int[]?[]! vertexMapping) -> SA3D.Modeling.Mesh.Attach!
const SA3D.Modeling.Mesh.Chunk.Structs.ChunkStrip.MaxByteSize = 65531 -> uint
SA3D.Modeling.Mesh.Weighted.WeightedMesh.ToAttach(SA3D.Modeling.Mesh.AttachFormat format, bool optimize, out int[]?[]! vertexMapping) -> SA3D.Modeling.Mesh.Attach!
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckIsStrip(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckStripHasColors(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckStripHasHDTexcoords(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.CheckStripHasNormals(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> bool
static SA3D.Modeling.Mesh.Chunk.ChunkTypeExtensions.GetStripTexCoordCount(this SA3D.Modeling.Mesh.Chunk.PolyChunkType type) -> int
static SA3D.Modeling.Mesh.Weighted.WeightedMesh.ToModel(SA3D.Modeling.ObjectData.Node! model, SA3D.Modeling.Mesh.Weighted.WeightedMesh![]! meshes, SA3D.Modeling.Mesh.AttachFormat format, bool optimize, out int[]?[]! vertexMapping) -> void

0 comments on commit 52b18bb

Please sign in to comment.