Skip to content

Commit

Permalink
Refactor model IO (LostArtefacts#624)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 authored Apr 23, 2024
1 parent 559d370 commit 5733ee4
Show file tree
Hide file tree
Showing 21 changed files with 404 additions and 786 deletions.
264 changes: 264 additions & 0 deletions TRLevelControl/Build/TRModelBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
using System.Diagnostics;
using TRLevelControl.Model;

namespace TRLevelControl.Build;

public class TRModelBuilder
{
private static readonly ushort _tr5ModelPadding = 0xFFEF;

private readonly TRGameVersion _version;

public TRModelBuilder(TRGameVersion version)
{
_version = version;
}

public List<TRAnimation> ReadAnimations(TRLevelReader reader)
{
uint numAnimations = reader.ReadUInt32();
List<TRAnimation> animations = new();

for (int i = 0; i < numAnimations; i++)
{
TRAnimation animation = new()
{
FrameOffset = reader.ReadUInt32(),
FrameRate = reader.ReadByte(),
FrameSize = reader.ReadByte(),
StateID = reader.ReadUInt16(),
Speed = reader.ReadFixed32(),
Accel = reader.ReadFixed32(),
};

if (_version >= TRGameVersion.TR4)
{
animation.SpeedLateral = reader.ReadFixed32();
animation.AccelLateral = reader.ReadFixed32();
}

animation.FrameStart = reader.ReadUInt16();
animation.FrameEnd = reader.ReadUInt16();
animation.NextAnimation = reader.ReadUInt16();
animation.NextFrame = reader.ReadUInt16();
animation.NumStateChanges = reader.ReadUInt16();
animation.StateChangeOffset = reader.ReadUInt16();
animation.NumAnimCommands = reader.ReadUInt16();
animation.AnimCommand = reader.ReadUInt16();

animations.Add(animation);
}

return animations;
}

public void Write(List<TRAnimation> animations, TRLevelWriter writer)
{
writer.Write((uint)animations.Count);

foreach (TRAnimation animation in animations)
{
writer.Write(animation.FrameOffset);
writer.Write(animation.FrameRate);
writer.Write(animation.FrameSize);
writer.Write(animation.StateID);
writer.Write(animation.Speed);
writer.Write(animation.Accel);

if (_version >= TRGameVersion.TR4)
{
writer.Write(animation.SpeedLateral);
writer.Write(animation.AccelLateral);
}

writer.Write(animation.FrameStart);
writer.Write(animation.FrameEnd);
writer.Write(animation.NextAnimation);
writer.Write(animation.NextFrame);
writer.Write(animation.NumStateChanges);
writer.Write(animation.StateChangeOffset);
writer.Write(animation.NumAnimCommands);
writer.Write(animation.AnimCommand);
}
}

public List<TRStateChange> ReadStateChanges(TRLevelReader reader)
{
uint numStateChanges = reader.ReadUInt32();
List<TRStateChange> stateChanges = new();

for (int i = 0; i < numStateChanges; i++)
{
stateChanges.Add(new()
{
StateID = reader.ReadUInt16(),
NumAnimDispatches = reader.ReadUInt16(),
AnimDispatch = reader.ReadUInt16(),
});
}

return stateChanges;
}

public void Write(List<TRStateChange> stateChanges, TRLevelWriter writer)
{
writer.Write((uint)stateChanges.Count);

foreach (TRStateChange stateChange in stateChanges)
{
writer.Write(stateChange.StateID);
writer.Write(stateChange.NumAnimDispatches);
writer.Write(stateChange.AnimDispatch);
}
}

public List<TRAnimDispatch> ReadDispatches(TRLevelReader reader)
{
uint numAnimDispatches = reader.ReadUInt32();
List<TRAnimDispatch> dispatches = new();

for (int i = 0; i < numAnimDispatches; i++)
{
dispatches.Add(new()
{
Low = reader.ReadInt16(),
High = reader.ReadInt16(),
NextAnimation = reader.ReadInt16(),
NextFrame = reader.ReadInt16(),
});
}

return dispatches;
}

public void Write(List<TRAnimDispatch> dispatches, TRLevelWriter writer)
{
writer.Write((uint)dispatches.Count);

foreach (TRAnimDispatch dispatch in dispatches)
{
writer.Write(dispatch.Low);
writer.Write(dispatch.High);
writer.Write(dispatch.NextAnimation);
writer.Write(dispatch.NextFrame);
}
}

public List<TRAnimCommand> ReadCommands(TRLevelReader reader)
{
uint numAnimCommands = reader.ReadUInt32();
List<TRAnimCommand> commands = new();

for (int i = 0; i < numAnimCommands; i++)
{
commands.Add(new()
{
Value = reader.ReadInt16(),
});
}

return commands;
}

public void Write(List<TRAnimCommand> commands, TRLevelWriter writer)
{
writer.Write((uint)commands.Count);

foreach (TRAnimCommand command in commands)
{
writer.Write(command.Value);
}
}

public List<TRMeshTreeNode> ReadTrees(TRLevelReader reader)
{
uint numMeshTrees = reader.ReadUInt32() / sizeof(int);
List<TRMeshTreeNode> trees = new();

for (int i = 0; i < numMeshTrees; i++)
{
trees.Add(new()
{
Flags = reader.ReadUInt32(),
OffsetX = reader.ReadInt32(),
OffsetY = reader.ReadInt32(),
OffsetZ = reader.ReadInt32(),
});
}

return trees;
}

public void Write(List<TRMeshTreeNode> trees, TRLevelWriter writer)
{
writer.Write((uint)trees.Count * sizeof(int));

foreach (TRMeshTreeNode tree in trees)
{
writer.Write(tree.Flags);
writer.Write(tree.OffsetX);
writer.Write(tree.OffsetY);
writer.Write(tree.OffsetZ);
}
}

public List<ushort> ReadFrames(TRLevelReader reader)
{
uint numFrames = reader.ReadUInt32();
return new(reader.ReadUInt16s(numFrames));
}

public void Write(List<ushort> frames, TRLevelWriter writer)
{
writer.Write((uint)frames.Count);
writer.Write(frames);
}

public List<TRModel> ReadModels(TRLevelReader reader)
{
uint numModels = reader.ReadUInt32();
List<TRModel> models = new();

for (int i = 0; i < numModels; i++)
{
TRModel model = new()
{
ID = reader.ReadUInt32(),
NumMeshes = reader.ReadUInt16(),
StartingMesh = reader.ReadUInt16(),
MeshTree = reader.ReadUInt32(),
FrameOffset = reader.ReadUInt32(),
Animation = reader.ReadUInt16()
};

if (_version == TRGameVersion.TR5)
{
Debug.Assert(reader.ReadUInt16() == _tr5ModelPadding);
}

models.Add(model);
}

return models;
}

public void Write(List<TRModel> models, TRLevelWriter writer)
{
writer.Write((uint)models.Count);

foreach (TRModel model in models)
{
writer.Write(model.ID);
writer.Write(model.NumMeshes);
writer.Write(model.StartingMesh);
writer.Write(model.MeshTree);
writer.Write(model.FrameOffset);
writer.Write(model.Animation);

if (_version == TRGameVersion.TR5)
{
writer.Write(_tr5ModelPadding);
}
}
}
}
97 changes: 27 additions & 70 deletions TRLevelControl/Control/TR1LevelControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,61 +105,7 @@ protected override void Read(TRLevelReader reader)

ReadMeshData(reader);

//Animations
uint numAnimations = reader.ReadUInt32();
_level.Animations = new();
for (int i = 0; i < numAnimations; i++)
{
_level.Animations.Add(TR2FileReadUtilities.ReadAnimation(reader));
}

//State Changes
uint numStateChanges = reader.ReadUInt32();
_level.StateChanges = new();
for (int i = 0; i < numStateChanges; i++)
{
_level.StateChanges.Add(TR2FileReadUtilities.ReadStateChange(reader));
}

//Animation Dispatches
uint numAnimDispatches = reader.ReadUInt32();
_level.AnimDispatches = new();
for (int i = 0; i < numAnimDispatches; i++)
{
_level.AnimDispatches.Add(TR2FileReadUtilities.ReadAnimDispatch(reader));
}

//Animation Commands
uint numAnimCommands = reader.ReadUInt32();
_level.AnimCommands = new();
for (int i = 0; i < numAnimCommands; i++)
{
_level.AnimCommands.Add(TR2FileReadUtilities.ReadAnimCommand(reader));
}

//Mesh Trees
uint numMeshTrees = reader.ReadUInt32() / 4;
_level.MeshTrees = new();
for (int i = 0; i < numMeshTrees; i++)
{
_level.MeshTrees.Add(TR2FileReadUtilities.ReadMeshTreeNode(reader));
}

//Frames
uint numFrames = reader.ReadUInt32();
_level.Frames = new();
for (int i = 0; i < numFrames; i++)
{
_level.Frames.Add(reader.ReadUInt16());
}

//Models
uint numModels = reader.ReadUInt32();
_level.Models = new();
for (int i = 0; i < numModels; i++)
{
_level.Models.Add(TR2FileReadUtilities.ReadModel(reader));
}
ReadModelData(reader);

//Static Meshes
uint numStaticMeshes = reader.ReadUInt32();
Expand Down Expand Up @@ -264,21 +210,8 @@ protected override void Write(TRLevelWriter writer)

WriteMeshData(writer);

writer.Write((uint)_level.Animations.Count);
foreach (TRAnimation anim in _level.Animations) { writer.Write(anim.Serialize()); }
writer.Write((uint)_level.StateChanges.Count);
foreach (TRStateChange statec in _level.StateChanges) { writer.Write(statec.Serialize()); }
writer.Write((uint)_level.AnimDispatches.Count);
foreach (TRAnimDispatch dispatch in _level.AnimDispatches) { writer.Write(dispatch.Serialize()); }
writer.Write((uint)_level.AnimCommands.Count);
foreach (TRAnimCommand cmd in _level.AnimCommands) { writer.Write(cmd.Serialize()); }
writer.Write((uint)(_level.MeshTrees.Count * 4)); //To get the correct number /= 4 is done during read, make sure to reverse it here.
foreach (TRMeshTreeNode node in _level.MeshTrees) { writer.Write(node.Serialize()); }
writer.Write((uint)_level.Frames.Count);
foreach (ushort frame in _level.Frames) { writer.Write(frame); }

writer.Write((uint)_level.Models.Count);
foreach (TRModel model in _level.Models) { writer.Write(model.Serialize()); }
WriteModelData(writer);

writer.Write((uint)_level.StaticMeshes.Count);
foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); }

