-
Notifications
You must be signed in to change notification settings - Fork 0
/
q3bsploader.h
325 lines (274 loc) · 8.72 KB
/
q3bsploader.h
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#ifndef j7Q3BSPLoader_hpp
#define j7Q3BSPLoader_hpp
#include <string> // std::string
#include <array> // std::array
#include <vector> // std::vector
#include <unordered_map> // std::map
#include <SFML/OpenGL.hpp> // OpenGL datatypes
#include <glm/glm.hpp> // glm::fvec3, glm::mat2, normalize, rotate, transform, scale
const std::string IDENT = "IBSP";
#define IBSP_VERSION 46
#define TESSELLATION_LEVEL 12
#define HEADER_LUMPS 17
#define LIGHTMAP_RESOLUTION 128 // RTCW might use larger lightmaps?
typedef struct {
int offset;
int length;
} dirEntry;
typedef struct {
char magicNumber[4];
int version;
dirEntry direntries[HEADER_LUMPS];
} BSPHeader;
// Lump 0
class BSPEntity {
public:
std::unordered_map<std::string, std::string> pair;
BSPEntity(std::string clause) { // Takes a single clause (within {} braces) and populates a vector of type/value pairs
size_t open = clause.find_first_of('"', 0);
size_t close = 0;
std::string type, value;
while (open != std::string::npos) {
++open; // Skip past the opening quotation mark. Cannot do during assignment as it borks the if(npos) check
close = clause.find('"', open); // First match is type
type = clause.substr(open, close - open);
open = clause.find('"', close + 1) + 1;
close = clause.find('"', open); // Second match is value
value = clause.substr(open, close - open);
pair[type] = value;
open = clause.find_first_of('"', close + 1); // Go around for next line
}
}
glm::fvec3 getVector(const std::string type) {
glm::fvec3 temp;
if (type != "origin" && type != "_color") return temp;
std::string token = pair[type];
if (token == "") return temp;
const float normalizer = (type == "_color") ? 1.0f : 255.0f; // colors need to be normalized
size_t offset = 0;
for (int i = 0; i < 3; ++i) {
temp[i] = std::stof(token, &offset) / normalizer;
token = token.substr(offset);
}
return temp;
}
};
class camPos {
public:
glm::vec3 origin;
float angle;
camPos(BSPEntity input) {
if (input.pair["classname"] != "info_player_deathmatch") return; // Not a spawnpoint
origin = input.getVector("origin");
angle = glm::radians(std::stof(input.pair["angle"]) + 90); // Why 90 (or -270)? is it because of swizzling?
}
};
class lightPos {
public:
glm::fvec3 origin;
glm::fvec3 _color;
float light; //brightness?
//target (ex: t6 - this is defined by the "target_position" classname)
//spawnflags
//radius
lightPos(BSPEntity input) {
if (input.pair["classname"] != "light") return; // Not a light
origin = input.getVector("origin");
_color = input.getVector("_color");
light = std::stof(input.pair["light"]);
}
};
typedef struct
{
char name[64];
int flags;
int contents;
} BSPTexture; // Lump 1
typedef struct {
glm::vec3 normal;
float distance;
} BSPPlane; // Lump 2
typedef struct {
int plane;
int children[2];
int mins[3];
int maxs[3];
} BSPNode; // Lump 3
typedef struct {
int cluster; //Visdata cluster index.
int area; //Areaportal area.
int mins[3]; //Integer bounding box min coord.
int maxs[3]; //Integer bounding box max coord.
int leafface; //First leafface for leaf.
int n_leaffaces; //Number of leaffaces for leaf.
int leafbrush; //First leafbrush for leaf.
int n_leafbrushes; //Number of leafbrushes for leaf.
} BSPLeaf; // Lump 4
// Lump 5: LeafFace (standard data type)
// Lump 6: LeafBrush (standard data type)
typedef struct {
float mins[3]; //Bounding box min coord.
float maxs[3]; //Bounding box max coord.
int face; //First face for model.
int n_faces; //Number of faces for model.
int brush; //First brush for model.
int n_brushes; //Number of brushes for model.
} BSPModel; // Lump 7
typedef struct {
int brushside; // First brushside for brush.
int n_brushsides; // Number of brushsides for brush.
int texture; // Texture index.
} BSPBrush; // Lump 8
typedef struct {
int plane; // Plane index.
int texture; // Texture index.
} BSPBrushSide; // Lump 9
// Lump 10
class BSPVertex
{
public:
// Members must be in this order as contents are memcpy'd into them from the binary
glm::fvec3 position;
glm::fvec2 texcoord;
glm::fvec2 lmcoord;
glm::fvec3 normal;
std::array<unsigned char, 4> color; //vertex color, in RGBA, as unsigned.
// Basic vector math
BSPVertex operator+(BSPVertex a) {
BSPVertex temp;
temp.position = this->position + a.position;
temp.normal = this->normal + a.normal;
temp.texcoord = this->texcoord + a.texcoord;
temp.lmcoord = this->lmcoord + a.lmcoord;
temp.color = this->color;
return temp;
}
BSPVertex operator*(float a) {
BSPVertex temp;
temp.position = this->position * a;
temp.normal = this->normal * a;
temp.texcoord = this->texcoord * a;
temp.lmcoord = this->lmcoord * a;
temp.color = this->color;
return temp;
}
};
// Lump 11: MeshVerts (standard data type)
typedef struct {
char name[64];
int brush;
int unknown; // Always 5, except in q3dm8, which has one effect with -1.
} BSPEffect; // Lump 12
typedef struct
{
int texture; //Texture index.
int effect; //Index into lump 12 (Effects), or -1.
int type; //Face type. 1=polygon, 2=patch, 3=mesh, 4=billboard.
int vertex; //Index of first vertex.
int n_vertexes; //Number of vertices.
int meshvert; //Index of first mesh vertex.
int n_meshverts; //Number of meshverts.
int lm_index; //Lightmap index.
int lm_start[2]; //Corner of this face's lightmap image in lightmap.
int lm_size[2]; //Size of this face's lightmap image in lightmap.
float lm_origin[3]; //World space origin of lightmap.
float lm_vecs[2][3]; //World space lightmap s and t unit vectors.
float normal[3]; //Surface normal.
int size[2]; //Patch dimensions. 0=width, 1=height.
} BSPFace; // Lump 13
class j7Bezier {
public:
std::array<BSPVertex,9> controls;
void tessellate(int level);
//private:
std::vector<BSPVertex> vertex;
std::vector<GLuint> indices;
};
class q3BSP;
class BSPPatch {
public:
BSPPatch(const q3BSP *bsp, const unsigned face);
BSPPatch() { }
GLsizei n_indices;
GLint offset;
GLuint start;
std::vector<GLuint> indices;
std::vector<BSPVertex> vertices;
};
typedef struct {
int n_vecs;
int sz_vecs;
std::vector<unsigned char> vecs;
} BSPVisData; // Lump 16
class q3BSP {
public:
enum LUMPNAMES {
Entities = 0,
Textures, //LUMP_SHADERS
Planes,
Nodes,
Leafs,
Leaffaces, //LUMP_LEAFSURFACES
Leafbrushes,
Models,
Brushes,
Brushsides,
Vertexes, //LUMP_DRAWVERTS
Meshverts, //LUMP_DRAWINDEXES
Effects, //LUMP_FOGS
Faces, //LUMP_SURFACES
Lightmaps,
Lightvols, //LUMP_LIGHTGRID
Visdata //LUMP_VISIBILITY
};
enum SURFACETYPES {
SURF_BAD=0,
SURF_POLY,
SURF_PATCH,
SURF_MODEL
};
q3BSP(std::string filename);
//private:
// Raw data from the BSP file
std::vector<BSPEntity> entities; // Lump 0
std::vector<BSPTexture> textures; // Lump 1
std::vector<BSPPlane> planes; // Lump 2
std::vector<BSPNode> nodes; // Lump 3
std::vector<BSPLeaf> leafs; // Lump 4
std::vector<int> leafFaces; // Lump 5
std::vector<int> leafBrushes; // Lump 6
std::vector<BSPModel> models; // Lump 7
std::vector<BSPBrush> brushes; // Lump 8
std::vector<BSPBrushSide> brushSides; // Lump 9
std::vector<BSPVertex> vertices; // Lump 10
std::vector<int> meshVerts; // Lump 11
std::vector<BSPEffect> effects; // Lump 12
std::vector<BSPFace> faces; // Lump 13
// Lump 15
BSPVisData visData; // Lump 16
// Functions for parsing BSP data and the processed data
// Lump 0
void parseEntities(const std::string *entities); // Take raw string of entities and make a vector of clauses
std::string worldMusic; // Music for the level ::TODO:: Intro music is not played
std::vector<camPos> cameraPositions; // Spawnpoints
std::vector<lightPos> lightPositions; // Lights
// Lump 1
std::vector<GLuint> textureIDs;
GLint texSamplerPos;
//Lump 4
int findCurrentLeaf(const glm::vec3 position) const; // Finds what leaf the given position is in
bool isClusterVisible(const int visCluster, const int testCluster) const; // Determines if testCluster is visible from visCluster
//Lump 13
std::vector<int> makeListofVisibleFaces(const glm::vec3 position, const glm::mat4 viewmatrix) const; // Generates a list of faces visible from position
std::vector<std::vector<BSPFace>> facesByTexture; // All of the faces grouped by texture
std::vector<BSPPatch> patches; // Contains the tessellated faces
//Lump 14
GLuint bindLightmaps(std::vector<std::array<std::array<std::array<char, 3>, LIGHTMAP_RESOLUTION>, LIGHTMAP_RESOLUTION>> lightmaps);
GLint lmSamplerPos;
GLint lightmapIndexUniformPosition;
GLuint lightmapGLID;
//Shaders
void parseShader(const std::string shadername);
};
GLuint makeVAO(const std::vector<BSPVertex> *vertices, const std::vector<GLuint> *indices);
#endif