Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor packages #52

Merged
merged 7 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
508 changes: 0 additions & 508 deletions src/ThreeDModels/Format/Ctm/CtmReader.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ThreeDModels.Format.Ctm;
namespace ThreeDModels.Format.Ctm.Elements;

public enum CompressionMethod
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ThreeDModels.Format.Ctm;
namespace ThreeDModels.Format.Ctm.IO;

public static class Constants
{
Expand Down
81 changes: 81 additions & 0 deletions src/ThreeDModels/Format/Ctm/IO/CtmReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using SevenZip.Compression.LZMA;
using ThreeDModels.Format.Ctm.Elements;

namespace ThreeDModels.Format.Ctm.IO;

public class CtmReader
{
public Ctm Execute(string path)
{
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
return Execute(fs);
}

public Ctm Execute(Stream stream)
{
using var reader = new BinaryReader(stream);
if (reader.ReadInt32() != Identifier.Magic)
{
throw new InvalidDataException("Invalid magic identifier");
}
if (reader.ReadInt32() > Constants.Version)
{
throw new InvalidDataException("Unsupported version");
}
var method = (CompressionMethod)reader.ReadInt32();
var ctm = new Ctm()
{
CompressionMethod = method,
};
var verticesCount = reader.ReadInt32();
var trianglesCount = reader.ReadInt32();
var uvMapsCount = reader.ReadInt32();
var attributeMapsCount = reader.ReadInt32();
ctm.Vertices = new List<Vertex>(verticesCount);
ctm.Triangles = new List<Triangle>(trianglesCount);
ctm.UvMaps = new List<UvMap>(uvMapsCount);
ctm.AttributeMaps = new List<AttributeMap>(attributeMapsCount);
ctm.Flags = reader.ReadInt32();
ctm.Comment = ReadString(reader);
switch (method)
{
case CompressionMethod.RAW:
{
RawReader.Read(reader, verticesCount, trianglesCount, uvMapsCount, attributeMapsCount, ref ctm);
break;
}
case CompressionMethod.MG1:
{
Mg1Reader.Read(reader, verticesCount, trianglesCount, uvMapsCount, attributeMapsCount, ref ctm);
break;
}
case CompressionMethod.MG2:
{
Mg2Reader.Read(reader, verticesCount, trianglesCount, uvMapsCount, attributeMapsCount, ref ctm);
break;
}
default:
{
throw new InvalidDataException($"Unsupported compression method {method}");
}
}
return ctm;
}

internal static Stream UnpackLzmaStream(BinaryReader reader, int unpackedSize)
{
var packedSize = reader.ReadInt32();
var ms = new MemoryStream(unpackedSize);
Decoder decoder = new();
decoder.SetDecoderProperties(reader.ReadBytes(Constants.PackedDataPropsSize));
decoder.Code(reader.BaseStream, ms, packedSize, unpackedSize, null);
ms.Position = 0;
return ms;
}

internal static string ReadString(BinaryReader reader)
{
var length = reader.ReadInt32();
return new string(reader.ReadChars(length));
}
}
11 changes: 11 additions & 0 deletions src/ThreeDModels/Format/Ctm/IO/Data3D.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ThreeDModels.Format.Ctm.IO;

/// <summary>
/// Represents data about a 3D-axial reference.
/// </summary>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="Z"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
internal record Data3D<T>(T X, T Y, T Z);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ThreeDModels.Format.Ctm;
namespace ThreeDModels.Format.Ctm.IO;

public static class Flag
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ThreeDModels.Format.Ctm;
namespace ThreeDModels.Format.Ctm.IO;

public static class Identifier
{
Expand Down
185 changes: 185 additions & 0 deletions src/ThreeDModels/Format/Ctm/IO/Mg1Reader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
using ThreeDModels.Format.Ctm.Elements;

namespace ThreeDModels.Format.Ctm.IO;

internal static class Mg1Reader
{
internal static void Read(BinaryReader reader, int verticesCount, int trianglesCount, int uvMapsCount, int attributeMapsCount, ref Ctm ctm)
{
ReadTriangles(reader, trianglesCount, ref ctm);
ReadVertices(reader, verticesCount, ref ctm);
ReadVertexNormals(reader, verticesCount, ref ctm);
ReadUvMaps(reader, uvMapsCount, verticesCount, ref ctm);
ReadAttributeMaps(reader, attributeMapsCount, verticesCount, ref ctm);
}

private static void ReadTriangles(BinaryReader reader, int trianglesCount, ref Ctm ctm)
{
if (trianglesCount > 0 && reader.ReadInt32() != Identifier.Indices)
{
throw new InvalidDataException("Invalid indices section");
}
using var trianglesReader = new BinaryReader(CtmReader.UnpackLzmaStream(reader, trianglesCount * 3 * sizeof(int)));
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < trianglesCount; j++)
{
var deltaIndex = trianglesReader.ReadInt32();
if (i == 0)
{
ctm.Triangles.Add(new Triangle()
{
Vertex1 = j > 0 ? deltaIndex + ctm.Triangles[j - 1].Vertex1 : deltaIndex,
Vertex2 = 0,
Vertex3 = 0,
});
}
else if (i == 1)
{
ctm.Triangles[j].Vertex2 = j > 0 && ctm.Triangles[j].Vertex1 == ctm.Triangles[j - 1].Vertex1 ? deltaIndex + ctm.Triangles[j - 1].Vertex2 : deltaIndex + ctm.Triangles[j].Vertex1;
}
else
{
ctm.Triangles[j].Vertex3 = deltaIndex + ctm.Triangles[j].Vertex1;
}
}
}
}

private static void ReadVertices(BinaryReader reader, int verticesCount, ref Ctm ctm)
{
if (verticesCount > 0 && reader.ReadInt32() != Identifier.Vertices)
{
throw new InvalidDataException("Invalid vertices section");
}
using var verticesReader = new BinaryReader(CtmReader.UnpackLzmaStream(reader, verticesCount * 3 * sizeof(float)));
for (var i = 0; i < verticesCount; i++)
{
ctm.Vertices.Add(new Vertex()
{
X = verticesReader.ReadSingle(),
Y = verticesReader.ReadSingle(),
Z = verticesReader.ReadSingle(),
});
}
}

private static void ReadVertexNormals(BinaryReader reader, int verticesCount, ref Ctm ctm)
{
if ((ctm.Flags & Flag.HasNormals) == Flag.HasNormals)
{
if (verticesCount > 0 && reader.ReadInt32() != Identifier.Normals)
{
throw new InvalidDataException("Invalid normals section");
}
using var normalsReader = new BinaryReader(CtmReader.UnpackLzmaStream(reader, verticesCount * 3 * sizeof(float)));
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < verticesCount; j++)
{
if (i == 0)
{
ctm.Vertices[j].Normal = new Normal()
{
X = normalsReader.ReadSingle(),
Y = 0,
Z = 0,
};
}
else if (i == 1)
{
ctm.Vertices[j].Normal!.Y = normalsReader.ReadSingle();
}
else
{
ctm.Vertices[j].Normal!.Z = normalsReader.ReadSingle();
}

}
}
}
}

