-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhlbsp.zig
220 lines (198 loc) · 5.85 KB
/
hlbsp.zig
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// Reference: https://hlbsp.sourceforge.net/index.php?content=bspdef
const std = @import("std");
comptime {
if (@import("builtin").cpu.arch.endian() != .Little)
@compileError("little-endian only");
}
/// bsp file header
/// only use as a pointer !
pub const Header = extern struct {
const Self = @This();
version: u32,
entities: Lump,
planes: Lump,
textures: Lump,
vertices: Lump,
visibility: Lump,
nodes: Lump,
texinfos: Lump,
faces: Lump,
lighting: Lump,
clipnodes: Lump,
leaves: Lump,
marksurfaces: Lump,
edges: Lump,
surfedges: Lump,
models: Lump,
pub fn fromBytes(bytes: anytype) *align(1) const Self {
return @alignCast(@ptrCast(bytes));
}
pub fn getLumpArr(self: *align(1) const Self, lump: Lump, comptime T: type) []align(1) const T {
const many: [*]align(1) const T = @ptrCast(self.getLumpPtr(lump, T));
return many[0 .. lump.length / @sizeOf(T)];
}
pub fn getLumpPtr(self: *align(1) const Self, lump: Lump, comptime T: type) *align(1) const T {
const bytes: [*]const u8 = @ptrCast(self);
return @ptrCast(bytes + lump.offset);
}
pub fn getLumpBytes(self: *align(1) const Self, lump: Lump) []const u8 {
const bytes: [*]const u8 = @ptrCast(self);
return bytes[lump.offset..][0..lump.length];
}
};
pub const Lump = extern struct {
offset: u32,
length: u32,
};
/// lump 0 entities: []u8
pub const EntityLump = @compileError("ascii text");
pub const vec3 = [3]f32;
/// lump 1 planes: []Plane
pub const Plane = extern struct {
normal: vec3,
dist: f32,
type: i32,
};
/// lump 2 textures: TextureLump
/// only use as a pointer !
pub const TextureLump = extern struct {
const Self = @This();
count: u32,
pub fn getOffsets(self: *align(1) const Self) []align(1) const u32 {
const p: [*]const u8 = @ptrCast(self);
const a: [*]align(1) const u32 = @ptrCast(p + @sizeOf(@This()));
return a[0..self.count];
}
pub fn getMipTex(self: *align(1) const Self, off: u32) *align(1) const MipTex {
const p: [*]const u8 = @ptrCast(self);
return @ptrCast(p + off);
}
};
/// only use as a pointer !
pub const MipTex = extern struct {
_name: [16]u8,
width: u32,
height: u32,
offsets: [4]u32,
pub fn getName(self: *align(1) const @This()) []const u8 {
if (std.mem.indexOfScalar(u8, &self._name, 0)) |i|
return self._name[0..i];
return &self._name;
}
pub fn getColors(self: *align(1) const @This()) *const [256][3]u8 {
const miptex: [*]const u8 = @ptrCast(self);
const offs_3 = self.offsets[3];
const lens_3 = self.width * self.height >> 6;
return @ptrCast(miptex + offs_3 + lens_3 + 2);
}
pub fn getTexture(self: *align(1) const @This(), level: u2) Texture {
const miptex: [*]const u8 = @ptrCast(self);
const width = self.width >> level;
const height = self.height >> level;
const offset = self.offsets[level];
return .{
.width = width,
.height = height,
.pixels = miptex[offset..][0 .. width * height],
};
}
};
pub const Texture = struct {
width: u32,
height: u32,
pixels: []const u8,
};
/// lump 3 vertices: []vec3
pub const VertexLump = vec3;
/// lump 4 visibility
pub const VisLump = @compileError("see reference");
/// lump 5 nodes: []Node
pub const Node = extern struct {
iPlane: u32,
iChildren: [2]i16, // if neg: ~i is index into leaf
mins: [3]i16,
maxs: [3]i16,
iFace0: u16,
nFaces: u16,
};
/// lump 6 texinfo: []TexInfo
pub const TexInfo = extern struct {
const Self = @This();
vS: vec3,
fSShift: f32,
vT: vec3,
fTShift: f32,
iMipTex: u32,
flags: u32,
pub fn calcST(self: Self, vtx: vec3, w: u32, h: u32) [2]f32 {
return .{
(vtx[0] * self.vS[0] + vtx[1] * self.vS[1] + vtx[2] * self.vS[2] + self.fSShift) / @as(f32, @floatFromInt(w)),
(vtx[0] * self.vT[0] + vtx[1] * self.vT[1] + vtx[2] * self.vT[2] + self.fTShift) / @as(f32, @floatFromInt(h)),
};
}
};
/// lump 7 faces: []Face
pub const Face = extern struct {
iPlane: u16,
iPSide: u16, // 0 - front, 1 - back
iEdge0: u32, // surfedge
nEdges: u16, // surfedge
iTexInfo: u16,
styles: [4]u8,
lightmapOffset: u32,
};
/// lump 8 lighting
pub const LightmapLump = @compileError("array of rgb ([3]u8)");
/// lump 9 clipnodes: []ClipNode
pub const ClipNode = extern struct {
iPlane: u32,
iChildren: [2]i16, // if neg: content
};
pub const Contents = struct {
pub const EMPTY = -1;
pub const SOLID = -2;
pub const WATER = -3;
pub const SLIME = -4;
pub const LAVA = -5;
pub const SKY = -6;
pub const ORIGIN = -7;
pub const CLIP = -8;
pub const CURRENT_0 = -9;
pub const CURRENT_90 = -10;
pub const CURRENT_180 = -11;
pub const CURRENT_270 = -12;
pub const CURRENT_UP = -13;
pub const CURRENT_DOWN = -14;
pub const TRANSLUCENT = -15;
};
/// lump 10 leaves
pub const Leaf = extern struct {
contents: i32,
visOffset: u32,
mins: [3]i16,
maxs: [3]i16,
iMarkSurface0: u16,
nMarkSurfaces: u16,
ambientLevels: [4]u8,
};
/// lump 11 marksurfaces
pub const MarkSurfaces = @compileError("u16 index into face");
/// lump 12 edges
/// two indices into vertex
pub const Edge = [2]u16;
/// lump 13 edges: i32 index into edge, if neg: -i is index, reversed
pub const SurfEdge = i32;
/// lump 14 models
pub const Model = extern struct {
mins: vec3,
maxs: vec3,
origin: vec3,
/// 0 - render
/// 1 - [-16, -16, -36] - [+16, +16, +36] : 32x32x72 standing;
/// 2 - [-32, -32, -32] - [+32, +32, +32] : 64x64x64 big;
/// 3 - [-16, -16, -18] - [+16, +16, +18] : 32x32x36 crouched;
iHeadnodes: [4]i32,
nVisLeafs: u32,
iFace0: u32,
nFaces: u32,
};