UFO: Alien Invasion
Doxygen documentation generating
r_model_brush.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 #include "r_lightmap.h"
28 #include "../../shared/parse.h"
29 #include "r_light.h"
30 #include "r_grass.h"
31 
32 /*
33 ===============================================================================
34 BRUSHMODEL LOADING
35 ===============================================================================
36 */
37 
41 static const byte* mod_base;
46 static ipos3_t shift;
52 
56 static void R_ModLoadLighting (const lump_t* l)
57 {
58  /* map has no lightmap */
59  if (l->filelen == 0)
60  return;
61 
63  r_worldmodel->bsp.lightquant = *(const byte*) (mod_base + l->fileofs);
64  memcpy(r_worldmodel->bsp.lightdata, mod_base + l->fileofs, l->filelen);
65 }
66 
67 static void R_ModLoadVertexes (const lump_t* l)
68 {
69  const dBspVertex_t* in = (const dBspVertex_t*) (mod_base + l->fileofs);
70  if (l->filelen % sizeof(*in))
71  Com_Error(ERR_DROP, "R_ModLoadVertexes: funny lump size in %s", r_worldmodel->name);
72 
73  int count = l->filelen / sizeof(*in);
75  Com_DPrintf(DEBUG_RENDERER, "...verts: %i\n", count);
76 
77  r_worldmodel->bsp.vertexes = out;
79 
80  for (int i = 0; i < count; i++, in++, out++) {
81  out->position[0] = LittleFloat(in->point[0]);
82  out->position[1] = LittleFloat(in->point[1]);
83  out->position[2] = LittleFloat(in->point[2]);
84  }
85 }
86 
87 static void R_ModLoadNormals (const lump_t* l)
88 {
89  const dBspNormal_t* in = (const dBspNormal_t*)(mod_base + l->fileofs);
90  if (l->filelen % sizeof(*in)) {
91  Com_Error(ERR_DROP, "R_LoadNormals: Funny lump size in %s.", r_worldmodel->name);
92  }
93  int count = l->filelen / sizeof(*in);
94 
95  if (count != r_worldmodel->bsp.numvertexes) { /* ensure sane normals count */
96  Com_Error(ERR_DROP, "R_LoadNormals: unexpected normals count in %s: (%d != %d).",
98  }
99 
101 
102  for (int i = 0; i < count; i++, in++, out++) {
103  out->normal[0] = LittleFloat(in->normal[0]);
104  out->normal[1] = LittleFloat(in->normal[1]);
105  out->normal[2] = LittleFloat(in->normal[2]);
106  }
107 }
108 
109 static inline float R_RadiusFromBounds (const vec3_t mins, const vec3_t maxs)
110 {
111  vec3_t corner;
112 
113  for (int i = 0; i < 3; i++)
114  corner[i] = fabsf(mins[i]) > fabsf(maxs[i]) ? fabsf(mins[i]) : fabsf(maxs[i]);
115 
116  return VectorLength(corner);
117 }
118 
119 
124 static void R_ModLoadSubmodels (const lump_t* l)
125 {
126  const dBspModel_t* in = (const dBspModel_t*) (mod_base + l->fileofs);
127  if (l->filelen % sizeof(*in))
128  Com_Error(ERR_DROP, "R_ModLoadSubmodels: funny lump size in %s", r_worldmodel->name);
129 
130  int count = l->filelen / sizeof(*in);
132  Com_DPrintf(DEBUG_RENDERER, "...submodels: %i\n", count);
133 
134  r_worldmodel->bsp.submodels = out;
136 
137  for (int i = 0; i < count; i++, in++, out++) {
138  /* spread the mins / maxs by a pixel */
139  for (int j = 0; j < 3; j++) {
140  out->hBox.mins[j] = LittleFloat(in->dbmBox.mins[j]) - 1.0f + (float)shift[j];
141  out->hBox.maxs[j] = LittleFloat(in->dbmBox.maxs[j]) + 1.0f + (float)shift[j];
142  out->origin[j] = LittleFloat(in->origin[j]) + (float)shift[j];
143  }
144  out->radius = R_RadiusFromBounds(out->hBox.mins, out->hBox.maxs);
145  out->headnode = LittleLong(in->headnode);
146  out->firstface = LittleLong(in->firstface);
147  out->numfaces = LittleLong(in->numfaces);
148  }
149 }
150 
151 static void R_ModLoadEdges (const lump_t* l)
152 {
153  const dBspEdge_t* in = (const dBspEdge_t*) (mod_base + l->fileofs);
154  if (l->filelen % sizeof(*in))
155  Com_Error(ERR_DROP, "R_ModLoadEdges: funny lump size in %s", r_worldmodel->name);
156 
157  int count = l->filelen / sizeof(*in);
159  Com_DPrintf(DEBUG_RENDERER, "...edges: %i\n", count);
160 
161  r_worldmodel->bsp.edges = out;
163 
164  for (int i = 0; i < count; i++, in++, out++) {
165  out->v[0] = (unsigned short) LittleShort(in->v[0]);
166  out->v[1] = (unsigned short) LittleShort(in->v[1]);
167  }
168 }
169 
173 static void R_ModLoadTexinfo (const char* mapZone, const lump_t* l)
174 {
175  const dBspTexinfo_t* in = (const dBspTexinfo_t*) (mod_base + l->fileofs);
176  if (l->filelen % sizeof(*in))
177  Com_Error(ERR_DROP, "R_ModLoadTexinfo: funny lump size in %s", r_worldmodel->name);
178 
179  int count = l->filelen / sizeof(*in);
181  Com_DPrintf(DEBUG_RENDERER, "...texinfo: %i\n", count);
182 
183  r_worldmodel->bsp.texinfo = out;
185 
186  for (int i = 0; i < count; i++, in++, out++) {
187  char name[MAX_QPATH];
188  for (int j = 0; j < 3; j++) {
189  out->uv[j] = LittleFloat(in->vecs[0][j]);
190  out->vv[j] = LittleFloat(in->vecs[1][j]);
191  }
192  out->u_offset = LittleFloat(in->vecs[0][3]);
193  out->v_offset = LittleFloat(in->vecs[1][3]);
194 
195  out->flags = LittleLong(in->surfaceFlags);
196 
197  /* exchange the textures with the ones that are needed for base assembly */
198  if (Q_strvalid(mapZone) && strstr(in->texture, "tex_terrain/dummy"))
199  Com_sprintf(name, sizeof(name), "textures/tex_terrain/%s", mapZone);
200  else
201  Com_sprintf(name, sizeof(name), "textures/%s", in->texture);
202 
203  out->image = R_FindImage(name, it_world);
204  }
205 }
206 
210 static void R_SetSurfaceExtents (mBspSurface_t* surf, const model_t* mod)
211 {
212  vec3_t mins, maxs;
213  vec2_t stmins, stmaxs;
214  int i;
215  const mBspTexInfo_t* tex;
216 
217  VectorSet(mins, 999999, 999999, 999999);
218  VectorSet(maxs, -999999, -999999, -999999);
219 
220  Vector2Set(stmins, 999999, 999999);
221  Vector2Set(stmaxs, -999999, -999999);
222 
223  tex = surf->texinfo;
224 
225  for (i = 0; i < surf->numedges; i++) {
226  const int e = mod->bsp.surfedges[surf->firstedge + i];
227  const mBspVertex_t* v;
228  vec3_t position;
229  if (e >= 0)
230  v = &mod->bsp.vertexes[mod->bsp.edges[e].v[0]];
231  else
232  v = &mod->bsp.vertexes[mod->bsp.edges[-e].v[1]];
233 
234  VectorCopy(v->position, position);
235 
236  for (int j = 0; j < 3; j++) { /* calculate mins, maxs */
237  position[j] += (float)shift[j];
238  if (position[j] > maxs[j])
239  maxs[j] = position[j];
240  if (position[j] < mins[j])
241  mins[j] = position[j];
242  }
243 
244  { /* calculate stmins, stmaxs */
245  const float valS = DotProduct(v->position, tex->uv) + tex->u_offset;
246  const float valT = DotProduct(v->position, tex->vv) + tex->v_offset;
247  stmins[0] = std::min(valS, stmins[0]);
248  stmaxs[0] = std::max(valS, stmaxs[0]);
249  stmins[1] = std::min(valT, stmins[1]);
250  stmaxs[1] = std::max(valT, stmaxs[1]);
251  }
252  }
253 
254  surf->mbsBox.set(mins, maxs);
255  surf->mbsBox.getCenter(surf->center);
256 
257  for (i = 0; i < 2; i++) {
258  const int bmins = floor(stmins[i] / surf->lightmap_scale);
259  const int bmaxs = ceil(stmaxs[i] / surf->lightmap_scale);
260 
261  surf->stmins[i] = bmins * surf->lightmap_scale;
262  surf->stmaxs[i] = bmaxs * surf->lightmap_scale;
263 
264  surf->stcenter[i] = (surf->stmaxs[i] + surf->stmins[i]) / 2.0;
265  surf->stextents[i] = (bmaxs - bmins) * surf->lightmap_scale;
266  }
267 }
268 
269 static void R_ModLoadSurfaces (bool day, const lump_t* l)
270 {
271  const dBspSurface_t* in = (const dBspSurface_t*) (mod_base + l->fileofs);
272  if (l->filelen % sizeof(*in))
273  Com_Error(ERR_DROP, "R_ModLoadSurfaces: funny lump size in %s", r_worldmodel->name);
274  int count = l->filelen / sizeof(*in);
276  Com_DPrintf(DEBUG_RENDERER, "...faces: %i\n", count);
277 
278  r_worldmodel->bsp.surfaces = out;
280 
281  for (int surfnum = 0; surfnum < count; surfnum++, in++, out++) {
282  uint16_t planenum;
283  int16_t side;
284  int ti;
285  int i;
286 
287  out->firstedge = LittleLong(in->firstedge);
288  out->numedges = LittleShort(in->numedges);
289 
290  /* resolve plane */
291  planenum = LittleShort(in->planenum);
292  out->plane = r_worldmodel->bsp.planes + planenum;
293 
294  /* and sideness */
295  side = LittleShort(in->side);
296  if (side) {
297  out->flags |= MSURF_PLANEBACK;
298  VectorNegate(out->plane->normal, out->normal);
299  } else {
300  VectorCopy(out->plane->normal, out->normal);
301  }
302 
303  ti = LittleShort(in->texinfo);
304  if (ti < 0 || ti >= r_worldmodel->bsp.numtexinfo)
305  Com_Error(ERR_DROP, "R_ModLoadSurfaces: bad texinfo number");
306  out->texinfo = r_worldmodel->bsp.texinfo + ti;
307 
308  out->lightmap_scale = (1 << r_worldmodel->bsp.lightquant);
309 
310  /* and size, texcoords, etc */
312 
313  if (!(out->texinfo->flags & SURF_WARP))
314  out->flags |= MSURF_LIGHTMAP;
315 
316  /* lastly lighting info */
317  if (day)
318  i = LittleLong(in->lightofs[LIGHTMAP_DAY]);
319  else
320  i = LittleLong(in->lightofs[LIGHTMAP_NIGHT]);
321 
322  if (i == -1)
323  out->samples = nullptr;
324  else
325  out->samples = r_worldmodel->bsp.lightdata + i;
326 
327  /* create lightmaps */
329 
330  out->tile = r_numMapTiles - 1;
331  }
332 }
333 
338 static void R_ModLoadNodes (const lump_t* l)
339 {
340  const dBspNode_t* in = (const dBspNode_t*) (mod_base + l->fileofs);
341  if (l->filelen % sizeof(*in))
342  Com_Error(ERR_DROP, "R_ModLoadNodes: funny lump size in %s", r_worldmodel->name);
343 
344  int count = l->filelen / sizeof(*in);
346  Com_DPrintf(DEBUG_RENDERER, "...nodes: %i\n", count);
347 
348  r_worldmodel->bsp.nodes = out;
350 
351  mBspNode_t* parent = nullptr;
352  for (int i = 0; i < count; i++, in++, out++) {
353  int j;
354  const int p = LittleLong(in->planenum);
355 
356  /* skip special pathfinding nodes - they have a negative index */
357  if (p == PLANENUM_LEAF) {
358  /* in case of "special" pathfinding nodes (they don't have a plane)
359  * we have to set this to nullptr */
360  out->plane = nullptr;
362  parent = nullptr;
363  } else {
364  out->plane = r_worldmodel->bsp.planes + p;
365  /* differentiate from leafs */
366  out->contents = CONTENTS_NODE;
367  parent = out;
368  }
369 
370  for (j = 0; j < 3; j++) {
371  out->minmaxs.mins[j] = LittleShort(in->mins[j]) + (float)shift[j];
372  out->minmaxs.maxs[j] = LittleShort(in->maxs[j]) + (float)shift[j];
373  }
374 
375  out->firstsurface = LittleShort(in->firstface);
376  out->numsurfaces = LittleShort(in->numfaces);
377 
378  for (j = 0; j < 2; j++) {
379  const int p2 = LittleLong(in->children[j]);
380  if (p2 > LEAFNODE) {
381  assert(p2 < r_worldmodel->bsp.numnodes);
382  out->children[j] = r_worldmodel->bsp.nodes + p2;
383  } else {
384  assert((LEAFNODE - p2) < r_worldmodel->bsp.numleafs);
385  out->children[j] = (mBspNode_t*) (r_worldmodel->bsp.leafs + (LEAFNODE - p2));
386  }
387  out->children[j]->parent = parent;
388  }
389  }
390 }
391 
392 static void R_ModLoadLeafs (const lump_t* l)
393 {
394  const dBspLeaf_t* in = (const dBspLeaf_t*) (mod_base + l->fileofs);
395  if (l->filelen % sizeof(*in))
396  Com_Error(ERR_DROP, "R_ModLoadLeafs: funny lump size in %s", r_worldmodel->name);
397  const int count = l->filelen / sizeof(*in);
399  Com_DPrintf(DEBUG_RENDERER, "...leafs: %i\n", count);
400 
401  r_worldmodel->bsp.leafs = out;
403 
404  for (int i = 0; i < count; i++, in++, out++) {
405  for (int j = 0; j < 3; j++) {
406  out->minmaxs.mins[j] = LittleShort(in->mins[j]) + (float)shift[j];
407  out->minmaxs.maxs[j] = LittleShort(in->maxs[j]) + (float)shift[j];
408  }
409 
410  out->contents = LittleLong(in->contentFlags);
411  }
412 }
413 
414 static void R_ModLoadSurfedges (const lump_t* l)
415 {
416  const int* in = (const int*) (mod_base + l->fileofs);
417  if (l->filelen % sizeof(*in))
418  Com_Error(ERR_DROP, "R_ModLoadSurfedges: funny lump size in %s", r_worldmodel->name);
419 
420  int count = l->filelen / sizeof(*in);
421  if (count < 1 || count >= MAX_MAP_SURFEDGES)
422  Com_Error(ERR_DROP, "R_ModLoadSurfedges: bad surfedges count in %s: %i", r_worldmodel->name, count);
423 
424  int* const out = Mem_PoolAllocTypeN(int, count, vid_modelPool);
425  Com_DPrintf(DEBUG_RENDERER, "...surface edges: %i\n", count);
426 
427  r_worldmodel->bsp.surfedges = out;
429 
430  for (int i = 0; i < count; i++)
431  out[i] = LittleLong(in[i]);
432 }
433 
437 static void R_ModLoadPlanes (const lump_t* l)
438 {
439  const dBspPlane_t* in = (const dBspPlane_t*) (mod_base + l->fileofs);
440  if (l->filelen % sizeof(*in))
441  Com_Error(ERR_DROP, "R_ModLoadPlanes: funny lump size in %s", r_worldmodel->name);
442 
443  int count = l->filelen / sizeof(*in);
445  Com_DPrintf(DEBUG_RENDERER, "...planes: %i\n", count);
446 
447  r_worldmodel->bsp.planes = out;
449 
450  for (int i = 0; i < count; i++, in++, out++) {
451  for (int j = 0; j < 3; j++)
452  out->normal[j] = LittleFloat(in->normal[j]);
453  out->dist = LittleFloat(in->dist);
454  out->type = LittleLong(in->type);
455  }
456 }
457 
467 static void R_ModShiftTile (void)
468 {
469  mBspVertex_t* vert;
470  cBspPlane_t* plane;
471  int i, j;
472 
473  /* we can't do this instantly, because of rounding errors on extents calculation */
474  /* shift vertexes */
475  for (i = 0, vert = r_worldmodel->bsp.vertexes; i < r_worldmodel->bsp.numvertexes; i++, vert++)
476  for (j = 0; j < 3; j++)
477  vert->position[j] += shift[j];
478 
479  /* shift planes */
480  for (i = 0, plane = r_worldmodel->bsp.planes; i < r_worldmodel->bsp.numplanes; i++, plane++)
481  for (j = 0; j < 3; j++)
482  plane->dist += plane->normal[j] * shift[j];
483 }
484 
493 static void R_LoadBspVertexArrays (model_t* mod)
494 {
495  int i;
496  int vertOfs, texCoordOfs, tangOfs;
497  float* vecShifted;
498  float soff, toff, s, t;
499  float* point, *sdir, *tdir;
500  vec4_t tangent;
501  vec3_t binormal;
502  mBspSurface_t* surf;
503  mBspVertex_t* vert;
504  int vertexCount, indexCount;
505 
506  vertOfs = texCoordOfs = tangOfs = 0;
507  vertexCount = indexCount = 0;
508 
509  for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) {
510  const int numedges = surf->numedges;
511  vertexCount += numedges;
512  if (numedges > 2) /* no triangles for degenerate polys */
513  indexCount += (numedges - 2) * 3;
514  }
515 
516  surf = mod->bsp.surfaces;
517 
518  /* allocate the vertex arrays */
519  mod->bsp.texcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool);
520  mod->bsp.lmtexcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool);
521  mod->bsp.verts = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool);
522  mod->bsp.normals = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool);
523  mod->bsp.tangents = Mem_PoolAllocTypeN(GLfloat, vertexCount * 4, vid_modelPool);
524  mod->bsp.indexes = Mem_PoolAllocTypeN(glElementIndex_t, indexCount, vid_modelPool); /* Will be filled at the end of map loading, after building surface lists */
525 
526  for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
527  surf->index = vertOfs / 3;
528  surf->firstTriangle = -1; /* Mark as "no triangles generated yet" */
529 
530  for (int j = 0; j < surf->numedges; j++) {
531  const float* normal;
532  const int index = mod->bsp.surfedges[surf->firstedge + j];
533 
534  /* vertex */
535  if (index > 0) { /* negative indices to differentiate which end of the edge */
536  const mBspEdge_t* edge = &mod->bsp.edges[index];
537  vert = &mod->bsp.vertexes[edge->v[0]];
538  } else {
539  const mBspEdge_t* edge = &mod->bsp.edges[-index];
540  vert = &mod->bsp.vertexes[edge->v[1]];
541  }
542 
543  point = vert->position;
544 
545  /* shift it for assembled maps */
546  vecShifted = &mod->bsp.verts[vertOfs];
547  /* origin (func_door, func_rotating) bmodels must not have shifted vertices,
548  * they are translated by their entity origin value */
549  if (surf->isOriginBrushModel)
550  VectorCopy(point, vecShifted);
551  else
552  VectorAdd(point, shift, vecShifted);
553 
554  /* texture directional vectors and offsets */
555  sdir = surf->texinfo->uv;
556  soff = surf->texinfo->u_offset;
557 
558  tdir = surf->texinfo->vv;
559  toff = surf->texinfo->v_offset;
560 
561  /* texture coordinates */
562  s = DotProduct(point, sdir) + soff;
563  s /= surf->texinfo->image->width;
564 
565  t = DotProduct(point, tdir) + toff;
566  t /= surf->texinfo->image->height;
567 
568  mod->bsp.texcoords[texCoordOfs + 0] = s;
569  mod->bsp.texcoords[texCoordOfs + 1] = t;
570 
571  if (surf->flags & MSURF_LIGHTMAP) { /* lightmap coordinates */
572  s = DotProduct(point, sdir) + soff;
573  s -= surf->stmins[0];
574  s += surf->light_s* surf->lightmap_scale;
575  s += surf->lightmap_scale / 2.0;
576  s /= r_lightmaps.size * surf->lightmap_scale;
577 
578  t = DotProduct(point, tdir) + toff;
579  t -= surf->stmins[1];
580  t += surf->light_t* surf->lightmap_scale;
581  t += surf->lightmap_scale / 2.0;
582  t /= r_lightmaps.size * surf->lightmap_scale;
583  }
584 
585  mod->bsp.lmtexcoords[texCoordOfs + 0] = s;
586  mod->bsp.lmtexcoords[texCoordOfs + 1] = t;
587 
588  /* normal vectors */
589  if ((surf->texinfo->flags & SURF_PHONG) && VectorNotEmpty(vert->normal))
590  normal = vert->normal; /* phong shaded */
591  else
592  normal = surf->normal; /* per plane */
593 
594  memcpy(&mod->bsp.normals[vertOfs], normal, sizeof(vec3_t));
595 
596  /* tangent vector */
597  TangentVectors(normal, sdir, tdir, tangent, binormal);
598  memcpy(&mod->bsp.tangents[tangOfs], tangent, sizeof(vec4_t));
599 
600  vertOfs += 3;
601  texCoordOfs += 2;
602  tangOfs += 4;
603  }
604  }
605 
606  R_ReallocateStateArrays(vertOfs / 3);
607 
608  if (qglBindBuffer) {
609  /* and also the vertex buffer objects */
610  qglGenBuffers(1, &mod->bsp.vertex_buffer);
611  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
612  qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);
613 
614  qglGenBuffers(1, &mod->bsp.texcoord_buffer);
615  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
616  qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);
617 
618  qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
619  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
620  qglBufferData(GL_ARRAY_BUFFER, texCoordOfs * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);
621 
622  qglGenBuffers(1, &mod->bsp.normal_buffer);
623  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
624  qglBufferData(GL_ARRAY_BUFFER, vertOfs * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);
625 
626  qglGenBuffers(1, &mod->bsp.tangent_buffer);
627  qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
628  qglBufferData(GL_ARRAY_BUFFER, tangOfs * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);
629 
630  qglBindBuffer(GL_ARRAY_BUFFER, 0);
631  }
632 }
633 
634 static void R_SortSurfacesArrays_ (mBspSurfaces_t* surfs, mBspSurfaces_t** r_sorted_surfaces)
635 {
636  int i;
637 
638  for (i = 0; i < surfs->count; i++) {
639  const int texindex = R_GetImageIndex(surfs->surfaces[i]->texinfo->image);
640  if (texindex < 0 || texindex >= MAX_GL_TEXTURES)
641  Com_Error(ERR_FATAL, "R_SortSurfacesArrays: bogus image pointer");
642  R_AddSurfaceToArray(r_sorted_surfaces[texindex], surfs->surfaces[i]);
643  }
644 
645  surfs->count = 0;
646 
647  for (i = 0; i < r_numImages; i++) {
648  mBspSurfaces_t* sorted = r_sorted_surfaces[i];
649  if (sorted && sorted->count) {
650  for (int j = 0; j < sorted->count; j++)
651  R_AddSurfaceToArray(surfs, sorted->surfaces[j]);
652 
653  sorted->count = 0;
654  }
655  }
656 }
657 
662 static void R_SortSurfacesArrays (const model_t* mod)
663 {
664  const mBspSurface_t* surf, *s;
665  int i, ns;
666  mBspSurfaces_t** r_sorted_surfaces = Mem_AllocTypeN(mBspSurfaces_t* , r_numImages);
667 
668  /* resolve the start surface and total surface count */
669  s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface];
670  ns = mod->bsp.nummodelsurfaces;
671 
672  /* allocate the per-texture surfaces arrays and determine counts */
673  for (i = 0, surf = s; i < ns; i++, surf++) {
674  int index = R_GetImageIndex(surf->texinfo->image);
675  mBspSurfaces_t* surfs = r_sorted_surfaces[index];
676  if (!surfs) { /* allocate it */
678  r_sorted_surfaces[index] = surfs;
679  }
680 
681  surfs->count++;
682  }
683 
684  /* allocate the surfaces pointers based on counts */
685  for (i = 0; i < r_numImages; i++) {
686  mBspSurfaces_t* surfs = r_sorted_surfaces[i];
687  if (surfs) {
689  surfs->count = 0;
690  }
691  }
692 
693  /* sort the model's surfaces arrays into the per-texture arrays */
694  for (i = 0; i < NUM_SURFACES_ARRAYS; i++) {
695  if (mod->bsp.sorted_surfaces[i]->count) {
696  R_SortSurfacesArrays_(mod->bsp.sorted_surfaces[i], r_sorted_surfaces);
697  Com_DPrintf(DEBUG_RENDERER, "%i: #%i surfaces\n", i, mod->bsp.sorted_surfaces[i]->count);
698  }
699  }
700 
701  /* free the per-texture surfaces arrays */
702  for (i = 0; i < r_numImages; i++) {
703  mBspSurfaces_t* surfs = r_sorted_surfaces[i];
704  if (surfs) {
705  Mem_Free(surfs->surfaces);
706  Mem_Free(surfs);
707  }
708  }
709 
710  Mem_Free(r_sorted_surfaces);
711 }
712 
713 static void R_LoadSurfacesArrays_ (model_t* mod)
714 {
715  mBspSurface_t* surf, *s;
716  int i, ns;
717 
718  /* allocate the surfaces array structures */
720  for (i = 0; i < NUM_SURFACES_ARRAYS; i++)
722 
723  /* resolve the start surface and total surface count */
724  s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface];
725  ns = mod->bsp.nummodelsurfaces;
726 
727  /* determine the maximum counts for each rendered type in order to
728  * allocate only what is necessary for the specified model */
729  for (i = 0, surf = s; i < ns; i++, surf++) {
730  const mBspTexInfo_t* texinfo = surf->texinfo;
731  const material_t* material = &texinfo->image->material;
732  if (texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) {
733  if (texinfo->flags & SURF_WARP)
734  mod->bsp.blend_warp_surfaces->count++;
735  else
736  mod->bsp.blend_surfaces->count++;
737  } else {
738  if (texinfo->flags & SURF_WARP)
739  mod->bsp.opaque_warp_surfaces->count++;
740  else if (texinfo->flags & SURF_ALPHATEST)
741  mod->bsp.alpha_test_surfaces->count++;
742  else
743  mod->bsp.opaque_surfaces->count++;
744  }
745 
746  if (material->flags & STAGE_RENDER)
747  mod->bsp.material_surfaces->count++;
748 
749  if (material->flags & STAGE_FLARE)
750  mod->bsp.flare_surfaces->count++;
751  }
752 
753  /* allocate the surfaces pointers based on the counts */
754  for (i = 0; i < NUM_SURFACES_ARRAYS; i++) {
755  mBspSurfaces_t* surfaces = mod->bsp.sorted_surfaces[i];
756  if (surfaces->count) {
757  surfaces->surfaces = Mem_PoolAllocTypeN(mBspSurface_t*, surfaces->count, vid_modelPool);
758  surfaces->count = 0;
759  }
760  }
761 
762  /* iterate the surfaces again, populating the allocated arrays based
763  * on primary render type */
764  for (i = 0, surf = s; i < ns; i++, surf++) {
765  const mBspTexInfo_t* texinfo = surf->texinfo;
766  const material_t* material = &texinfo->image->material;
767  if (texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) {
768  if (texinfo->flags & SURF_WARP)
769  R_AddSurfaceToArray(mod->bsp.blend_warp_surfaces, surf);
770  else
771  R_AddSurfaceToArray(mod->bsp.blend_surfaces, surf);
772  } else {
773  if (texinfo->flags & SURF_WARP)
774  R_AddSurfaceToArray(mod->bsp.opaque_warp_surfaces, surf);
775  else if (texinfo->flags & SURF_ALPHATEST)
776  R_AddSurfaceToArray(mod->bsp.alpha_test_surfaces, surf);
777  else
778  R_AddSurfaceToArray(mod->bsp.opaque_surfaces, surf);
779  }
780 
781  if (material->flags & STAGE_RENDER)
782  R_AddSurfaceToArray(mod->bsp.material_surfaces, surf);
783 
784  if (material->flags & STAGE_FLARE)
785  R_AddSurfaceToArray(mod->bsp.flare_surfaces, surf);
786  }
787 
788  /* now sort them by texture */
790 }
791 
792 static void R_LoadSurfacesArrays (void)
793 {
794  int i;
795 
796  for (i = 0; i < r_numMapTiles; i++)
798 
799  for (i = 0; i < r_numModelsInline; i++)
801 }
802 
803 static int totalBspTriangles;
804 
806 {
807  mBspModel_t* bsp = &mod->bsp; /* can be aliased with baseTile, so beware */
808  mBspModel_t* baseTile = &r_mapTiles[bsp->maptile]->bsp;
809  int tris = 0;
810 
811  Com_DPrintf(DEBUG_RENDERER, "Soup: model %i/%i\n", bsp->maptile, bsp->firstmodelsurface);
812 
813  for (int i = 0; i < NUM_SURFACES_ARRAYS; i++) {
814  mBspSurfaces_t* surfaces = mod->bsp.sorted_surfaces[i];
815 
816  for (int j = 0; j < surfaces->count; j++) {
817  mBspSurface_t* surf = surfaces->surfaces[j];
818 
819  if (surf->firstTriangle >= 0)
820  continue; /* Already allocated */
821 
822  surf->firstTriangle = baseTile->numIndexes / 3;
823 
824  if (surf->numedges <= 2) {
825  /* degenerate poly, no triangles */
826  surf->numTriangles = 0;
827  } else {
828  /* Build triangle list for this surface */
829  int numTris = surf->numedges - 2;
830  surf->numTriangles = numTris;
831  for (int k = 0; k < numTris; k++) {
832  /* k'th element of triangle fan */
833  baseTile->indexes[baseTile->numIndexes++] = surf->index;
834  baseTile->indexes[baseTile->numIndexes++] = surf->index + k + 1;
835  baseTile->indexes[baseTile->numIndexes++] = surf->index + k + 2;
836  tris++;
837  }
838  }
839  }
840  }
841 
842  totalBspTriangles += tris;
843  Com_DPrintf(DEBUG_RENDERER, " surfs: %i tris: %i\n", bsp->nummodelsurfaces, tris);
844 }
845 
847 {
848  int i;
849 
850  totalBspTriangles = 0;
851 
852  for (i = 0; i < r_numMapTiles; i++)
854 
855  for (i = 0; i < r_numModelsInline; i++)
857 
858  Com_Printf("World model: %i triangles\n", totalBspTriangles);
859 
860  /* Create buffer objects for indexes */
861  if (qglBindBuffer) {
862  for (i = 0; i < r_numMapTiles; i++) {
863  mBspModel_t* bsp = &r_mapTiles[i]->bsp;
864 
865  qglGenBuffers(1, &bsp->index_buffer);
866  qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bsp->index_buffer);
867  qglBufferData(GL_ELEMENT_ARRAY_BUFFER, bsp->numIndexes * sizeof(glElementIndex_t), bsp->indexes, GL_STATIC_DRAW);
868  }
869 
870  qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
871  }
872 }
873 
877 static void R_SetModel (mBspNode_t* node, model_t* mod)
878 {
879  node->model = mod;
880 
881  if (node->contents > CONTENTS_NODE)
882  return;
883 
884  R_SetModel(node->children[0], mod);
885  R_SetModel(node->children[1], mod);
886 }
887 
888 
892 static void R_RecursiveSetModel (mBspNode_t* node, model_t* mod)
893 {
894  /* skip special pathfinding nodes */
895  if (node->contents == CONTENTS_PATHFINDING_NODE) {
896  R_RecursiveSetModel(node->children[0], mod);
897  R_RecursiveSetModel(node->children[1], mod);
898  } else {
899  R_SetModel(node, mod);
900  }
901 }
902 
906 static void R_SetupSubmodels (void)
907 {
908  int i, j;
909 
910  /* set up the submodels, the first 255 submodels are the models of the
911  * different levels, don't care about them */
914  const mBspHeader_t* sub = &r_worldmodel->bsp.submodels[i];
915 
916  /* copy most info from world */
917  *mod = *r_worldmodel;
918  mod->type = mod_bsp_submodel;
919 
920  Com_sprintf(mod->name, sizeof(mod->name), "*%d", i);
921 
922  /* copy the rest from the submodel */
923  mod->modBox.set(sub->hBox);
924  mod->radius = sub->radius;
925 
926  mod->bsp.firstnode = sub->headnode;
927  mod->bsp.nodes = &r_worldmodel->bsp.nodes[mod->bsp.firstnode];
928  mod->bsp.maptile = r_numMapTiles - 1;
929  if (mod->bsp.firstnode >= r_worldmodel->bsp.numnodes)
930  Com_Error(ERR_DROP, "R_SetupSubmodels: Inline model %i has bad firstnode", i);
931 
932  R_RecursiveSetModel(mod->bsp.nodes, mod);
933 
934  mod->bsp.firstmodelsurface = sub->firstface;
935  mod->bsp.nummodelsurfaces = sub->numfaces;
936 
937  /* submodel vertices of the surfaces must not be shifted in case of rmas */
938  for (j = mod->bsp.firstmodelsurface; j < mod->bsp.firstmodelsurface + mod->bsp.nummodelsurfaces; j++) {
940  }
941 
942  /*mod->bsp.numleafs = sub->visleafs;*/
944  }
945 }
946 
951 static void R_SetupWorldModel (void)
952 {
953  int surfCount = r_worldmodel->bsp.numsurfaces;
954 
955 #ifdef DEBUG
956  /* validate surface allocation by submodels by checking the surface array range they are using */
957  /* start with inverted range to simplify code */
958  int first = surfCount, last = -1; /* @note range is [,) */
959  /* first NUM_REGULAR_MODELS submodels are the models of the different levels, don't care about them */
960  for (int i = NUM_REGULAR_MODELS; i < r_worldmodel->bsp.numsubmodels; i++) {
961  const mBspHeader_t* sub = &r_worldmodel->bsp.submodels[i];
962  int firstFace = sub->firstface;
963  int lastFace = firstFace + sub->numfaces;
964 
965  if (lastFace <= firstFace)
966  continue; /* empty submodel, ignore it */
967 
968  if (last >= 0 && (firstFace > last || lastFace < first))
969  Com_Printf("Warning: submodels may not combine to contigous range in the surface array, some world geometry could be missing as a result (submodel %i)\n", i);
970 
971  if (firstFace < first)
972  first = firstFace;
973 
974  if (lastFace > last)
975  last = lastFace;
976 
977  Com_DPrintf(DEBUG_RENDERER, "Submodel %i, range %i..%i\n", i, firstFace, lastFace - 1);
978  }
979  surfCount = first;
980 
981  if (last >= 0 && last != r_worldmodel->bsp.numsurfaces)
982  Com_Printf("Warning: %i surfaces are lost, some world geometry could be missing as a result\n", r_worldmodel->bsp.numsurfaces - last);
983 #else
984  /* take a shortcut: assume that first submodel surfaces begin exactly after world model ones */
985  if (NUM_REGULAR_MODELS < r_worldmodel->bsp.numsubmodels)
987 #endif
988  Com_DPrintf(DEBUG_RENDERER, "World model, range 0..%i\n", surfCount - 1);
989 
991  r_worldmodel->bsp.nummodelsurfaces = surfCount;
992 }
993 
1005 static void R_ModAddMapTile (const char* name, const char* mapZone, bool day, int sX, int sY, int sZ)
1006 {
1007  int i;
1008  byte* buffer;
1009  dBspHeader_t* header;
1010  const int lightingLump = day ? LUMP_LIGHTING_DAY : LUMP_LIGHTING_NIGHT;
1011 
1012  if (r_numMapTiles < 0 || r_numMapTiles >= MAX_MAPTILES)
1013  Com_Error(ERR_DROP, "R_ModAddMapTile: Too many map tiles");
1014 
1015  /* alloc model and tile */
1019  Com_sprintf(r_worldmodel->name, sizeof(r_worldmodel->name), "maps/%s.bsp", name);
1020 
1021  /* load the file */
1022  FS_LoadFile(r_worldmodel->name, &buffer);
1023  if (!buffer)
1024  Com_Error(ERR_DROP, "R_ModAddMapTile: %s not found", r_worldmodel->name);
1025 
1026  /* init */
1029 
1030  /* prepare shifting */
1031  VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_SIZE);
1032 
1033  /* test version */
1034  header = (dBspHeader_t*) buffer;
1035  i = LittleLong(header->version);
1036  if (i != BSPVERSION)
1037  Com_Error(ERR_DROP, "R_ModAddMapTile: %s has wrong version number (%i should be %i)", r_worldmodel->name, i, BSPVERSION);
1038 
1039  /* swap all the lumps */
1040  mod_base = (byte*) header;
1041 
1042  BSP_SwapHeader(header, r_worldmodel->name);
1043 
1044  /* load into heap */
1046  R_ModLoadNormals(&header->lumps[LUMP_NORMALS]);
1047  R_ModLoadEdges(&header->lumps[LUMP_EDGES]);
1049  R_ModLoadLighting(&header->lumps[lightingLump]);
1050  R_ModLoadPlanes(&header->lumps[LUMP_PLANES]);
1051  R_ModLoadTexinfo(mapZone, &header->lumps[LUMP_TEXINFO]);
1052  R_ModLoadSurfaces(day, &header->lumps[LUMP_FACES]);
1053  R_ModLoadLeafs(&header->lumps[LUMP_LEAFS]);
1054  R_ModLoadNodes(&header->lumps[LUMP_NODES]);
1056 
1057  R_SetupSubmodels();
1059 
1061 
1062  /* in case of random map assembly shift some vectors */
1063  if (VectorNotEmpty(shift))
1064  R_ModShiftTile();
1065 
1066  FS_FreeFile(buffer);
1067 }
1068 
1069 static void R_ModEndLoading (const char* mapName)
1070 {
1075  R_GenerateGrass();
1076 }
1077 
1098 void R_ModBeginLoading (const char* tiles, bool day, const char* pos, const char* mapName, const char* mapZone)
1099 {
1100  char name[MAX_VAR];
1101  char base[MAX_QPATH];
1102 
1103  assert(mapName);
1104 
1105  /* clear any lights leftover in the active list from previous maps */
1107  /* remove all leftover grass */
1108  R_ClearGrass();
1109 
1110  /* init */
1112  r_numModelsInline = 0;
1113  r_numMapTiles = 0;
1114 
1115  /* load tiles */
1116  while (tiles) {
1117  /* get tile name */
1118  const char* token = Com_Parse(&tiles);
1119  if (!tiles) {
1120  /* finish */
1122  return;
1123  }
1124 
1125  /* get base path */
1126  if (token[0] == '-') {
1127  Q_strncpyz(base, token + 1, sizeof(base));
1128  continue;
1129  }
1130 
1131  /* get tile name */
1132  if (token[0] == '+')
1133  Com_sprintf(name, sizeof(name), "%s%s", base, token + 1);
1134  else
1135  Q_strncpyz(name, token, sizeof(name));
1136 
1137  if (pos && pos[0]) {
1138  ipos3_t sh;
1139  /* get grid position and add a tile */
1140  for (int i = 0; i < 3; i++) {
1141  token = Com_Parse(&pos);
1142  if (!pos)
1143  Com_Error(ERR_DROP, "R_ModBeginLoading: invalid positions\n");
1144  sh[i] = atoi(token);
1145  }
1146  if (sh[0] <= -(PATHFINDING_WIDTH / 2) || sh[0] >= PATHFINDING_WIDTH / 2)
1147  Com_Error(ERR_DROP, "R_ModBeginLoading: invalid x position given: %i\n", sh[0]);
1148  if (sh[1] <= -(PATHFINDING_WIDTH / 2) || sh[1] >= PATHFINDING_WIDTH / 2)
1149  Com_Error(ERR_DROP, "R_ModBeginLoading: invalid y position given: %i\n", sh[1]);
1150  if (sh[2] >= PATHFINDING_HEIGHT)
1151  Com_Error(ERR_DROP, "R_ModBeginLoading: invalid z position given: %i\n", sh[2]);
1152  R_ModAddMapTile(name, mapZone, day, sh[0], sh[1], sh[2]);
1153  } else {
1154  /* load only a single tile, if no positions are specified */
1155  R_ModAddMapTile(name, mapZone, day, 0, 0, 0);
1157  return;
1158  }
1159  }
1160 
1161  Com_Error(ERR_DROP, "R_ModBeginLoading: invalid tile names\n");
1162 }
1163 
1168 {
1169  for (int i = 0; i < r_numMapTiles; i++) {
1170  model_t* mod = r_mapTiles[i];
1171  const size_t size = lengthof(mod->bsp.sorted_surfaces);
1172  for (int j = 0; j < size; j++)
1173  if (mod->bsp.sorted_surfaces[j]) {
1174  Mem_Free(mod->bsp.sorted_surfaces[j]);
1175  mod->bsp.sorted_surfaces[j] = nullptr;
1176  }
1177  }
1179 }
mBspModel_t bsp
Definition: r_model.h:60
#define LEAFNODE
Definition: defines.h:44
#define SURF_ORIGIN
Definition: defines.h:266
struct model_s * model
#define LUMP_LIGHTING_DAY
Definition: defines.h:175
vec_t VectorLength(const vec3_t v)
Calculate the length of a vector.
Definition: mathlib.cpp:434
static void R_ModLoadLighting(const lump_t *l)
Load the lightmap data.
vec3_t maxs
Definition: aabb.h:258
#define LUMP_EDGES
Definition: defines.h:178
static ipos3_t shift
The shift array is used for random map assemblies (RMA) to shift the mins/maxs and stuff like that...
#define VectorCopy(src, dest)
Definition: vector.h:51
#define Mem_AllocTypeN(type, n)
Definition: mem.h:38
static void R_RecursiveSetModel(mBspNode_t *node, model_t *mod)
#define LIGHTMAP_DAY
Definition: defines.h:364
#define VectorSet(v, x, y, z)
Definition: vector.h:59
vec2_t stextents
Definition: r_model_brush.h:97
memPool_t * vid_modelPool
Definition: cl_main.cpp:90
unsigned int lmtexcoord_buffer
static void R_ModEndLoading(const char *mapName)
void R_LoadMaterials(const char *map)
Load material definitions for each map that has one.
Definition: r_material.cpp:920
static const byte * mod_base
The model base pointer - bases for the lump offsets.
#define LUMP_SURFEDGES
Definition: defines.h:179
lump_t lumps[HEADER_LUMPS]
Definition: qfiles.h:265
#define STAGE_RENDER
Definition: r_material.h:55
#define LUMP_NODES
Definition: defines.h:171
int r_numImages
Definition: r_image.cpp:41
model_t * r_mapTiles[MAX_MAPTILES]
The world model(s)
Definition: r_model.cpp:32
static void R_SetupWorldModel(void)
Sets up surface range for the world model.
#define SURF_ALPHATEST
Definition: defines.h:268
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
unsigned int tangent_buffer
#define LUMP_NORMALS
Definition: defines.h:183
#define VectorNegate(src, dest)
Definition: vector.h:58
void R_EndBuildingLightmaps(void)
Definition: r_lightmap.cpp:298
unsigned short numsurfaces
static void R_ModLoadSurfedges(const lump_t *l)
voidpf void uLong size
Definition: ioapi.h:42
local graphics definitions
int firstmodelsurface
static void R_SortSurfacesArrays(const model_t *mod)
Reorders all surfaces arrays for the specified model, grouping the surface pointers by texture...
int nummodelsurfaces
uint32_t flags
Definition: r_model_brush.h:70
static void R_ModLoadNormals(const lump_t *l)
float dist
Definition: typedefs.h:22
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
mBspTexInfo_t * texinfo
uint32_t filelen
Definition: qfiles.h:258
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
#define LUMP_MODELS
Definition: defines.h:180
model_t r_modelsInline[MAX_MOD_KNOWN]
Definition: r_model.cpp:36
mBspSurface_t ** surfaces
#define R_AddSurfaceToArray(array, surf)
void R_CreateSurfaceLightmap(mBspSurface_t *surf)
Definition: r_lightmap.cpp:223
modtype_t type
Definition: r_model.h:46
#define CONTENTS_NODE
mBspVertex_t * vertexes
struct mBspNode_s * children[2]
byte type
Definition: typedefs.h:23
vec3_t normal
Definition: typedefs.h:21
static void R_ModLoadEdges(const lump_t *l)
mBspSurface_t * surfaces
int height
Definition: r_image.h:64
#define ERR_FATAL
Definition: common.h:210
int r_numMapTiles
Definition: r_model.cpp:33
ipos_t ipos3_t[3]
Definition: ufotypes.h:70
static float R_RadiusFromBounds(const vec3_t mins, const vec3_t maxs)
unsigned short v[2]
Definition: r_model_brush.h:54
#define LUMP_PLANES
Definition: defines.h:168
#define Q_strvalid(string)
Definition: shared.h:141
Directory of the different data blocks.
Definition: qfiles.h:256
static void R_ModLoadVertexes(const lump_t *l)
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
void R_ClearStaticLights(void)
Remove all static light data.
Definition: r_light.cpp:300
#define STAGE_FLARE
Definition: r_material.h:48
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
Definition: r_image.cpp:603
unsigned int index
lightmap definitions
#define LIGHTMAP_NIGHT
Definition: defines.h:363
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
AABB modBox
Definition: r_model.h:51
#define PATHFINDING_WIDTH
absolute max
Definition: defines.h:292
#define LittleShort(X)
Definition: byte.h:35
#define SURF_BLEND33
Definition: defines.h:257
#define DotProduct(x, y)
Returns the distance between two 3-dimensional vectors.
Definition: vector.h:44
#define ERR_DROP
Definition: common.h:211
#define LUMP_LIGHTING_NIGHT
Definition: defines.h:174
The BSP header definition with the data block directory.
Definition: qfiles.h:262
#define OBJZERO(obj)
Definition: shared.h:178
#define MAX_VAR
Definition: shared.h:36
unsigned int normal_buffer
void set(const AABB &other)
Copies the values from the given aabb.
Definition: aabb.h:60
#define Vector2Set(v, x, y)
Definition: vector.h:61
#define LUMP_VERTEXES
Definition: defines.h:169
#define NUM_REGULAR_MODELS
Definition: defines.h:354
uint32_t fileofs
Definition: qfiles.h:257
static void R_ModLoadSurfaces(bool day, const lump_t *l)
static void R_SetSurfaceExtents(mBspSurface_t *surf, const model_t *mod)
Fills in s->stmins[] and s->stmaxs[].
static void R_LoadBspVertexArrays(model_t *mod)
Puts the map data into buffers.
model_t * R_AllocModelSlot(void)
Definition: r_model.cpp:100
static void R_SetModel(mBspNode_t *node, model_t *mod)
void TangentVectors(const vec3_t normal, const vec3_t sdir, const vec3_t tdir, vec4_t tangent, vec3_t binormal)
Projects the normalized directional vectors on to the normal&#39;s plane. The fourth component of the res...
Definition: mathlib.cpp:1057
int R_GetImageIndex(image_t *imagePtr)
Returns an index of the image pointer in the r_images linked list, as if r_images would be a plain co...
Definition: r_image.cpp:702
bool isOriginBrushModel
unsigned short firstsurface
cBspPlane_t * planes
image_t * image
Definition: r_model_brush.h:71
brush model
static void R_ModLoadSubmodels(const lump_t *l)
Loads brush entities like func_door and func_breakable.
static void R_LoadSurfacesArrays_(model_t *mod)
float * tangents
float * texcoords
static void R_ModLoadNodes(const lump_t *l)
GLuint glElementIndex_t
Definition: r_gl.h:57
#define MSURF_PLANEBACK
Definition: r_model_brush.h:50
short stmins[2]
Definition: r_model_brush.h:94
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
#define SURF_PHONG
Definition: defines.h:263
unsigned int index_buffer
memPool_t * vid_lightPool
Definition: cl_main.cpp:89
vec3_t mins
Definition: aabb.h:257
unsigned flags
Definition: r_material.h:157
#define VectorNotEmpty(a)
Definition: vector.h:72
static void R_SortSurfacesArrays_(mBspSurfaces_t *surfs, mBspSurfaces_t **r_sorted_surfaces)
int r_numModelsInline
Definition: r_model.cpp:37
byte * lightdata
uint32_t version
Definition: qfiles.h:264
void R_GenerateGrass()
Definition: r_grass.cpp:228
void getCenter(vec3_t center) const
Calculates the center of the bounding box.
Definition: aabb.h:155
static void R_ModLoadTexinfo(const char *mapZone, const lump_t *l)
static void R_LoadSurfacesArrays(void)
#define CONTENTS_PATHFINDING_NODE
unsigned int texcoord_buffer
QGL_EXTERN GLuint index
Definition: r_gl.h:110
#define UNIT_SIZE
Definition: defines.h:121
convex region of space in the BSP tree
Definition: typedefs.h:416
QGL_EXTERN GLuint count
Definition: r_gl.h:99
static void R_ModAddMapTile(const char *name, const char *mapZone, bool day, int sX, int sY, int sZ)
#define MAX_GL_TEXTURES
Definition: r_image.h:76
static int totalBspTriangles
char name[MAX_QPATH]
Definition: r_model.h:44
float * normals
Pseudoinstanced grass generation and rendering.
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
#define PATHFINDING_HEIGHT
15 max, adjusting above 8 will require a rewrite to the DV code
Definition: defines.h:294
#define VectorAdd(a, b, dest)
Definition: vector.h:47
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
lightmaps_t r_lightmaps
Definition: r_lightmap.cpp:32
mBspLeaf_t * leafs
cBspPlane_t * plane
Definition: r_model_brush.h:84
float radius
Definition: r_model.h:52
#define PLANENUM_LEAF
Definition: defines.h:45
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
void R_ClearGrass()
Definition: r_grass.cpp:56
static void R_SetupSubmodels(void)
Sets up bmodels (brush models) like doors and breakable objects.
int width
Definition: r_image.h:64
void R_ModBeginLoading(const char *tiles, bool day, const char *pos, const char *mapName, const char *mapZone)
Specifies the model that will be used as the world.
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
#define MAX_MAP_SURFEDGES
Definition: defines.h:147
float * verts
unsigned int numTriangles
surfaces are assigned to arrays based on their primary rendering type and then sorted by world textur...
mBspSurfaces_t * sorted_surfaces[NUM_SURFACES_ARRAYS]
#define Mem_Free(ptr)
Definition: mem.h:35
static void R_GenerateTriangleSoup()
static void R_ModLoadPlanes(const lump_t *l)
mBspNode_t * nodes
vec_t vec3_t[3]
Definition: ufotypes.h:39
vec_t vec2_t[2]
Definition: ufotypes.h:38
static void R_ModShiftTile(void)
Shift the verts for map assemblies.
mBspEdge_t * edges
static model_t * r_worldmodel
The currently loaded world model for the actual tile.
#define LUMP_FACES
Definition: defines.h:173
float * lmtexcoords
mBspHeader_t * submodels
static void R_GenerateTriangleSoup_(model_t *mod)
#define lengthof(x)
Definition: shared.h:105
#define SURF_BLEND66
Definition: defines.h:258
vec3_t position
Definition: r_model_brush.h:37
#define LUMP_TEXINFO
Definition: defines.h:172
#define BSPVERSION
Definition: qfiles.h:253
void R_BeginBuildingLightmaps(void)
Definition: r_lightmap.cpp:273
mBspTexInfo_t * texinfo
short stmaxs[2]
Definition: r_model_brush.h:95
#define Mem_PoolAllocType(type, pool)
Definition: mem.h:43
#define BSP_SwapHeader(header, name)
Definition: qfiles.h:269
void R_ReallocateStateArrays(int size)
Reallocate arrays of GL primitives if needed.
Definition: r_state.cpp:1029
cBspPlane_t * plane
#define SURF_WARP
Definition: defines.h:256
static void R_ModLoadLeafs(const lump_t *l)
#define LUMP_LEAFS
Definition: defines.h:176
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
#define DEBUG_RENDERER
Definition: defines.h:62
plane_t structure
Definition: typedefs.h:20
unsigned int vertex_buffer
material_t material
Definition: r_image.h:68
glElementIndex_t * indexes
#define LittleFloat(X)
Definition: byte.h:57
static const char * mapName
void R_ModReloadSurfacesArrays(void)
void FS_FreeFile(void *buffer)
Definition: files.cpp:411
#define LittleLong(X)
Definition: byte.h:37
#define MSURF_LIGHTMAP
Definition: r_model_brush.h:51
vec_t vec4_t[4]
Definition: ufotypes.h:40