private static void ReadUvMaps(BinaryReader reader, int uvMapsCount, int verticesCount, ref Ctm ctm)
{
for (var i = 0; i < uvMapsCount; i++)
{
if (reader.ReadInt32() != Identifier.UVMaps)
{
throw new InvalidDataException("Invalid uv maps section");
}
var uvMap = new UvMap()
{
Name = CtmReader.ReadString(reader),
Filename = CtmReader.ReadString(reader),
Coordinates = new List<UvCoordinate>(verticesCount),
};
using var uvCoordinatesReader = new BinaryReader(CtmReader.UnpackLzmaStream(reader, verticesCount * 2 * sizeof(float)));
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < verticesCount; k++)
{
if (j == 0)
{
uvMap.Coordinates.Add(new UvCoordinate()
{
U = uvCoordinatesReader.ReadSingle(),
V = 0,
});
}
else
{
uvMap.Coordinates[k].V = uvCoordinatesReader.ReadSingle();
}
}
}
ctm.UvMaps.Add(uvMap);
}
}

private static void ReadAttributeMaps(BinaryReader reader, int attributeMapsCount, int verticesCount, ref Ctm ctm)
{
for (var i = 0; i < attributeMapsCount; i++)
{
if (reader.ReadInt32() != Identifier.AttributeMaps)
{
throw new InvalidDataException("Invalid attribute maps section");
}
var attributeMap = new AttributeMap()
{
Name = CtmReader.ReadString(reader),
Values = new List<AttributeValue>(verticesCount),
};
using var attributeValuesReader = new BinaryReader(CtmReader.UnpackLzmaStream(reader, verticesCount * 4 * sizeof(float)));
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < verticesCount; k++)
{
if (j == 0)
{
attributeMap.Values.Add(new AttributeValue()
{
A = attributeValuesReader.ReadSingle(),
B = 0,
C = 0,
D = 0,
});
}
else if (j == 1)
{
attributeMap.Values[k].B = attributeValuesReader.ReadSingle();
}
else if (j == 2)
{
attributeMap.Values[k].C = attributeValuesReader.ReadSingle();
}
else
{
attributeMap.Values[k].D = attributeValuesReader.ReadSingle();
}
}
}
ctm.AttributeMaps.Add(attributeMap);
}
}
}
3 changes: 3 additions & 0 deletions src/ThreeDModels/Format/Ctm/IO/Mg2Header.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace ThreeDModels.Format.Ctm.IO;

internal record Mg2Header(float VertexPrecision, float NormalPrecision, Data3D<float> LowerBoundCoordinates, Data3D<float> UpperBoundCoordinates, Data3D<int> GridDivisions);
Loading
Loading