Expand Down Expand Up @@ -338,6 +271,30 @@ private void WriteMeshData(TRLevelWriter writer)
builder.WriteObjectMeshes(writer, _level.Meshes, _level.MeshPointers);
}

private void ReadModelData(TRLevelReader reader)
{
TRModelBuilder builder = new(TRGameVersion.TR1);
_level.Animations = builder.ReadAnimations(reader);
_level.StateChanges = builder.ReadStateChanges(reader);
_level.AnimDispatches = builder.ReadDispatches(reader);
_level.AnimCommands = builder.ReadCommands(reader);
_level.MeshTrees = builder.ReadTrees(reader);
_level.Frames = builder.ReadFrames(reader);
_level.Models = builder.ReadModels(reader);
}

private void WriteModelData(TRLevelWriter writer)
{
TRModelBuilder builder = new(TRGameVersion.TR1);
builder.Write(_level.Animations, writer);
builder.Write(_level.StateChanges, writer);
builder.Write(_level.AnimDispatches, writer);
builder.Write(_level.AnimCommands, writer);
builder.Write(_level.MeshTrees, writer);
builder.Write(_level.Frames, writer);
builder.Write(_level.Models, writer);
}

private static TRRoomData ConvertToRoomData(TRRoom room)
{
int RoomDataOffset = 0;
Expand Down
Loading

0 comments on commit 5733ee4

Please sign in to comment.