Skip to content

Commit

Permalink
Link CPlugCrystal 0x006 (lightmaps) with vertices
Browse files Browse the repository at this point in the history
  • Loading branch information
BigBang1112 committed Nov 24, 2024
1 parent 8c6b466 commit c5f1962
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 11 deletions.
7 changes: 0 additions & 7 deletions Src/GBX.NET/Engines/Plug/CPlugCrystal.chunkl
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ CPlugCrystal 0x09003000
0x005 [MP4, TM2020] // layers

0x006 [MP4.v0, TM2020.v1] // lightmap UVs
version
v0=
vec2[]
v1+
uint[] // two Int16 technically
v2+
optimizedint[]

0x007 [MP4, TM2020] // smoothing groups
version
Expand Down
135 changes: 131 additions & 4 deletions Src/GBX.NET/Engines/Plug/CPlugCrystal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ public void ExportToObj(string objFilePath, string mtlFilePath, int? mergeVertic
ExportToObj(objWriter, mtlWriter, mergeVerticesDigitThreshold);
}

public Vec2[] GetLightmapCoords()
{
return Layers.OfType<GeometryLayer>()
.Select(x => x.Crystal)
.OfType<Crystal>()
.SelectMany(c => c.Faces)
.SelectMany(f => f.Vertices.Select(v => v.LightmapCoord))
.ToArray();
}

public Vec2[][] GetLightmapCoordFaces()
{
return Layers.OfType<GeometryLayer>()
.Select(x => x.Crystal)
.OfType<Crystal>()
.SelectMany(c => c.Faces)
.Select(f => f.Vertices.Select(v => v.LightmapCoord).ToArray())
.ToArray();
}

public partial class Chunk09003000 : IVersionable
{
public int Version { get; set; }
Expand Down Expand Up @@ -130,6 +150,113 @@ public override void Write(CPlugCrystal n, GbxWriter w)
}
}

public partial class Chunk09003006 : IVersionable
{
public int Version { get; set; }

public override void Read(CPlugCrystal n, GbxReader r)
{
Version = r.ReadInt32();

var faces = n.Layers.OfType<GeometryLayer>()
.Select(x => x.Crystal)
.OfType<Crystal>()
.SelectMany(c => c.Faces);

var lightmapCoordCount = r.ReadInt32();

if (Version == 0)
{
var counter = 0;
foreach (var face in faces)
{
for (int i = 0; i < face.Vertices.Length; i++)
{
face.Vertices[i] = face.Vertices[i] with { LightmapCoord = r.ReadVec2() };
counter++;

if (counter > lightmapCoordCount)
{
throw new Exception("LightmapCoord count exceeded");
}
}
}

if (counter != lightmapCoordCount)
{
throw new Exception("LightmapCoord count mismatch");
}
}

if (Version >= 1)
{
var lightmaps = new Vec2[lightmapCoordCount];

for (int i = 0; i < lightmapCoordCount; i++)
{
lightmaps[i] = (r.ReadUInt16() / (float)ushort.MaxValue, r.ReadUInt16() / (float)ushort.MaxValue);
}

var indices = Version >= 2 ? r.ReadArrayOptimizedInt() : null;

var counter = 0;
foreach (var face in faces)
{
for (int i = 0; i < face.Vertices.Length; i++)
{
face.Vertices[i] = face.Vertices[i] with { LightmapCoord = lightmaps[indices?[counter++] ?? counter] };

if (counter > lightmapCoordCount)
{
throw new Exception("LightmapCoord count exceeded");
}
}
}

if (counter != lightmapCoordCount)
{
throw new Exception("LightmapCoord count mismatch");
}
}
}

public override void Write(CPlugCrystal n, GbxWriter w)
{
w.Write(Version);

var faces = n.Layers.OfType<GeometryLayer>()
.Select(x => x.Crystal)
.OfType<Crystal>()
.SelectMany(c => c.Faces);

var lightmaps = faces.SelectMany(f => f.Vertices.Select(v => v.LightmapCoord)).ToArray();

w.Write(lightmaps.Length);

if (Version == 0)
{
foreach (var lightmap in lightmaps)
{
w.Write(lightmap);
}
}

if (Version >= 1)
{
foreach (var lightmap in lightmaps)
{
w.Write((ushort)(lightmap.X * ushort.MaxValue));
w.Write((ushort)(lightmap.Y * ushort.MaxValue));
}

// subject to optimization due to IndexOf complexity
var indices = faces.SelectMany(f => f.Vertices.Select(v => Array.IndexOf(lightmaps, v.LightmapCoord))).ToArray();

w.WriteArrayOptimizedInt(indices);
}
}
}

[ArchiveGenerationOptions(StructureKind = StructureKind.SeparateReadAndWrite)]
public abstract partial class Layer;

Expand Down Expand Up @@ -343,7 +470,7 @@ public void Read(GbxReader r, CPlugCrystal n, int v = 0)
// this doesnt sound right
for (var j = 0; j < uvCount; j++)
{
vertices[j] = new Vertex(inds[j], TexCoord: r.ReadVec2());
vertices[j] = new Vertex(inds[j], TexCoord: r.ReadVec2(), default);
}

u01 = r.ReadVec3(); // normal?
Expand All @@ -352,14 +479,14 @@ public void Read(GbxReader r, CPlugCrystal n, int v = 0)
{
for (var j = 0; j < vertices.Length; j++)
{
vertices[j] = new Vertex(inds[j], TexCoord: r.ReadVec2());
vertices[j] = new Vertex(inds[j], TexCoord: r.ReadVec2(), default);
}
}
else
{
for (var j = 0; j < vertCount; j++)
{
vertices[j] = new Vertex(inds[j], TexCoord: texCoords[texCoordIndices[faceVertexIndex++]]);
vertices[j] = new Vertex(inds[j], TexCoord: texCoords[texCoordIndices[faceVertexIndex++]], default);
}
}

Expand Down Expand Up @@ -651,5 +778,5 @@ public void Write(GbxWriter w, CPlugCrystal n, int v = 0)

public sealed record Face(Vertex[] Vertices, Part Group, Material? Material, Vec3? U01);

public readonly record struct Vertex(int Index, Vec2 TexCoord);
public readonly record struct Vertex(int Index, Vec2 TexCoord, Vec2 LightmapCoord);
}

0 comments on commit c5f1962

Please sign in to comment.