forked from Radfordhound/HedgeLib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GensTerrainGroup.cs
138 lines (112 loc) · 4.92 KB
/
GensTerrainGroup.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using HedgeLib.Headers;
using HedgeLib.IO;
using System.IO;
namespace HedgeLib.Terrain
{
// Based off of the wonderful SCHG page on Sonic Generations over at Sonic Retro
public class GensTerrainGroup : FileBase
{
// Variables/Constants
public InstanceInfoEntry[] InstanceInfos;
public string[] TerrainModels;
public GensHeader Header = new GensHeader();
public const string Extension = ".terrain-group";
// Methods
public override void Load(Stream fileStream)
{
// Header
var reader = new GensReader(fileStream, true);
Header = new GensHeader(reader);
// Root Node
uint instanceInfoCount = reader.ReadUInt32();
uint instanceInfoOffsetsOffset = reader.ReadUInt32();
uint terrainModelCount = reader.ReadUInt32();
uint terrainModelOffsetsOffset = reader.ReadUInt32();
// Instance Infos
InstanceInfos = new InstanceInfoEntry[instanceInfoCount];
reader.JumpTo(instanceInfoOffsetsOffset, false);
for (uint i = 0; i < instanceInfoCount; ++i)
{
var instanceInfo = new InstanceInfoEntry();
uint instanceInfoOffset = reader.ReadUInt32();
long curPos = reader.BaseStream.Position;
reader.JumpTo(instanceInfoOffset, false);
uint fileNameCount = reader.ReadUInt32();
uint fileNameOffsetsOffset = reader.ReadUInt32();
uint boundingSphereOffset = reader.ReadUInt32();
reader.JumpTo(fileNameOffsetsOffset, false);
// File Names
instanceInfo.FileNames = new string[fileNameCount];
for (uint i2 = 0; i2 < fileNameCount; ++i2)
{
instanceInfo.FileNames[i2] = reader.GetString();
}
// Bounding Sphere
reader.JumpTo(boundingSphereOffset, false);
instanceInfo.BoundingSphereCenter = reader.ReadVector3();
instanceInfo.BoundingSphereRadius = reader.ReadSingle();
InstanceInfos[i] = instanceInfo;
reader.BaseStream.Position = curPos;
}
// Terrain Models
TerrainModels = new string[terrainModelCount];
reader.JumpTo(terrainModelOffsetsOffset, false);
for (uint i = 0; i < terrainModelCount; ++i)
{
TerrainModels[i] = reader.GetString();
}
}
public override void Save(Stream fileStream)
{
// Header
var writer = new GensWriter(fileStream, Header);
// Root Node
writer.Write(InstanceInfos.Length);
writer.AddOffset("instanceInfoOffsetsOffset");
writer.Write(TerrainModels.Length);
writer.AddOffset("terrainModelOffsetsOffset");
// Instance Infos
writer.FillInOffset("instanceInfoOffsetsOffset", false);
writer.AddOffsetTable("instanceInfoOffset", (uint)InstanceInfos.Length);
for (int i = 0; i < InstanceInfos.Length; ++i)
{
var instanceInfo = InstanceInfos[i];
writer.FillInOffset("instanceInfoOffset_" + i, false);
writer.Write(instanceInfo.FileNames.Length);
writer.AddOffset("fileNameOffsetOffset");
writer.AddOffset("boundingSphereOffset");
// File Names
writer.FillInOffset("fileNameOffsetOffset", false);
writer.AddOffsetTable("fileNameOffset",
(uint)instanceInfo.FileNames.Length);
for (int i2 = 0; i2 < instanceInfo.FileNames.Length; ++i2)
{
writer.FillInOffset($"fileNameOffset_{i2}", false);
writer.WriteNullTerminatedString(instanceInfo.FileNames[i2]);
writer.FixPadding(4);
}
// Bounding Sphere
writer.FillInOffset("boundingSphereOffset", false);
writer.Write(instanceInfo.BoundingSphereCenter);
writer.Write(instanceInfo.BoundingSphereRadius);
}
// Terrain Models
writer.FillInOffset("terrainModelOffsetsOffset", false);
writer.AddOffsetTable("terrainModelOffset", (uint)TerrainModels.Length);
for (int i = 0; i < TerrainModels.Length; ++i)
{
writer.FillInOffset($"terrainModelOffset_{i}", false);
writer.WriteNullTerminatedString(TerrainModels[i]);
writer.FixPadding(4);
}
writer.FinishWrite(Header);
}
// Other
public struct InstanceInfoEntry
{
public string[] FileNames;
public Vector3 BoundingSphereCenter;
public float BoundingSphereRadius;
}
}
}