1 //-----------------------------------------------------------------------------
2 // Q3 Binary Space Tree
3 //-----------------------------------------------------------------------------
4
5 #include "cake.h"
6 #include "q3bsp.h"
7 #include "types.h"
8 #include "console.h"
9 #include "logfile.h"
10 #include "render.h"
11 #include "vars.h"
12 #include "math.h"
13 #include "skybox.h"
14 #include "overlay.h"
15 #include "mem.h"
16 #include "frustum.h"
17 #include "sound.h"
18 #include "timer.h"
19 #include "framework.h"
20 #include "system.h"
21
22 // PVS test macro: PVS table is a packed single bit array, rowsize
23 // bytes times numclusters rows
24 #define BSP_TESTVIS(from,to) \
25 (*(r_visibility->data + (from)*r_visibility->rowsize + \
26 ((to)>>3)) & (1 << ((to) & 7)))
27
28 #define DIST_EPSILON (0.03125f)
29
30 Var r_drawsky("r_drawsky", 1);
31 Var r_drawworld("r_drawworld", 1);
32 Var r_drawmodels("r_drawmodels", 1);
33 Var r_showcluster("r_showcluster", 0);
34 Var r_showlbrushes("r_showlbrushes", 0);
35 Var r_showleafs("r_showleafs", 0);
36 Var r_showcamleaf("r_showcamleaf", 0);
37 Var r_nofaces("r_nofaces", 0);
38 Var r_nocurves("r_nocurves", 0);
39 Var r_nomesh("r_nomesh", 0);
40 Var r_noflares("r_noflares", 0);
41 Var r_noportals("r_noportals", 0);
42 Var r_nofrustum("r_nofrustum", 0);
43 Var r_lockpvs("r_lockpvs", 0);
44 Var r_novis("r_novis", 0);
45 Var r_surfsky("r_surfsky", 0);
46 Var r_fillside("r_fillside", -1, VF_DEBUG);
47 Var r_grid("r_grid", 0);
48 Var r_normals("r_normals", 0);
49 Var r_showbbox("r_showbbox", 0);
50 Var v_selectsurface("v_selectsurface", -1);
51 Var v_selectpatch("v_selectpatch", -1);
52 Var v_selectmodel("v_selectmodel", -1);
53 Var v_bspdebug("v_bspdebug", 0, VF_DEBUG);
54 Var sys_bspstate("sys_bspstate", INACTIVE, VF_SYSTEM);
55
56 int num_leafs = 0, num_leafs_last_frame;
57 int cam_leaf = -1; /**< Camera leaf number */
58 int cam_cluster = -1; /**< Camera cluster number */
59
60 // Initialization
Q3BSP(char * name,World * w,int * res)61 Q3BSP::Q3BSP(char *name, World* w, int *res):LumpFile(name, BSPHEADERID, BSPVERSION, NUM_LUMPS)
62 {
63 sys_bspstate = INACTIVE;
64
65 r_shaderrefs = NULL;
66 r_planes = NULL;
67 r_nodes = NULL;
68 r_leafs = NULL;
69 r_leaffaces = NULL;
70 r_leafbrushes = NULL;
71 r_leafpatches = NULL;
72 r_models = NULL;
73 r_brushes = NULL;
74 r_brushsides = NULL;
75 r_verts = NULL;
76 r_elems = NULL;
77 r_lightmapinfos = NULL;
78 r_effects = NULL;
79 r_visibility = NULL;
80 face_list = NULL;
81 r_surfaces = NULL;
82 r_patchesgroups = NULL;
83 r_skybox = NULL;
84 r_lightvols = NULL;
85 r_faces = NULL;
86 r_patches = NULL;
87 r_meshes = NULL;
88 r_flares = NULL;
89 r_patches = NULL;
90 r_entities = NULL;
91
92 worldname = NULL;
93
94 levelshotdetail = levelshot = -1;
95
96 if (!mem)
97 {
98 gConsole->Insertln("^1ERROR: %s is not a valid map name", name);
99 *res = 0;
100 return;
101 }
102
103 world = w;
104
105 // --- Loading
106 gConsole->Insertln("--- Loading bsp \"%s\"", name);
107
108 // Remove the path and extension from map name
109 char map_name[256] = { '\0' };
110 int lname = (int) strlen(name)-1;
111 while (lname >= 0 && name[lname] != '/' && name[lname] != '\\') --lname;
112 strcpy(map_name, &name[lname+1]);
113 f_StripExtension(map_name);
114 LoadLevelshot(map_name);
115 DisplayLevelshot();
116 gRender->SwapBuffers();
117
118 LoadShaders();
119 LoadEntities();
120 LoadPlanes();
121 LoadNodes();
122 LoadLFaces(); // leaf faces before leafs
123 LoadLBrushes(); // leaf brushes before leafs
124 LoadBrushSides(); // brush sides before brushes
125 LoadBrushes();
126 LoadLeafs();
127 LoadVerts();
128 LoadElems();
129 LoadEffects();
130 LoadFaces();
131 LoadModels();
132 LoadLightmaps();
133 LoadLightVols();
134 LoadVisibility();
135
136 // shader references not needed any more (all shaders have been
137 // transfered in the world shader manager
138 if (r_shaderrefs) cake_free(r_shaderrefs); r_shaderrefs = NULL;
139
140 // init counters
141 nodecount = 0;
142 viscount = 0;
143 checkcount = 0;
144
145 // delete after loading
146 delete [] mem;
147 mem = NULL;
148
149 gVars->RegisterVar(r_drawsky);
150 gVars->RegisterVar(r_drawworld);
151 gVars->RegisterVar(r_drawmodels);
152 gVars->RegisterVar(r_showcluster);
153 gVars->RegisterVar(r_showlbrushes);
154 gVars->RegisterVar(r_showleafs);
155 gVars->RegisterVar(r_showcamleaf);
156 gVars->RegisterVar(r_novis);
157 gVars->RegisterVar(r_nofrustum);
158 gVars->RegisterVar(r_nofaces);
159 gVars->RegisterVar(r_nocurves);
160 gVars->RegisterVar(r_nomesh);
161 gVars->RegisterVar(r_noflares);
162 gVars->RegisterVar(r_noportals);
163 gVars->RegisterVar(r_lockpvs);
164 gVars->RegisterVar(r_surfsky);
165 gVars->RegisterVar(r_fillside);
166 gVars->RegisterVar(r_grid);
167 gVars->RegisterVar(r_normals);
168 gVars->RegisterVar(r_showbbox);
169 gVars->RegisterVar(v_selectsurface);
170 gVars->RegisterVar(v_selectpatch);
171 gVars->RegisterVar(v_selectmodel);
172 gVars->RegisterVar(v_bspdebug);
173 gVars->RegisterVar(sys_bspstate);
174
175 *res = 1; // success
176 }
177
178 // Shutdown
~Q3BSP(void)179 Q3BSP::~Q3BSP(void)
180 {
181 int i;
182
183 gConsole->Insertln("--- Deleting BSP...");
184
185 sys_bspstate.ivalue = SHUTING;
186
187 world = NULL;
188
189 if (worldname) delete [] worldname; worldname = NULL;
190
191 if (r_shaderrefs) cake_free(r_shaderrefs); r_shaderrefs = NULL;
192 if (r_planes) cake_free(r_planes); r_planes = NULL;
193 if (r_nodes) cake_free(r_nodes); r_nodes = NULL;
194 if (r_leafs) cake_free(r_leafs); r_leafs = NULL;
195 if (r_leaffaces) cake_free(r_leaffaces); r_leaffaces = NULL;
196 if (r_leafbrushes) cake_free(r_leafbrushes); r_leafbrushes = NULL;
197 if (r_leafpatches) cake_free(r_leafpatches); r_leafpatches = NULL;
198 if (r_models) cake_free(r_models); r_models = NULL;
199 if (r_brushes) cake_free(r_brushes); r_brushes = NULL;
200 if (r_brushsides) cake_free(r_brushsides); r_brushsides = NULL;
201 if (r_verts) cake_free(r_verts); r_verts = NULL;
202 if (r_elems) cake_free(r_elems); r_elems = NULL;
203
204 for (i = 0; i < r_numlightmaps[0]; ++i) gRender->UnregisterTexInfo(&r_lightmapinfos[i]);
205 if (r_lightmapinfos) cake_free(r_lightmapinfos); r_lightmapinfos = NULL;
206
207 if (r_effects) cake_free(r_effects); r_effects = NULL;
208
209 if (r_visibility) cake_free(r_visibility); r_visibility = NULL;
210
211 if (r_skybox) { r_skybox->Shut(); // must be done before face_list destruction
212 delete r_skybox; } r_skybox = NULL;
213
214 if (face_list) delete [] face_list; face_list = NULL;
215
216 if (r_cpatches) cake_free(r_cpatches); r_cpatches = NULL;
217
218 if (r_faces)
219 {
220 for (i = 0; i < r_numfaces[0]; ++i) r_faces[i] = NULL;
221 delete [] r_faces;
222 r_faces = NULL;
223 }
224
225 if (r_patches)
226 {
227 for (i = 0; i < r_numpatches[0]; ++i) r_patches[i] = NULL;
228 delete [] r_patches;
229 r_patches = NULL;
230 }
231
232 if (r_meshes)
233 {
234 for (i = 0; i < r_nummeshes[0]; ++i) r_meshes[i] = NULL;
235 delete [] r_meshes;
236 r_meshes = NULL;
237 }
238
239 if (r_flares)
240 {
241 for (i = 0; i < r_numflares[0]; ++i) r_flares[i] = NULL;
242 delete [] r_flares;
243 r_flares = NULL;
244 }
245
246 if (r_surfaces)
247 {
248 for (i = 0; i < r_numsurfaces[0]; ++i)
249 {
250 if (r_surfaces[i].facetype == FACETYPE_PATCH)
251 {
252 for (int l = 1; l < r_surfaces[i].levels; ++l)
253 {
254 cake_free(r_surfaces[i].firstvert[l]);
255 cake_free(r_surfaces[i].firstelem[l]);
256 }
257 }
258 r_surfaces[i].Shut();
259 }
260 delete [] r_surfaces;
261 r_surfaces = NULL;
262 }
263
264 if (r_patchesgroups) delete [] r_patchesgroups; r_patchesgroups = NULL;
265
266 if (r_lightvols) cake_free(r_lightvols); r_lightvols = NULL;
267 if (r_entities) delete r_entities; r_entities = NULL;
268
269 gVars->UnregisterVar(r_drawsky);
270 gVars->UnregisterVar(r_drawworld);
271 gVars->UnregisterVar(r_drawmodels);
272 gVars->UnregisterVar(r_showcluster);
273 gVars->UnregisterVar(r_showlbrushes);
274 gVars->UnregisterVar(r_showleafs);
275 gVars->UnregisterVar(r_showcamleaf);
276 gVars->UnregisterVar(r_novis);
277 gVars->UnregisterVar(r_nofrustum);
278 gVars->UnregisterVar(r_nofaces);
279 gVars->UnregisterVar(r_nocurves);
280 gVars->UnregisterVar(r_nomesh);
281 gVars->UnregisterVar(r_noflares);
282 gVars->UnregisterVar(r_noportals);
283 gVars->UnregisterVar(r_lockpvs);
284 gVars->UnregisterVar(r_surfsky);
285 gVars->UnregisterVar(r_fillside);
286 gVars->UnregisterVar(r_grid);
287 gVars->UnregisterVar(r_normals);
288 gVars->UnregisterVar(r_showbbox);
289 gVars->UnregisterVar(v_selectsurface);
290 gVars->UnregisterVar(v_selectpatch);
291 gVars->UnregisterVar(v_selectmodel);
292 gVars->UnregisterVar(v_bspdebug);
293 gVars->UnregisterVar(sys_bspstate);
294 }
295
296 // more initialization
Init(void)297 void Q3BSP::Init(void)
298 {
299 sys_bspstate = INITIALIZING;
300
301 Surface *surf;
302 Shader *shad;
303 int i;
304
305 cam_leaf = -1;
306 cam_cluster = -1;
307
308 DisplayLoadingMessage("Initializing faces...");
309 InitSurfaces();
310
311 DisplayLoadingMessage("Sorting faces...");
312 gConsole->Insertln("Sorting faces...");
313
314 for (i = 0; i < r_numsurfaces[0]; ++i)
315 {
316 surf = face_list[i].face;
317 if (!surf) continue;
318
319 if (surf->shader > -1)
320 {
321 shad = world->shaders.GetShader(surf->shader);
322 face_list[i].sort_value = ((shad->sortvalue) << 16) +
323 (surf->shader << 8) +
324 (surf->lm_texnum + 1);
325
326 // Rotate sprites to default position
327 for (int k = 0; k < MAX_DEFORMS; ++k)
328 {
329 if (shad->deformVertexes[k].type == DEFORMVERTEXES_AUTOSPRITE ||
330 shad->deformVertexes[k].type == DEFORMVERTEXES_AUTOSPRITE2)
331 {
332 InitAutosprite(surf, shad->deformVertexes[k].type);
333 break;
334 }
335 }
336 }
337 else
338 {
339 face_list[i].sort_value = 0;
340 }
341
342 // Initialize fog parameter for surface
343 // FIXME: can it be done at face or effect loading ?
344 #if MODIF_FOG
345 if (surf->effect >=0 && surf->effect < r_numeffects[0])
346 {
347 if (world->shaders.GetShader(r_effects[surf->effect].shader))
348 {
349 surf->fogplane = r_planes + r_effects[surf->effect].planeidx;
350 }
351 else
352 {
353 surf->fogplane = NULL;
354 gConsole->Insertln("^1Face has effect with no shader !!");
355 }
356 }
357 else
358 {
359 // if (surf->effect > -1 && r_numeffects[0] == 0)
360 // gConsole->Insertln("^1Face %d/%d uses inexistent effect %d/%d !", i, r_numsurfaces[0], surf->effect, r_numeffects[0]);
361 surf->fogplane = NULL;
362 }
363 #else
364 if (surf->effect >= 0 && surf->effect < r_numeffects[0] && r_effects[surf->effect].planeidx >= 0)
365 {
366 cplane_t *p = r_planes + r_effects[surf->effect].planeidx;
367 surf->fog[0] = p->normal[0];
368 surf->fog[1] = p->normal[1];
369 surf->fog[2] = p->normal[2];
370 surf->fog[3] = p->dist;
371 surf->fog[4] = p->type;
372 }
373 else
374 {
375 //if (surf->effect > -1 && r_numeffects[0] == 0)
376 // gConsole->Insertln("^1Face %d/%d uses inexistent effect %d/%d !", i, r_numsurfaces[0], surf->effect, r_numeffects[0]);
377 surf->fog[0] = 0;
378 surf->fog[1] = 0;
379 surf->fog[2] = 1;
380 surf->fog[3] = 0;
381 surf->fog[4] = 2;
382 }
383 #endif
384 }
385
386 // that should be done each time we go int or out water
387 qsort((void*)face_list, r_numsurfaces[0], sizeof(render_face_s), FaceCmp);
388
389 // initialize vertice
390 DisplayLoadingMessage("Overbrighting verts...");
391 float overbright = gVars->ValueForKey("v_overbrightbits");
392 if (overbright > 1)
393 {
394 unsigned int top, r, g, b, a;
395 for (int i = 0; i < r_numverts[0]; ++i)
396 {
397 // overbrighting vertex colors
398 top = r = (unsigned int) ((float) r_verts[i].colour[0] * overbright);
399 g = (unsigned int) ((float) r_verts[i].colour[1] * overbright);
400 b = (unsigned int) ((float) r_verts[i].colour[2] * overbright);
401 a = r_verts[i].colour[3];
402 if (g > top) top = g;
403 if (b > top) top = b;
404 if (top > 255)
405 {
406 top = (255 << 8) / top;
407 r = (r * top) >> 8;
408 g = (g * top) >> 8;
409 b = (b * top) >> 8;
410 }
411
412 r_verts[i].colour[0] = r;
413 r_verts[i].colour[1] = g;
414 r_verts[i].colour[2] = b;
415 r_verts[i].colour[3] = a;
416 }
417 }
418
419 MarkLeafs(-1);
420
421 // Calculate bsp bounding box
422 DisplayLoadingMessage("Generating world bounding box...");
423 gConsole->Insertln("Generating world bounding box...");
424 GenerateBoundingBox(bbox, 0, r_numsurfaces[0]);
425
426 // Adapt camera settings to scene
427 vec3_t diag;
428 VectorSub(&bbox[3], &bbox[0], diag);
429 gVars->SetKeyValue("v_camfar", VectorLength(diag));
430
431 // We generate skybox here because it needs shaders update (cf. world.Init).
432 DisplayLoadingMessage("Generating skybox...");
433 GenerateSkyBox();
434
435 // Load the entities sounds
436 DisplayLoadingMessage("Loading... sounds");
437 gConsole->Insertln("Loading sounds...");
438 r_entities->Init();
439
440 // Play the background music
441 toggleBGMusicPause();
442
443 sys_bspstate = RUNNING;
444 }
445
SetWorldName(const char * name)446 void Q3BSP::SetWorldName(const char *name)
447 {
448 if (!name) return;
449
450 if (worldname) delete [] worldname;
451 int l = (int) strlen(name)+1;
452 worldname = new char[l];
453 memset(worldname, '\0', l);
454 strcpy(worldname, name);
455 }
456
GenerateBoundingBox(bboxf_t destbox,int firstface,int numfaces)457 void Q3BSP::GenerateBoundingBox(bboxf_t destbox, int firstface, int numfaces)
458 {
459 if (!r_surfaces || !r_numsurfaces) return;
460
461 BoxCopy(r_surfaces[firstface].bbox, destbox);
462
463 for (int i = 1; i < numfaces; ++i)
464 {
465 destbox[0] = min(destbox[0], r_surfaces[firstface+i].bbox[0]);
466 destbox[1] = min(destbox[1], r_surfaces[firstface+i].bbox[1]);
467 destbox[2] = min(destbox[2], r_surfaces[firstface+i].bbox[2]);
468 destbox[3] = max(destbox[3], r_surfaces[firstface+i].bbox[3]);
469 destbox[4] = max(destbox[4], r_surfaces[firstface+i].bbox[4]);
470 destbox[5] = max(destbox[5], r_surfaces[firstface+i].bbox[5]);
471 }
472 }
473
GenerateSkyBox(void)474 void Q3BSP::GenerateSkyBox(void)
475 {
476 gConsole->Insertln("Generating skybox...");
477
478 // Tricky method to get sky shader
479 Surface* surf;
480 Shader *shad;
481 int i, j, k, n = 0, shader_found = 0;
482
483 // Add all sky surfaces to skybox surfaces list
484 // Note: I could check only shaders, but I need the number of surfaces that
485 // are skysurfaces. Those faces will be added to skybox skylist to
486 // perform sky polygons clipping at runtime.
487 for (i = 0; i < r_numsurfaces[0]; ++i)
488 {
489 surf = &r_surfaces[i];
490 if (!surf || surf->shader < 0) continue;
491
492 shad = world->shaders.GetShader(surf->shader);
493
494 if (shad->surface_flags & SURF_SKY)
495 {
496 if (!shader_found && surf->effect < 0)
497 {
498 r_skybox = new SkyBox;
499 r_skybox->Init(shad->sky_params.cloudheight);
500 r_skybox->clouds_shader = surf->shader;
501
502 for (j = 0; j < 6; ++j)
503 {
504 for (k = 0; k < shad->sky_params.num_layers; ++k)
505 {
506 r_skybox->box_shader[j]->num_layers = shad->sky_params.num_layers;
507 r_skybox->box_shader[j]->layer[k] = shad->sky_params.layer[k][j];
508 r_skybox->box_shader[j]->cull = shad->cull;
509 r_skybox->box_shader[j]->flags = shad->flags;
510 r_skybox->box_shader[j]->sortvalue = shad->sortvalue;
511 r_skybox->box_shader[j]->surface_flags = shad->surface_flags;
512 r_skybox->box_shader[j]->content_flags = shad->content_flags;
513 }
514 }
515 shader_found = 1;
516 }
517
518 ++n;
519 }
520 }
521
522 // Define skybox size in function of camera near plane distance
523 // @todo Replace v_camnear with a function that check this and autoupdate it
524 if (r_skybox) r_skybox->skyboxsize = max(gVars->ValueForKey("v_camfar")/2.f, r_skybox->skyboxsize);
525
526 if (!shader_found)
527 {
528 gConsole->Insertln("^5WARNING: No sky shader found");
529 return;
530 }
531
532 // Generate sky surfaces list
533 r_skybox->MakeSkyList(n);
534 for (i = 0; i < r_numsurfaces[0]; ++i)
535 {
536 surf = &r_surfaces[i];
537 if (!surf || surf->shader < 0) continue;
538
539 shad = world->shaders.GetShader(surf->shader);
540
541 if (shad->surface_flags & SURF_SKY) r_skybox->AddToList(surf);
542 }
543 }
544
CreatePatchesGroups(void)545 void Q3BSP::CreatePatchesGroups(void)
546 {
547 gConsole->Insertln("Generating patch groups...");
548
549 r_numpatchesgroups[0] = 0;
550 r_numpatchesgroups[1] = r_numpatches[0];
551 r_patchesgroups = new PatchesGroup[r_numpatchesgroups[1]];
552 if (!r_patchesgroups) ThrowException(ALLOCATION_ERROR, "Q3BSP::CreatePatchesGroups.r_patchesgroups");
553
554 bool *rel = new bool[r_numpatches[0]];
555 if (!rel) ThrowException(ALLOCATION_ERROR, "Q3BSP::CreatePatchesGroups.rel");
556 memset(rel, false, r_numpatches[0]*sizeof(bool)); // initialize the boolean table
557
558 int i, j, k, l, m;
559 bool patchadded, addpatch;
560 Surface *surf;
561 const int deflvl = 0;
562 for (i = 0; i < r_numpatches[0]; ++i)
563 {
564 if (rel[i]) continue; // slip if already in a group
565
566 // add patch i in a new group
567 r_patchesgroups[r_numpatchesgroups[0]].Add(i);
568 rel[i] = true; // patch is now in a group
569
570 do
571 {
572 // While a new patch is added to group, it can have common points with
573 // another patch (that had no common point with group before). So we
574 // force the loop until no new patch is added
575 patchadded = false; // by default, no new patch is added to group
576
577 for (j = i+1; j < r_numpatches[0]; ++j) // check all other patches...
578 {
579 if (rel[j]) continue; // ...that haven't been added to any patch
580
581 for (m = 0; m < r_patchesgroups[r_numpatchesgroups[0]].nsurf; ++m)
582 {
583 surf = r_patches[r_patchesgroups[r_numpatchesgroups[0]].surfidx[m]];
584
585 #if 0
586 // We check if both patches have at the least one common vertex
587 addpatch = false; // let's suppose the patch does not belong to group
588 for (k = 0; k < surf->numverts[deflvl]; ++k)
589 {
590 for (l = 0; l < r_patches[j]->numverts[deflvl]; ++l)
591 {
592 if (surf->firstvert[deflvl][k].v_point[0] == r_patches[j]->firstvert[deflvl][l].v_point[0]
593 && surf->firstvert[deflvl][k].v_point[1] == r_patches[j]->firstvert[deflvl][l].v_point[1]
594 && surf->firstvert[deflvl][k].v_point[2] == r_patches[j]->firstvert[deflvl][l].v_point[2])
595 {
596 addpatch = true;
597 break;
598 }
599 }
600 if (addpatch) break;
601 }
602 #else
603 // We check if the patch in inside the bounding box of another patch
604 // Note: In the bsp file, it seems that patch bounding box are either
605 // (0, 0, 0, 0, 0, 0) or the bounding box of the group
606 addpatch = true; // let's suppose the patch belongs to group
607 for (l = 0; l < r_patches[j]->numverts[0]; ++l)
608 {
609 if (r_patches[j]->firstvert[deflvl][l].v_point[0] < surf->bbox[0] || r_patches[j]->firstvert[deflvl][l].v_point[0] > surf->bbox[3] ||
610 r_patches[j]->firstvert[deflvl][l].v_point[1] < surf->bbox[1] || r_patches[j]->firstvert[deflvl][l].v_point[1] > surf->bbox[4] ||
611 r_patches[j]->firstvert[deflvl][l].v_point[2] < surf->bbox[2] || r_patches[j]->firstvert[deflvl][l].v_point[2] > surf->bbox[5])
612 {
613 addpatch = false;
614 break;
615 }
616 }
617 #endif
618
619 if (addpatch) // Add the patch j in the group of i
620 {
621 r_patchesgroups[r_numpatchesgroups[0]].Add(j);
622 rel[j] = true;
623 patchadded = true;
624 break;
625 }
626 }
627 }
628 } while(patchadded);
629
630 // the new group is finished
631 ++r_numpatchesgroups[0];
632 }
633
634 delete [] rel;
635
636 // Calculate the middle vertex of each group
637 // TODO: Calculate the bounding box and make tests with the bounding box
638 int nverts;
639 for (i = 0; i < r_numpatchesgroups[0]; ++i)
640 {
641 nverts = 0;
642 surf = r_patches[r_patchesgroups[i].surfidx[0]];
643 r_patchesgroups[i].middle[0] = r_patchesgroups[i].middle[1] = r_patchesgroups[i].middle[2] = 0.f;
644 r_patchesgroups[i].bbox[0] = surf->bbox[0];
645 r_patchesgroups[i].bbox[1] = surf->bbox[1];
646 r_patchesgroups[i].bbox[2] = surf->bbox[2];
647 r_patchesgroups[i].bbox[3] = surf->bbox[3];
648 r_patchesgroups[i].bbox[4] = surf->bbox[4];
649 r_patchesgroups[i].bbox[5] = surf->bbox[5];
650 for (j = 0; j < r_patchesgroups[i].nsurf; ++j)
651 {
652 // middle vertex
653 for (k = 0; k < r_patches[r_patchesgroups[i].surfidx[j]]->numverts[deflvl]; ++k)
654 {
655 r_patchesgroups[i].middle[0] += r_patches[r_patchesgroups[i].surfidx[j]]->firstvert[deflvl][k].v_point[0];
656 r_patchesgroups[i].middle[1] += r_patches[r_patchesgroups[i].surfidx[j]]->firstvert[deflvl][k].v_point[1];
657 r_patchesgroups[i].middle[2] += r_patches[r_patchesgroups[i].surfidx[j]]->firstvert[deflvl][k].v_point[2];
658 ++nverts;
659 }
660
661 // bounding box
662 if (j > 0) // j = 0 is already done before the loop
663 {
664 r_patchesgroups[i].bbox[0] = min(r_patchesgroups[i].bbox[0], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[0]);
665 r_patchesgroups[i].bbox[1] = min(r_patchesgroups[i].bbox[1], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[1]);
666 r_patchesgroups[i].bbox[2] = min(r_patchesgroups[i].bbox[2], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[2]);
667 r_patchesgroups[i].bbox[3] = max(r_patchesgroups[i].bbox[3], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[3]);
668 r_patchesgroups[i].bbox[4] = max(r_patchesgroups[i].bbox[4], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[4]);
669 r_patchesgroups[i].bbox[5] = max(r_patchesgroups[i].bbox[5], r_patches[r_patchesgroups[i].surfidx[j]]->bbox[5]);
670 }
671
672 }
673 // size
674 r_patchesgroups[i].size = max(r_patchesgroups[i].bbox[3]-r_patchesgroups[i].bbox[0],
675 r_patchesgroups[i].bbox[4]-r_patchesgroups[i].bbox[1]);
676 r_patchesgroups[i].size = max(r_patchesgroups[i].size, r_patchesgroups[i].bbox[5]-r_patchesgroups[i].bbox[2]);
677
678 if (!nverts) ThrowException(DIVISION_BY_ZERO, "Q3BSP::CreatePatchesGroups.nverts");
679 r_patchesgroups[i].middle[0] /= (float) nverts;
680 r_patchesgroups[i].middle[1] /= (float) nverts;
681 r_patchesgroups[i].middle[2] /= (float) nverts;
682 }
683
684 gConsole->Insertln("\t%d patch groups created", r_numpatchesgroups[0]);
685 }
686
687 // Face comparator for qsort
FaceCmp(const void * a,const void * b)688 int Q3BSP::FaceCmp(const void *a, const void *b)
689 {
690 return ((render_face_s*)a)->sort_value - ((render_face_s*)b)->sort_value;
691 }
692
693 // Report info of the bsp
Report(void)694 void Q3BSP::Report(void)
695 {
696 int i;
697
698 gLogFile->OpenFile();
699
700 // report info
701 gConsole->Insertln("BSP Report:");
702 gConsole->Insertln("\tnum surfaces = %d", r_numsurfaces[0]);
703 gConsole->Insertln("\t\tnum faces = %d", r_numfaces[0]);
704 gConsole->Insertln("\t\tnum patches = %d (%d groups)", r_numpatches[0], r_numpatchesgroups[0]);
705 gConsole->Insertln("\t\tnum meshes = %d", r_nummeshes[0]);
706 gConsole->Insertln("\t\tnum flares = %d", r_numflares[0]);
707 gConsole->Insertln("\tnum lightmaps = %d", r_numlightmaps[0]);
708 gConsole->Insertln("\tnum shaders = %d", r_numshaders[0]);
709 gConsole->Insertln("\tnum planes = %d", r_numplanes[0]);
710 gConsole->Insertln("\tnum nodes = %d", r_numnodes[0]);
711 gConsole->Insertln("\tnum leafs = %d", r_numleafs[0]);
712 gConsole->Insertln("\tnum leaffaces = %d", r_numleaffaces[0]);
713 gConsole->Insertln("\tnum brushes = %d", r_numbrushes[0]);
714 gConsole->Insertln("\tnum leafbrushes = %d", r_numleafbrushes[0]);
715 gConsole->Insertln("\tnum leafpatches = %d", r_numleafpatches[0]);
716 gConsole->Insertln("\tnum models = %d", r_nummodels[0]);
717 for (i = 1; i < r_nummodels[0]; ++i) // model 0 is the map
718 {
719 gConsole->Insertln("\t\tmodel %d:", i);
720 gConsole->Insertln("\t\t\tfirstface %d", r_models[i].firstface);
721 gConsole->Insertln("\t\t\tnumfaces %d", r_models[i].numfaces);
722 }
723 gConsole->Insertln("\tnum verts = %d", r_numverts[0]);
724 gConsole->Insertln("\tnum elems = %d", r_numelems[0]);
725 gConsole->Insertln("\tnum lightvols = %d", r_numlightvols[0]);
726 gConsole->Insertln("\tnum effects = %d", r_numeffects[0]);
727
728 gLogFile->CloseFile();
729 }
730
GetEntities(void)731 EntityManager* Q3BSP::GetEntities(void)
732 {
733 return r_entities;
734 }
735
736 //-----------------------------------------------------------------------------
737 // Updating and Drawing
738 //-----------------------------------------------------------------------------
739
740 // Render a new frame of the bsp
Update(void)741 void Q3BSP::Update(void)
742 {
743 if (r_drawworld.ivalue) UpdateFaces();
744 if (r_skybox && r_drawsky.ivalue) UpdateSky();
745 }
746
UpdateFaces(void)747 void Q3BSP::UpdateFaces(void)
748 {
749 Camera *camera = gRender->current_camera;
750
751 // Find camera cluster
752 int new_cam_leaf = FindLeaf(camera->pos);
753 cleaf_t* currleaf = &r_leafs[new_cam_leaf];
754 int i;
755
756 if (new_cam_leaf != cam_leaf)
757 {
758 cam_leaf = new_cam_leaf;
759
760 if (r_showlbrushes.ivalue)
761 {
762 char str[1024];
763 sprintf(str, "%d leafbrushes: ", currleaf->numleafbrushes);
764 for (int i = 0; i < currleaf->numleafbrushes; ++i)
765 sprintf(str, "%s%d/", str, r_leafbrushes[currleaf->firstleafbrush+i]);
766 gConsole->Insertln(str);
767 }
768
769 if (r_showcamleaf.ivalue)
770 {
771 gConsole->Insertln("leaf: %d\tmiddle: %d %d %d",
772 new_cam_leaf,
773 (currleaf->bbox[0]+currleaf->bbox[3])/2,
774 (currleaf->bbox[1]+currleaf->bbox[4])/2,
775 (currleaf->bbox[2]+currleaf->bbox[5])/2);
776 }
777 }
778
779 // Check if camera is in water
780 // FIXME: Can I do that somewhere else... here is not really the good place !
781 camera->inWater = false;
782 if (currleaf->numleafbrushes)
783 {
784 Shader* shad;
785 int *lbrush = &r_leafbrushes[currleaf->firstleafbrush];
786 for (i = 0; i < currleaf->numleafbrushes; ++i, lbrush++)
787 {
788 if (!(shad = world->shaders.GetShader(r_brushes[*lbrush].shader))) continue;
789 if (shad->content_flags & CONTENTS_WATER &&
790 PointInsideBrush(*lbrush, camera->pos))
791 {
792 camera->inWater = true;
793 break;
794 }
795 }
796 }
797
798 if (currleaf->cluster != cam_cluster && !r_lockpvs.ivalue)
799 {
800 if (r_showcluster.ivalue)
801 gConsole->Insertln("cluster: %d\tarea: %d", currleaf->cluster, currleaf->area);
802
803 ++nodecount;
804 MarkLeafs((r_novis.ivalue)?-1:currleaf->cluster);
805 cam_cluster = currleaf->cluster;
806 }
807
808 num_leafs = 0;
809 ++viscount; // Set current visibility number (only faces with this number are rendered in the frame)
810 WalkTree(0, true);
811
812 if (r_showleafs.ivalue && num_leafs != num_leafs_last_frame)
813 {
814 gConsole->Insertln("number of visible leafs: %d/%d", num_leafs, r_numleafs[0]);
815 num_leafs_last_frame = num_leafs;
816 }
817
818 // Update patches levels
819 if (!r_nocurves.ivalue)
820 {
821 float dx1, dy1, dz1, dx2, dy2, dz2, d[3], v;
822 for (i = 0; i < r_numpatchesgroups[0]; ++i)
823 {
824 if (!r_nofrustum.ivalue && !camera->BoxInFrustum(r_patchesgroups[i].bbox)) continue;
825 dx1 = camera->pos[0]-r_patchesgroups[i].bbox[0];
826 dx2 = camera->pos[0]-r_patchesgroups[i].bbox[3];
827 dy1 = camera->pos[1]-r_patchesgroups[i].bbox[1];
828 dy2 = camera->pos[1]-r_patchesgroups[i].bbox[4];
829 dz1 = camera->pos[2]-r_patchesgroups[i].bbox[2];
830 dz2 = camera->pos[2]-r_patchesgroups[i].bbox[5];
831 VectorSub(r_patchesgroups[i].middle, camera->pos, d);
832 dx1 *= dx1; dx2 *= dx2;
833 dy1 *= dy1; dy2 *= dy2;
834 dz1 *= dz1; dz2 *= dz2;
835
836 v = (min(dx1,dx2)+min(dy1,dy2)+min(dz1,dz2)+d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);
837 if (r_patchesgroups[i].size > 0) v /= r_patchesgroups[i].size;
838 r_patchesgroups[i].Update(v, r_patches);
839 }
840 }
841 }
842
UpdateSky(void)843 void Q3BSP::UpdateSky(void)
844 {
845 if (r_fillside.ivalue > 5)
846 {
847 // All sky planes are rendered
848 r_skybox->NewFrame(1);
849 }
850 else if (r_fillside.ivalue < 0)
851 {
852 // Sky planes are clipped and rendered if visible
853 r_skybox->NewFrame(0);
854 r_skybox->AutoFill(gRender->current_camera, r_novis.ivalue?-1:viscount);
855 }
856 else
857 {
858 // Only sky plane "r_fillside.ivalue" is rendered
859 // Report to sky class to know about sky planes values
860 r_skybox->NewFrame(0);
861 r_skybox->FillSide(r_fillside.ivalue);
862 }
863 }
864
865 // Finds leaf of the current position
FindLeaf(vec3_t p,int headnode)866 int Q3BSP::FindLeaf(vec3_t p, int headnode)
867 {
868 cnode_t *node;
869 cplane_t *plane;
870 int idx;
871 float dot;
872
873 idx = headnode;
874
875 while (idx >= 0) // if idx < 0 we have found a leaf.
876 {
877 node = &r_nodes[idx];
878 plane = r_planes + node->planeidx;
879
880 if (plane->type < PLANE_NON_AXIAL)
881 dot = p[plane->type] - plane->dist;
882 else
883 dot = DotProduct(p, plane->normal) - plane->dist;
884
885 if (dot >= 0.0f) idx = node->children[0];
886 else idx = node->children[1];
887 }
888
889 return ~idx; //return (-(idx+1));
890 }
891
892 // update leaf framenum according to the visibility
893 // TODO: write 8 leafs at once
MarkLeafs(int vis_cluster)894 void Q3BSP::MarkLeafs(int vis_cluster)
895 {
896 cnode_t *node;
897
898 if (!r_numvisibility[0] || vis_cluster == -1)
899 {
900 for (int i = 0; i < r_numleafs[0]; ++i)
901 {
902 r_leafs[i].framenum = nodecount;
903 node = r_leafs[i].parent;
904 while (node)
905 {
906 if (node->framenum == nodecount) break;
907
908 node->framenum = nodecount;
909 node = node->parent;
910 }
911 }
912 }
913 else
914 {
915 for (int i = 0; i < r_numleafs[0]; ++i)
916 {
917 if (r_leafs[i].cluster > -1 && BSP_TESTVIS(vis_cluster, r_leafs[i].cluster))
918 {
919 r_leafs[i].framenum = nodecount;
920 node = r_leafs[i].parent;
921 while (node)
922 {
923 if (node->framenum == nodecount) break;
924
925 node->framenum = nodecount;
926 node = node->parent;
927 }
928 }
929 }
930 }
931 }
932
933 /**
934 * Walk trough pv nodes inside the frustum.
935 * @todo We could iterate while we have only one visible node.
936 */
WalkTree(int idx,bool checkFrustum)937 void Q3BSP::WalkTree(int idx, bool checkFrustum)
938 {
939 if (idx >= 0) // node
940 {
941 if (r_nodes[idx].framenum != nodecount) return;
942
943 if (r_nofrustum.ivalue || checkFrustum)
944 {
945 switch (gRender->current_camera->BoxInFrustum(r_nodes[idx].bbox))
946 {
947 case COMPLETE_OUT:
948 return;
949 case COMPLETE_IN:
950 checkFrustum = false;
951 break;
952 default:
953 break;
954 }
955 }
956 WalkTree(r_nodes[idx].children[0], checkFrustum); // front
957 WalkTree(r_nodes[idx].children[1], checkFrustum); // back
958 }
959 else // leaf
960 {
961 idx = ~idx;
962 if (r_leafs[idx].framenum != nodecount) return; // cluster not visible
963
964 if (r_nofrustum.ivalue || checkFrustum)
965 if (!gRender->current_camera->BoxInFrustum(r_leafs[idx].bbox)) return;
966
967 int *p = &r_leaffaces[r_leafs[idx].firstleafface];
968 int i = r_leafs[idx].numleaffaces;
969 while (i--) r_surfaces[*p++].framenum = viscount;
970 ++num_leafs;
971 }
972 }
973
Render(void)974 void Q3BSP::Render(void)
975 {
976 gRender->gridpass = 0;
977
978 if (r_drawsky.ivalue && r_skybox) DrawSky();
979 if (r_drawworld.ivalue) DrawFaces();
980 // if (r_drawmodels.ivalue) DrawModels();
981 gRender->ForceFlush();
982
983 if (r_grid.ivalue)
984 {
985 gRender->gridpass = 1;
986
987 if (r_drawsky.ivalue && r_skybox) DrawSky();
988 if (r_drawworld.ivalue) DrawFaces();
989 // if (r_drawmodels.ivalue) DrawModels();
990 gRender->ForceFlush();
991
992 gRender->gridpass = 0;
993
994 // Rendering origin and axis
995 GLboolean depthtest, texture;
996 glGetBooleanv(GL_TEXTURE_2D, &texture);
997 glGetBooleanv(GL_DEPTH_TEST, &depthtest);
998 glDisable(GL_TEXTURE_2D);
999 glDisable(GL_DEPTH_TEST);
1000
1001 glBegin(GL_LINES);
1002 glColor3f(1.f, 0.f, 0.f);
1003 glVertex3f(0, 0, 0);
1004 glVertex3f(1000, 0, 0);
1005 glEnd();
1006
1007 glBegin(GL_LINES);
1008 glColor3f(0.f, 1.f, 0.f);
1009 glVertex3f(0, 0, 0);
1010 glVertex3f(0, 1000, 0);
1011 glEnd();
1012
1013 glBegin(GL_LINES);
1014 glColor3f(0.f, 0.f, 1.f);
1015 glVertex3f(0, 0, 0);
1016 glVertex3f(0, 0, 1000);
1017 glEnd();
1018 gRender->CheckGLError(19);
1019
1020 if (depthtest) { glEnable(GL_DEPTH_TEST); gRender->CheckGLError(); }
1021 if (texture) { glEnable(GL_TEXTURE_2D); gRender->CheckGLError(); }
1022 }
1023
1024 if (r_showbbox.ivalue) DrawBoundingBoxes();
1025 if (v_selectsurface.ivalue >= 0 && v_selectsurface.ivalue < r_numsurfaces[0])
1026 {
1027 colour_t colorline = { 255, 255, 255, 255 };
1028 colour_t colorface = { 0, 0, 255, 32};
1029 DrawBoundingBox(r_surfaces[v_selectsurface.ivalue].bbox, colorline, colorface);
1030 }
1031 if (v_selectpatch.ivalue >= 0 && v_selectpatch.ivalue < r_numpatches[0])
1032 {
1033 colour_t colorline = { 255, 255, 255, 255 };
1034 colour_t colorface = { 0, 255, 0, 32};
1035 DrawBoundingBox(r_patches[v_selectpatch.ivalue]->bbox, colorline, colorface);
1036 }
1037 if (v_selectmodel.ivalue >= 0 && v_selectmodel.ivalue < r_nummodels[0])
1038 {
1039 colour_t colorline = { 255, 255, 255, 255 };
1040 colour_t colorface = { 255, 0, 0, 32};
1041 DrawBoundingBox(r_models[v_selectmodel.ivalue].bbox, colorline, colorface);
1042 }
1043
1044 if (r_normals.ivalue) DrawNormals();
1045 }
1046
DrawFaces(void)1047 void Q3BSP::DrawFaces(void)
1048 {
1049 Surface *surf;
1050 Shader *shad;
1051 int last_shader = -1;
1052 int last_lightmap = -1;
1053 int last_effect = -2;
1054
1055 for (int i = 0; i < r_numsurfaces[0]; ++i)
1056 {
1057 surf = face_list[i].face;
1058
1059 if (surf->model > 0)
1060 {
1061 if (!r_drawmodels.ivalue) continue;
1062 if (surf->model >= r_nummodels[0]) continue;
1063 if (!r_models[surf->model].render) continue;
1064 // Tricky way that disables PVS test for models
1065 // TODO: link entities into tree
1066 }
1067 else if (!surf || surf->shader < 0 ||
1068 (!r_novis.ivalue && surf->framenum != viscount)) continue; // PVS optimization
1069
1070 shad = world->shaders.GetShader(surf->shader);
1071
1072 // Sky surfaces are only renderd if specified with r_surfsky
1073 // variable of if it has an effect (cf. q3tourney5)
1074 if (shad->surface_flags & SURF_SKY && surf->effect < 0 && !r_surfsky.ivalue) continue;
1075
1076 // Don't draw portals
1077 // TODO: Finish this - portals are not implemented yet
1078 if (r_noportals.ivalue && shad->flags & SF_PORTAL) continue;
1079
1080 if (!r_nofrustum.ivalue)
1081 {
1082 if (surf->model > 0 && surf->model < r_nummodels[0])
1083 {
1084 if (r_models[surf->model].entity)
1085 {
1086 if (!gRender->current_camera->BoxInFrustum(r_models[surf->model].entity->bbox)) continue;
1087 }
1088 else
1089 {
1090 if (!gRender->current_camera->BoxInFrustum(r_models[surf->model].bbox)) continue;
1091 }
1092 }
1093 else if (surf->facetype == FACETYPE_PATCH ||
1094 surf->facetype == FACETYPE_MESH)
1095 {
1096 if (!gRender->current_camera->BoxInFrustum(surf->bbox)) continue;
1097 }
1098 }
1099
1100 if (surf->shader != last_shader ||
1101 surf->lm_texnum != last_lightmap ||
1102 surf->effect != last_effect)
1103 {
1104 gRender->SetRenderState(shad,
1105 surf->lm_texnum==~0?~0:r_lightmapinfos[surf->lm_texnum].num,
1106 (surf->effect>-1&&r_numeffects[0]&&surf->facetype!=FACETYPE_FLARE)?world->shaders.GetShader(r_effects[surf->effect].shader):NULL);
1107 last_shader = surf->shader;
1108 last_lightmap = surf->lm_texnum;
1109 last_effect = surf->effect;
1110 }
1111
1112 if (surf->model > 0 && r_models[surf->model].entity)
1113 {
1114 gRender->ForceFlush();
1115 glMatrixMode(GL_MODELVIEW);
1116 glPushMatrix();
1117 glMultMatrixf(r_models[surf->model].entity->transformation);
1118 gRender->CheckGLError(2);
1119 }
1120
1121 switch (surf->facetype)
1122 {
1123 case FACETYPE_NORMAL: // Normal faces
1124 if (r_nofaces.ivalue) break;
1125
1126 // Following test causes problems on some faces if camera has negative z component
1127 // if ((shad->cull == CULL_FRONT && DotProduct(surf->v_norm, gRender->current_camera->pos) > surf->dist) ||
1128 // (shad->cull == CULL_BACK && DotProduct(surf->v_norm, gRender->current_camera->pos) < surf->dist)) break;
1129
1130 gRender->PushTriangles(surf);
1131 break;
1132 case FACETYPE_PATCH: // BezierPatches
1133 if (r_nocurves.ivalue) break;
1134 gRender->PushTriangles(surf);
1135 break;
1136 case FACETYPE_MESH: // Meshes
1137 if (r_nomesh.ivalue) break;
1138 gRender->PushTriangles(surf);
1139 break;
1140 case FACETYPE_FLARE: // Flares
1141 break; // not supported yet
1142 if (r_noflares.ivalue) break;
1143 gRender->PushTriangles(surf);
1144 break;
1145 default:
1146 break;
1147 }
1148
1149 if (surf->model > 0 && r_models[surf->model].entity)
1150 {
1151 gRender->ForceFlush();
1152 glPopMatrix();
1153 gRender->CheckGLError();
1154 }
1155 }
1156 }
1157 /*
1158 void Q3BSP::DrawModels(void)
1159 {
1160 Surface *surf;
1161 Shader *shad;
1162 int last_shader = -1;
1163 int last_lightmap = -1;
1164 int last_effect = -2;
1165 int lod = 0;
1166 cmodel_t *model = NULL;
1167
1168 for (int i = 1; i < r_nummodels[0]; ++i)
1169 {
1170 if (!r_models[i].numfaces) continue;
1171
1172 lod = 0;
1173 model = &r_models[i];
1174
1175 if (model->entity)
1176 {
1177 gRender->ForceFlush();
1178 glMatrixMode(GL_MODELVIEW);
1179 glPushMatrix();
1180 glMultMatrixf(model->entity->transformation);
1181 gRender->checkGLError(3);
1182
1183 // Get the lod for rendering
1184
1185 if (model->entity->num_lods)
1186 {
1187 vec_t m[16];
1188 glGetFloatv(GL_MODELVIEW_MATRIX, m);
1189 vec3_t dist;
1190 VectorCopy(&m[12], dist);
1191 // quick'n dirty lod based on distance
1192 // looks quite good though
1193 lod = (int) fabsf(dist[2]/200.f);
1194 if (lod > model->entity->num_lods-1) lod = model->entity->num_lods-1;
1195 }
1196
1197 model = model->entity->models[lod];
1198 }
1199
1200 if (!model) continue;
1201
1202 for (int j = 0; j < model->numfaces; ++j)
1203 {
1204 surf = &r_surfaces[model->firstface+j];
1205
1206 if (!(shad = world->shaders.GetShader(surf->shader))) continue;
1207
1208 // Sky surfaces are only renderd if specified with r_surfsky
1209 // variable of if it has an effect (cf. q3tourney5)
1210 if (shad->surface_flags & SURF_SKY && surf->effect < 0 && !r_surfsky.ivalue) continue;
1211
1212 // Don't draw portals
1213 // TODO: Finish this - portals are not implemented yet
1214 if (r_noportals.ivalue && shad->flags & SF_PORTAL) continue;
1215
1216 if (surf->shader != last_shader ||
1217 surf->lm_texnum != last_lightmap ||
1218 surf->effect != last_effect)
1219 {
1220 gRender->SetRenderState(shad,
1221 surf->lm_texnum==~0?~0:r_lightmapinfos[surf->lm_texnum].num,
1222 (surf->effect>-1&&r_numeffects[0]&&surf->facetype!=FACETYPE_FLARE)?world->shaders.GetShader(r_effects[surf->effect].shader):NULL);
1223 last_shader = surf->shader;
1224 last_lightmap = surf->lm_texnum;
1225 last_effect = surf->effect;
1226 }
1227
1228 switch (surf->facetype)
1229 {
1230 case FACETYPE_NORMAL: // Normal faces
1231 if (r_nofaces.ivalue) continue;
1232
1233 // Following test causes problems on some faces if camera has negative z component
1234 // if ((shad->cull == CULL_FRONT && DotProduct(surf->v_norm, gRender->current_camera->pos) > surf->dist) ||
1235 // (shad->cull == CULL_BACK && DotProduct(surf->v_norm, gRender->current_camera->pos) < surf->dist)) continue;
1236
1237 gRender->PushTriangles(surf);
1238 break;
1239 case FACETYPE_PATCH: // BezierPatches
1240 if (r_nocurves.ivalue) continue;
1241 gRender->PushTriangles(surf);
1242 break;
1243 case FACETYPE_MESH: // Meshes
1244 if (r_nomesh.ivalue) continue;
1245 gRender->PushTriangles(surf);
1246 break;
1247 case FACETYPE_FLARE: // Flares
1248 break; // not supported yet
1249 if (r_noflares.ivalue) continue;
1250 gRender->PushTriangles(surf);
1251 break;
1252 default:
1253 break;
1254 }
1255 }
1256 if (model->entity)
1257 {
1258 gRender->ForceFlush();
1259 glPopMatrix();
1260 gRender->checkGLError();
1261 }
1262 }
1263 }
1264 */
DrawSky(void)1265 void Q3BSP::DrawSky(void)
1266 {
1267 Shader *shad = NULL;
1268
1269 if (r_skybox->clouds_shader >= 0)
1270 shad = world->shaders.GetShader(r_skybox->clouds_shader);
1271
1272 if (!shad) return;
1273
1274 // Don't need to test depth value, sky is rendered as background
1275 glDisable(GL_DEPTH_TEST);
1276
1277 // Center skybox on camera to give the illusion of a larger space
1278 glMatrixMode(GL_MODELVIEW);
1279 glPushMatrix();
1280 glTranslatef(gRender->current_camera->pos[0],
1281 gRender->current_camera->pos[1],
1282 gRender->current_camera->pos[2]);
1283 glScalef(r_skybox->skyboxsize, r_skybox->skyboxsize, r_skybox->skyboxsize);
1284 gRender->CheckGLError(5);
1285
1286 // Farbox and NearBox
1287 if (shad->sky_params.num_layers)
1288 {
1289 if (r_skybox->usedskysides[0]) { gRender->SetRenderState(r_skybox->box_shader[0]); r_skybox->skyface[0].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[0]); }
1290 if (r_skybox->usedskysides[1]) { gRender->SetRenderState(r_skybox->box_shader[1]); r_skybox->skyface[1].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[1]); }
1291 if (r_skybox->usedskysides[2]) { gRender->SetRenderState(r_skybox->box_shader[2]); r_skybox->skyface[2].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[2]); }
1292 if (r_skybox->usedskysides[3]) { gRender->SetRenderState(r_skybox->box_shader[3]); r_skybox->skyface[3].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[3]); }
1293 if (r_skybox->usedskysides[4]) { gRender->SetRenderState(r_skybox->box_shader[4]); r_skybox->skyface[4].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[4]); }
1294 if (r_skybox->usedskysides[5]) { gRender->SetRenderState(r_skybox->box_shader[5]); r_skybox->skyface[5].currentlevel = 1; gRender->PushTriangles(&r_skybox->skyface[5]); }
1295 }
1296
1297 // Clouds
1298 if (shad->num_layers)
1299 {
1300 gRender->SetRenderState(shad);
1301 if (r_skybox->usedskysides[0]) { r_skybox->skyface[0].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[0], r_skybox->framenum[0]); }
1302 if (r_skybox->usedskysides[1]) { r_skybox->skyface[1].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[1], r_skybox->framenum[1]); }
1303 if (r_skybox->usedskysides[2]) { r_skybox->skyface[2].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[2], r_skybox->framenum[2]); }
1304 if (r_skybox->usedskysides[3]) { r_skybox->skyface[3].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[3], r_skybox->framenum[3]); }
1305 if (r_skybox->usedskysides[4]) { r_skybox->skyface[4].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[4], r_skybox->framenum[4]); }
1306 if (r_skybox->usedskysides[5]) { r_skybox->skyface[5].currentlevel = 0; gRender->PushTriangles(&r_skybox->skyface[5], r_skybox->framenum[5]); }
1307 }
1308
1309 // Flushing sky
1310 gRender->ForceFlush();
1311
1312 // Restore world space
1313 glMatrixMode(GL_MODELVIEW);
1314 glPopMatrix();
1315
1316 // Re-enable depth test for other faces
1317 glEnable(GL_DEPTH_TEST);
1318
1319 // clearing depth buffer
1320 // Note: I would prefer using the glDepthMask() function but depth masking state
1321 // is sometimes modified by shaders so and is not always constant.
1322 State::setDepthWrite(GL_TRUE); // must be true before clearing!
1323 glClear(GL_DEPTH_BUFFER_BIT);
1324 gRender->CheckGLError(4);
1325 }
1326
DrawBoundingBoxes(void)1327 void Q3BSP::DrawBoundingBoxes(void)
1328 {
1329 int i;
1330 Surface *surf;
1331
1332 colour_t colorline, colorface;
1333
1334 for (i = 0; i < r_numsurfaces[0]; ++i)
1335 {
1336 surf = face_list[i].face;
1337
1338 if (surf->facetype == FACETYPE_PATCH)
1339 {
1340 ColorSet(colorline, 255, 255, 255, 255);
1341 ColorSet(colorface, 0, 255, 255, 8);
1342 }
1343 else if (surf->facetype == FACETYPE_MESH)
1344 {
1345 ColorSet(colorline, 255, 255, 255, 255);
1346 ColorSet(colorface, 255, 255, 0, 8);
1347 }
1348 else if (surf->facetype == FACETYPE_NORMAL)
1349 {
1350 ColorSet(colorline, 255, 255, 255, 255);
1351 ColorSet(colorface, 255, 0, 255, 8);
1352 }
1353 else
1354 {
1355 ColorSet(colorline, 255, 255, 255, 255);
1356 ColorSet(colorface, 255, 0, 0, 8);
1357 }
1358
1359 if (surf->model > 0 && surf->model < r_nummodels[0])
1360 {
1361 // TODO Update model
1362 if (!r_drawmodels.ivalue) continue;
1363 if (r_nofrustum.ivalue && gRender->current_camera->BoxInFrustum(surf->bbox))
1364 DrawBoundingBox(surf->bbox, colorline, colorface);
1365 else if (r_models[surf->model].entity && gRender->current_camera->BoxInFrustum(r_models[surf->model].entity->bbox))
1366 DrawBoundingBox(r_models[surf->model].entity->bbox, colorline, colorface);
1367 }
1368 else if (!surf || surf->shader < 0 ||
1369 (!r_novis.ivalue && surf->framenum != viscount)) continue; // PVS optimisation
1370
1371 switch (surf->facetype)
1372 {
1373 case FACETYPE_PATCH:
1374 case FACETYPE_MESH:
1375 if (r_nofrustum.ivalue || gRender->current_camera->BoxInFrustum(surf->bbox))
1376 DrawBoundingBox(surf->bbox, colorline, colorface);
1377 break;
1378 default:
1379 break;
1380 }
1381 }
1382
1383 // Patches groups (for debug)
1384 ColorSet(colorline, 255, 255, 255, 255);
1385 ColorSet(colorface, 0, 255, 0, 8);
1386 for (i = 0; i < r_numpatchesgroups[0]; ++i)
1387 DrawBoundingBox(r_patchesgroups[i].bbox, colorline, colorface);
1388 }
1389
DrawBoundingBox(bboxf_t bbox,colour_t colorline,colour_t colorface)1390 void Q3BSP::DrawBoundingBox(bboxf_t bbox, colour_t colorline, colour_t colorface)
1391 {
1392 vec3_t v[8] = {
1393 { bbox[0], bbox[1], bbox[2] },
1394 { bbox[3], bbox[1], bbox[2] },
1395 { bbox[3], bbox[1], bbox[5] },
1396 { bbox[0], bbox[1], bbox[5] },
1397 { bbox[0], bbox[4], bbox[2] },
1398 { bbox[3], bbox[4], bbox[2] },
1399 { bbox[3], bbox[4], bbox[5] },
1400 { bbox[0], bbox[4], bbox[5] }
1401 };
1402
1403 State::setAlphaFunc(GL_ALWAYS, 0);
1404 State::setCulling(CULL_NONE); // disable culling
1405
1406 GLboolean texture, depthtest;
1407 glGetBooleanv(GL_TEXTURE_2D, &texture);
1408 glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1409 glDisable(GL_TEXTURE_2D);
1410 glDisable(GL_DEPTH_TEST);
1411 gRender->CheckGLError(4);
1412
1413 State::setBlend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1414 glColor4ubv(colorface);
1415 glBegin(GL_QUADS);
1416 glVertex3fv(v[0]);
1417 glVertex3fv(v[1]);
1418 glVertex3fv(v[2]);
1419 glVertex3fv(v[3]);
1420
1421 glVertex3fv(v[4]);
1422 glVertex3fv(v[5]);
1423 glVertex3fv(v[6]);
1424 glVertex3fv(v[7]);
1425
1426 glVertex3fv(v[0]);
1427 glVertex3fv(v[1]);
1428 glVertex3fv(v[5]);
1429 glVertex3fv(v[4]);
1430
1431 glVertex3fv(v[1]);
1432 glVertex3fv(v[5]);
1433 glVertex3fv(v[6]);
1434 glVertex3fv(v[2]);
1435
1436 glVertex3fv(v[2]);
1437 glVertex3fv(v[6]);
1438 glVertex3fv(v[7]);
1439 glVertex3fv(v[3]);
1440
1441 glVertex3fv(v[3]);
1442 glVertex3fv(v[7]);
1443 glVertex3fv(v[4]);
1444 glVertex3fv(v[0]);
1445 glEnd();
1446 State::setBlend(GL_ONE, GL_ZERO);
1447
1448 glColor4ubv(colorline);
1449 gRender->CheckGLError();
1450
1451 glBegin(GL_LINE_LOOP);
1452 glVertex3fv(v[0]);
1453 glVertex3fv(v[1]);
1454 glVertex3fv(v[2]);
1455 glVertex3fv(v[3]);
1456 glEnd();
1457
1458 glBegin(GL_LINE_LOOP);
1459 glVertex3fv(v[4]);
1460 glVertex3fv(v[5]);
1461 glVertex3fv(v[6]);
1462 glVertex3fv(v[7]);
1463 glEnd();
1464
1465 glBegin(GL_LINES);
1466 glVertex3fv(v[0]);
1467 glVertex3fv(v[4]);
1468 glVertex3fv(v[1]);
1469 glVertex3fv(v[5]);
1470 glVertex3fv(v[2]);
1471 glVertex3fv(v[6]);
1472 glVertex3fv(v[3]);
1473 glVertex3fv(v[7]);
1474 glEnd();
1475
1476 gRender->CheckGLError(53);
1477
1478 if (texture) { glEnable(GL_TEXTURE_2D); gRender->CheckGLError(); }
1479 if (depthtest) { glEnable(GL_DEPTH_TEST); gRender->CheckGLError(); }
1480 }
1481
DrawNormals(void)1482 void Q3BSP::DrawNormals(void)
1483 {
1484 vec3_t vnorm;
1485
1486 GLboolean texture, depthtest;
1487 glGetBooleanv(GL_TEXTURE_2D, &texture);
1488 glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1489 glDisable(GL_TEXTURE_2D);
1490 glDisable(GL_DEPTH_TEST);
1491 gRender->CheckGLError(4);
1492
1493 glColor3f(1.f, 1.f, 1.f);
1494
1495 glBegin(GL_LINES);
1496 for (int i = 0; i < r_numverts[0]; ++i)
1497 {
1498 VectorMA(r_verts[i].v_point, fabsf(r_normals.fvalue), r_verts[i].v_norm, vnorm);
1499 glVertex3fv(r_verts[i].v_point);
1500 glVertex3fv(vnorm);
1501 }
1502 glEnd();
1503 gRender->CheckGLError(r_numverts[0]+3);
1504
1505 if (texture) { glEnable(GL_TEXTURE_2D); gRender->CheckGLError(); }
1506 if (depthtest) { glEnable(GL_DEPTH_TEST); gRender->CheckGLError(); }
1507 }
1508
1509 // ClearLink is used for new headnodes
ClearLink(link_t * l)1510 void Q3BSP::ClearLink(link_t *l)
1511 {
1512 l->prev = l->next = l;
1513 }
1514
RemoveLink(link_t * l)1515 void Q3BSP::RemoveLink(link_t *l)
1516 {
1517 l->next->prev = l->prev;
1518 l->prev->next = l->next;
1519 }
1520
InsertLinkBefore(link_t * l,link_t * before)1521 void Q3BSP::InsertLinkBefore(link_t *l, link_t *before)
1522 {
1523 l->next = before;
1524 l->prev = before->prev;
1525 l->prev->next = l;
1526 l->next->prev = l;
1527 }
1528
LinkEntity(Entity * ent)1529 void Q3BSP::LinkEntity(Entity* ent)
1530 {
1531 // Put the entity in the BSP tree
1532 }
1533
UnlinkEntity(Entity * ent)1534 void Q3BSP::UnlinkEntity(Entity *ent)
1535 {
1536 // Remove the entity from the BSP tree
1537 }
1538
CreateNewModel(int * modelnum)1539 cmodel_t* Q3BSP::CreateNewModel(int *modelnum)
1540 {
1541 // No more free memory for models
1542 if (r_nummodels[0] == r_nummodels[1])
1543 {
1544 // TODO: Implement reallocation
1545 gConsole->Insertln("^1ERROR: Models buffer is too small for additional model.");
1546 return NULL;
1547 }
1548
1549 *modelnum = r_nummodels[0];
1550 return &r_models[r_nummodels[0]++];
1551 }
1552
CreateNewSurface(int facetype,int * facenum)1553 Surface* Q3BSP::CreateNewSurface(int facetype, int *facenum)
1554 {
1555 // No more free memory for surfaces
1556 if (r_numsurfaces[0] == r_numsurfaces[1])
1557 {
1558 // TODO: Implement reallocation
1559 gConsole->Insertln("^1ERROR: Faces buffer is too small for additional faces.");
1560 return NULL;
1561 }
1562
1563 switch (facetype)
1564 {
1565 case FACETYPE_NORMAL:
1566 r_surfaces[r_numsurfaces[0]].indextype = r_numfaces[1]++;
1567 break;
1568 case FACETYPE_PATCH:
1569 r_surfaces[r_numsurfaces[0]].indextype = r_numpatches[1]++;
1570 break;
1571 case FACETYPE_MESH:
1572 r_surfaces[r_numsurfaces[0]].indextype = r_nummeshes[1]++;
1573 break;
1574 case FACETYPE_FLARE:
1575 r_surfaces[r_numsurfaces[0]].indextype = r_numflares[1]++;
1576 break;
1577 default:
1578 gConsole->Insert("^1Invalid facetype!");
1579 return NULL;
1580 }
1581
1582 r_surfaces[r_numsurfaces[0]].facetype = facetype;
1583 face_list[r_numsurfaces[0]].face = &r_surfaces[r_numsurfaces[0]];
1584
1585 *facenum = r_numsurfaces[0];
1586 return &r_surfaces[r_numsurfaces[0]++];
1587 }
1588
1589 //-----------------------------------------------------------------------------
1590 // Data Loading Routines
1591 //-----------------------------------------------------------------------------
1592
1593 // Load Entities
LoadEntities(void)1594 void Q3BSP::LoadEntities(void)
1595 {
1596 char * ent; // Total entities lump
1597 int entitieslen = ReadLump(ENTITIES, (void**)&ent, 1);
1598
1599 r_entities = new EntityManager;
1600 if (!r_entities)
1601 {
1602 gConsole->Insertln("^1ERROR: Cannot allocate memory for entity manager.");
1603 return;
1604 }
1605
1606 if (!r_entities->Load(ent, entitieslen))
1607 {
1608 gConsole->Insertln("^1ERROR: entity loading aborted.");
1609 return;
1610 }
1611
1612 cake_free(ent);
1613 }
1614
1615 // Load Shaders
LoadShaders(void)1616 void Q3BSP::LoadShaders(void)
1617 {
1618 r_numshaders[0] = r_numshaders[1] = ReadLump(SHADERREFS, (void**)&r_shaderrefs, sizeof(shaderref_t));
1619 }
1620
1621 // Build clip planes
LoadPlanes(void)1622 void Q3BSP::LoadPlanes(void)
1623 {
1624 plane_t *planes;
1625
1626 r_numplanes[0] = r_numplanes[1] = ReadLump(_PLANES, (void**)&planes, sizeof(plane_t));
1627
1628 r_numplanes[1] += (MAX_CM_PLANES+12); // increase buffer because if will filled later
1629 r_planes = (cplane_t*) cake_malloc(r_numplanes[1]*sizeof(cplane_t), "Q3BSP::LoadPlanes.r_planes");
1630
1631 for (int i = 0; i < r_numplanes[0]; ++i)
1632 {
1633 r_planes[i].normal[0] = planes[i].normal[0];
1634 r_planes[i].normal[1] = planes[i].normal[1];
1635 r_planes[i].normal[2] = planes[i].normal[2];
1636 r_planes[i].dist = planes[i].dist;
1637
1638 CategorizePlane(&r_planes[i]);
1639 }
1640
1641 cake_free(planes); planes = NULL;
1642 }
1643
1644 // Load the nodes
LoadNodes(void)1645 void Q3BSP::LoadNodes(void)
1646 {
1647 node_t *nodes;
1648
1649 r_numnodes[0] = r_numnodes[1] = ReadLump(NODES, (void**)&nodes, sizeof(node_t));
1650
1651 r_numnodes[1] += (MAX_CM_NODES+6); // increase buffer because if will filled later
1652 r_nodes = (cnode_t*) cake_malloc(r_numnodes[1]*sizeof(cnode_t), "Q3BSP::LoadNodes.r_nodes");
1653
1654 for (int i = 0; i < r_numnodes[0]; ++i)
1655 {
1656 r_nodes[i].planeidx = nodes[i].plane;
1657 r_nodes[i].children[0] = nodes[i].children[0];
1658 r_nodes[i].children[1] = nodes[i].children[1];
1659 BoxCopy(nodes[i].bbox, r_nodes[i].bbox); // Copy the node bounding box
1660 }
1661
1662 cake_free(nodes); nodes = NULL;
1663 }
1664
1665 // this are the indices of the leafs to the faces and the brushes:
1666 // @todo this way it is very easy to load the map, but there is a lot of indirection
1667 // we could avoid that by using non-fixed sized leaf structures but that hurts me.
LoadLFaces(void)1668 void Q3BSP::LoadLFaces(void)
1669 {
1670 r_numleaffaces[0] = r_numleaffaces[1] = ReadLump(LFACES, (void**)&r_leaffaces, sizeof(int));
1671 }
1672
LoadLBrushes(void)1673 void Q3BSP::LoadLBrushes(void)
1674 {
1675 int *leafbrushes;
1676 r_numleafbrushes[0] = r_numleafbrushes[1] = ReadLump(LBRUSHES, (void**)&leafbrushes, sizeof(int));
1677
1678 r_numleafbrushes[1] += (MAX_CM_BRUSHES+1);
1679 r_leafbrushes = (int*) cake_malloc(r_numleafbrushes[1]*sizeof(int), "Q3BSP::LoadLBrushes.r_leafbrushes");
1680
1681 memcpy(r_leafbrushes, leafbrushes, r_numleafbrushes[0]*sizeof(int));
1682
1683 cake_free(leafbrushes);
1684 }
1685
1686 // Load the leafs
LoadLeafs(void)1687 void Q3BSP::LoadLeafs(void)
1688 {
1689 leaf_t *leafs;
1690 cbrush_t *brush;
1691
1692 r_numleafs[0] = r_numleafs[1] = ReadLump(LEAFS, (void**)&leafs, sizeof(leaf_t));
1693
1694 r_numleafs[1] += (MAX_CM_LEAFS+1);
1695 r_leafs = (cleaf_t*) cake_malloc(r_numleafs[1]*sizeof(cleaf_t), "Q3BSP::LoadLeafs.r_leafs");
1696
1697 emptyleaf = -1;
1698
1699 for (int i = 0; i < r_numleafs[0]; ++i)
1700 {
1701 r_leafs[i].parent = NULL;
1702 r_leafs[i].cluster = leafs[i].cluster;
1703 r_leafs[i].area = leafs[i].area;
1704 BoxCopy(leafs[i].bbox, r_leafs[i].bbox);
1705 r_leafs[i].firstleafface = leafs[i].firstface;
1706 r_leafs[i].numleaffaces = leafs[i].numfaces;
1707 r_leafs[i].firstleafbrush = leafs[i].firstbrush;
1708 r_leafs[i].numleafbrushes = leafs[i].numbrushes;
1709 r_leafs[i].firstleafpatch = 0;
1710 r_leafs[i].numleafpatches = 0;
1711 r_leafs[i].contents = 0;
1712
1713 // Update leaf content through brushes references
1714 for (int j = 0; j < r_leafs[i].numleafbrushes; ++j)
1715 {
1716 brush = &r_brushes[r_leafbrushes[r_leafs[i].firstleafbrush+j]];
1717 r_leafs[i].contents |= brush->contents;
1718 }
1719
1720 if (!r_leafs[i].contents) emptyleaf = i;
1721 }
1722
1723 // if map doesn't have an empty leaf - force one
1724 if (emptyleaf == -1)
1725 {
1726 if (r_numleafs[0] >= r_numleafs[1]) ThrowException(OVERFLOW_ERROR, "Q3BSP::LoadLeafs");
1727
1728 r_leafs[r_numleafs[0]].cluster = -1;
1729 r_leafs[r_numleafs[0]].area = -1;
1730 r_leafs[r_numleafs[0]].numleafbrushes = 0;
1731 r_leafs[r_numleafs[0]].contents = 0;
1732 r_leafs[r_numleafs[0]].firstleafbrush = 0;
1733
1734 gConsole->Insertln("Forging an empty leaf: %i", r_numleafs[0]);
1735 emptyleaf = r_numleafs[0]++;
1736 }
1737
1738 cake_free(leafs); leafs = NULL;
1739
1740 SetParent(0, NULL);
1741 }
1742
LoadModels(void)1743 void Q3BSP::LoadModels(void)
1744 {
1745 int i, j, m;
1746 model_t *models;
1747
1748 r_nummodels[0] = r_nummodels[1] = ReadLump(MODELS, (void**)&models, sizeof(model_t));
1749
1750 r_nummodels[1] += MAX_CM_MODELS;
1751 r_models = (cmodel_t*) cake_malloc(r_nummodels[1]*sizeof(cmodel_t), "Q3BSP::LoadModels.r_models");
1752 if (!r_models) ThrowException(ALLOCATION_ERROR, "Q3BSP::LoadModels.r_models");
1753
1754 for (i = 0; i < r_nummodels[0]; ++i)
1755 {
1756 #if 1
1757 BoxCopy(models[i].bbox, r_models[i].bbox);
1758 #else
1759 // spread the mins / maxs by a pixel
1760 r_models[i].bbox[0] = models[i].bbox[0] - 1;
1761 r_models[i].bbox[3] = models[i].bbox[3] + 1;
1762 r_models[i].bbox[1] = models[i].bbox[1] - 1;
1763 r_models[i].bbox[4] = models[i].bbox[4] + 1;
1764 r_models[i].bbox[2] = models[i].bbox[2] - 1;
1765 r_models[i].bbox[5] = models[i].bbox[5] + 1;
1766 #endif
1767 r_models[i].firstbrush = models[i].firstbrush;
1768 r_models[i].firstface = models[i].firstface;
1769 r_models[i].numbrushes = models[i].numbrushes;
1770 r_models[i].numfaces = models[i].numfaces;
1771
1772 r_models[i].entity = NULL;
1773 r_models[i].render = true;
1774
1775 // Associate faces with model
1776 Surface *surf = r_surfaces + r_models[i].firstface;
1777 j = r_models[i].numfaces;
1778 while (j--)
1779 {
1780 surf->model = i;
1781 ++surf;
1782 }
1783 /*
1784 if (i == 0)
1785 {
1786 r_models[i].headnode = 0;
1787 }
1788 else
1789 {
1790 r_models[i].headnode = -1 - r_numleafs[0];
1791
1792 while (r_numleafs[0] >= r_numleafs[1])
1793 {
1794 // force reallocation
1795 r_numleafs[1] += MAX_CM_LEAFS;
1796 if (!(r_leafs = (cleaf_t*) cake_realloc(r_leafs, r_numleafs[1]*sizeof(cleaf_t), "Q3BSP::LoadModels.r_leafs")))
1797 {
1798 gConsole->Insertln("^1Q3BSP::LoadModels.r_leafs: Cannot allocate required size");
1799 continue;
1800 }
1801 }
1802
1803 cleaf_t *bleaf = &r_leafs[r_numleafs[0]++];
1804 bleaf->numleafbrushes = r_models[i].numbrushes;
1805 bleaf->firstleafbrush = r_numleafbrushes[0];
1806 bleaf->contents = 0;
1807 bleaf->parent = NULL;
1808
1809 int *leafbrush = &r_leafbrushes[r_numleafbrushes[0]];
1810 for (j = 0; j < bleaf->numleafbrushes; j++, leafbrush++)
1811 {
1812 *leafbrush = r_models[i].firstbrush + j;
1813 bleaf->contents |= r_brushes[*leafbrush].contents;
1814 }
1815
1816 r_numleafbrushes[0] += bleaf->numleafbrushes;
1817 }
1818 */
1819 }
1820
1821 cake_free(models);
1822 models = NULL;
1823
1824 // Perform entities processing
1825 if (!r_entities->ProcessEntities(this))
1826 {
1827 gConsole->Insertln("^1ERROR: entity processing aborted.");
1828 return;
1829 }
1830
1831 // Associate entities with model
1832 for (i = 0; i < r_entities->num_entities; ++i)
1833 {
1834 m = r_entities->entities[i].model;
1835 if (m > 0 && m < r_nummodels[0])
1836 {
1837 r_entities->entities[i].SetModel(&r_models[m]);
1838 }
1839
1840 // Associate children
1841 for (j = 0; j < r_entities->entities[i].numchildren; ++j)
1842 {
1843 m = r_entities->entities[i].children[j]->model;
1844 if (m > 0 && m < r_nummodels[0])
1845 {
1846 r_entities->entities[i].children[j]->SetModel(&r_models[m]);
1847 }
1848 }
1849 }
1850 }
1851
LoadBrushes(void)1852 void Q3BSP::LoadBrushes(void)
1853 {
1854 brush_t *brushes;
1855 r_numbrushes[0] = r_numbrushes[1] = ReadLump(BRUSHES, (void**)&brushes, sizeof(brush_t));
1856
1857 r_numbrushes[1] += (MAX_CM_BRUSHES+1); // increase buffer because if will filled later
1858 r_brushes = (cbrush_t*) cake_malloc(r_numbrushes[1]*sizeof(cbrush_t), "Q3BSP::LoadBrushes.r_brushes");
1859
1860 for (int i = 0; i < r_numbrushes[0]; ++i)
1861 {
1862 r_brushes[i].shader = world->shaders.AddShader(r_shaderrefs[brushes[i].shader].name,
1863 r_shaderrefs[brushes[i].shader].surface_flags,
1864 r_shaderrefs[brushes[i].shader].content_flags);
1865 r_brushes[i].effect = -1;
1866 r_brushes[i].firstbrushside = brushes[i].firstside;
1867 r_brushes[i].numsides = brushes[i].numsides;
1868 r_brushes[i].checkcount = 0;
1869 if (brushes[i].shader >= 0 && brushes[i].shader < r_numshaders[0])
1870 r_brushes[i].contents = r_shaderrefs[brushes[i].shader].content_flags;
1871 else
1872 r_brushes[i].contents = 0;
1873 }
1874
1875 cake_free(brushes); brushes = NULL;
1876 }
1877
LoadBrushSides(void)1878 void Q3BSP::LoadBrushSides(void)
1879 {
1880 brushside_t* brushsides;
1881 r_numbrushsides[0] = r_numbrushsides[1] = ReadLump(BRUSH_SIDES, (void**)&brushsides, sizeof(brushside_t));
1882
1883 r_numbrushsides[1] += (MAX_CM_BRUSHSIDES+6); // increase buffer because if will filled later
1884 r_brushsides = (cbrushside_t*) cake_malloc(r_numbrushsides[1]*sizeof(cbrushside_t), "Q3BSP::LoadBrushSides.r_brushsides");
1885
1886 for (int i = 0; i < r_numbrushsides[0]; ++i)
1887 {
1888 r_brushsides[i].planeidx = brushsides[i].planeidx;
1889 r_brushsides[i].shader = world->shaders.AddShader(r_shaderrefs[brushsides[i].shader].name,
1890 r_shaderrefs[brushsides[i].shader].surface_flags,
1891 r_shaderrefs[brushsides[i].shader].content_flags);
1892 }
1893
1894 cake_free(brushsides);
1895 }
1896
LoadVerts(void)1897 void Q3BSP::LoadVerts(void)
1898 {
1899 vertex_t *verts;
1900 r_numverts[0] = r_numverts[1] = ReadLump(VERTS, (void**)&verts, sizeof(vertex_t));
1901 r_numverts[1] += MAX_CM_VERTEXES;
1902 r_verts = (vertex_t*) cake_malloc(r_numverts[1]*sizeof(vertex_t), "Q3BSP::LoadVerts.r_verts");
1903
1904 for (int i = 0; i < r_numverts[0]; ++i)
1905 {
1906 ColorCopy(verts[i].colour, r_verts[i].colour);
1907 TexcoordCopy(verts[i].lm_st, r_verts[i].lm_st);
1908 TexcoordCopy(verts[i].tex_st, r_verts[i].tex_st);
1909 VectorCopy(verts[i].v_norm, r_verts[i].v_norm);
1910 VectorCopy(verts[i].v_point, r_verts[i].v_point);
1911 }
1912
1913 cake_free(verts);
1914 }
1915
LoadElems(void)1916 void Q3BSP::LoadElems(void)
1917 {
1918 int *elems;
1919 r_numelems[0] = r_numelems[1] = ReadLump(ELEMS, (void**)&elems, sizeof(int));
1920 r_numelems[1] += MAX_CM_VERTEXES;
1921 r_elems = (int*) cake_malloc(r_numelems[1]*sizeof(int), "Q3BSP::LoadElems.r_elems");
1922
1923 for (int i = 0; i < r_numelems[0]; ++i)
1924 r_elems[i] = elems[i];
1925
1926 cake_free(elems);
1927 }
1928
LoadEffects(void)1929 void Q3BSP::LoadEffects(void)
1930 {
1931 effect_t *effects;
1932 r_numeffects[0] = r_numeffects[1] = ReadLump(EFFECTS, (void**)&effects, sizeof(effect_t));
1933
1934 r_effects = (ceffect_t*) cake_malloc(r_numeffects[1]*sizeof(ceffect_t), "Q3BSP::LoadEffects.r_effects");
1935
1936 // Associate effects with brushes
1937 for (int i = 0; i < r_numeffects[0]; ++i)
1938 {
1939 r_effects[i].shader = world->shaders.AddShader(effects[i].name, 0, 0, FACETYPE_MESH);
1940 r_effects[i].brush = effects[i].brush;
1941 r_effects[i].visibleside = effects[i].visibleside;
1942 if (effects[i].visibleside >= 0)
1943 r_effects[i].planeidx = r_brushsides[r_brushes[effects[i].brush].firstbrushside+effects[i].visibleside].planeidx;
1944 else
1945 r_effects[i].planeidx = -1;
1946 r_brushes[r_effects[i].brush].effect = i;
1947 }
1948
1949 cake_free(effects); effects = NULL;
1950 }
1951
LoadFaces(void)1952 void Q3BSP::LoadFaces(void)
1953 {
1954 face_t *faces;
1955 int i;
1956
1957 r_numsurfaces[0] = r_numsurfaces[1] = ReadLump(FACES, (void**)&faces, sizeof(face_t));
1958 r_numsurfaces[1] += MAX_MAP_FACES;
1959
1960 r_numfaces[0] = r_numfaces[1] = 0;
1961 r_numpatches[0] = r_numpatches[1] = 0;
1962 r_nummeshes[0] = r_nummeshes[1] = 0;
1963 r_numflares[0] = r_numflares[1] = 0;
1964
1965 int subdivs = gVars->IntForKey("r_subdivision");
1966 if (subdivs < 1) subdivs = 1;
1967 else if (subdivs > MAX_SUBDIV) subdivs = MAX_SUBDIV;
1968 gVars->SetKeyValue("r_subdivision", subdivs);
1969
1970 r_surfaces = new Surface[r_numsurfaces[1]];
1971 if (!r_surfaces) ThrowException(ALLOCATION_ERROR, "Q3BSP::LoadFaces.r_surfaces");
1972
1973 face_list = new render_face_s[r_numsurfaces[1]];
1974 if (!face_list) ThrowException(ALLOCATION_ERROR, "Q3BSP::LoadFaces.face_list");
1975
1976 for (i = 0; i < r_numsurfaces[0]; ++i)
1977 {
1978 switch (faces[i].facetype)
1979 {
1980 case FACETYPE_PLANAR:
1981 {
1982 r_surfaces[i].Init();
1983 r_surfaces[i].shader = world->shaders.AddShader(r_shaderrefs[faces[i].shader].name,
1984 r_shaderrefs[faces[i].shader].surface_flags,
1985 r_shaderrefs[faces[i].shader].content_flags,
1986 faces[i].facetype);
1987 r_surfaces[i].facetype = faces[i].facetype;
1988 r_surfaces[i].firstvert[0] = r_verts + faces[i].firstvert;
1989 r_surfaces[i].numverts[0] = faces[i].numverts;
1990 r_surfaces[i].firstelem[0] = r_elems + faces[i].firstelem;
1991 r_surfaces[i].numelems[0] = faces[i].numelems;
1992 r_surfaces[i].lm_texnum = faces[i].lm_texnum;
1993 r_surfaces[i].effect = faces[i].effect;
1994 r_surfaces[i].dist = (int) DotProduct(faces[i].v_orig, faces[i].v_norm);
1995 Vector2Copy(faces[i].mesh_cp, r_surfaces[i].patch_cp);
1996 VectorCopy(faces[i].v_norm, r_surfaces[i].v_norm);
1997 VectorCopy(faces[i].v_orig, r_surfaces[i].v_orig);
1998 BoxCopy(faces[i].bbox, r_surfaces[i].bbox);
1999 r_surfaces[i].indextype = r_numfaces[1]++;
2000 face_list[i].face = &r_surfaces[i];
2001 break;
2002 }
2003 case FACETYPE_PATCH:
2004 {
2005 r_surfaces[i].Init(subdivs+1); // create the levels
2006 r_surfaces[i].shader = world->shaders.AddShader(r_shaderrefs[faces[i].shader].name,
2007 r_shaderrefs[faces[i].shader].surface_flags,
2008 r_shaderrefs[faces[i].shader].content_flags,
2009 faces[i].facetype);
2010 r_surfaces[i].facetype = faces[i].facetype;
2011 r_surfaces[i].firstvert[0] = r_verts + faces[i].firstvert;
2012 r_surfaces[i].numverts[0] = faces[i].numverts;
2013 r_surfaces[i].firstelem[0] = r_elems + faces[i].firstelem;
2014 r_surfaces[i].numelems[0] = faces[i].numelems;
2015 r_surfaces[i].lm_texnum = faces[i].lm_texnum;
2016 r_surfaces[i].effect = faces[i].effect;
2017 r_surfaces[i].dist = (int) DotProduct(faces[i].v_orig, faces[i].v_norm);
2018 Vector2Copy(faces[i].mesh_cp, r_surfaces[i].patch_cp);
2019 VectorCopy(faces[i].v_norm, r_surfaces[i].v_norm);
2020 VectorCopy(faces[i].v_orig, r_surfaces[i].v_orig);
2021 BoxCopy(faces[i].bbox, r_surfaces[i].bbox);
2022 r_surfaces[i].indextype = r_numpatches[1]++;
2023 face_list[i].face = &r_surfaces[i];
2024 break;
2025 }
2026 case FACETYPE_MESH:
2027 {
2028 r_surfaces[i].Init();
2029 r_surfaces[i].shader = world->shaders.AddShader(r_shaderrefs[faces[i].shader].name,
2030 r_shaderrefs[faces[i].shader].surface_flags,
2031 r_shaderrefs[faces[i].shader].content_flags,
2032 faces[i].facetype);
2033 r_surfaces[i].facetype = faces[i].facetype;
2034 r_surfaces[i].firstvert[0] = r_verts + faces[i].firstvert;
2035 r_surfaces[i].numverts[0] = faces[i].numverts;
2036 r_surfaces[i].firstelem[0] = r_elems + faces[i].firstelem;
2037 r_surfaces[i].numelems[0] = faces[i].numelems;
2038 r_surfaces[i].lm_texnum = faces[i].lm_texnum;
2039 r_surfaces[i].effect = faces[i].effect;
2040 Vector2Copy(faces[i].mesh_cp, r_surfaces[i].patch_cp);
2041 VectorCopy(faces[i].v_norm, r_surfaces[i].v_norm);
2042 VectorCopy(faces[i].v_orig, r_surfaces[i].v_orig);
2043 BoxCopy(faces[i].bbox, r_surfaces[i].bbox);
2044 r_surfaces[i].indextype = r_nummeshes[1]++;
2045 face_list[i].face = &r_surfaces[i];
2046 break;
2047 }
2048 case FACETYPE_FLARE:
2049 {
2050 r_surfaces[i].Init();
2051 r_surfaces[i].shader = world->shaders.AddShader(r_shaderrefs[faces[i].shader].name,
2052 r_shaderrefs[faces[i].shader].surface_flags,
2053 r_shaderrefs[faces[i].shader].content_flags,
2054 faces[i].facetype);
2055 r_surfaces[i].facetype = faces[i].facetype;
2056 r_surfaces[i].firstvert[0] = r_verts + faces[i].firstvert;
2057 r_surfaces[i].numverts[0] = faces[i].numverts;
2058 r_surfaces[i].firstelem[0] = r_elems + faces[i].firstelem;
2059 r_surfaces[i].numelems[0] = faces[i].numelems;
2060 r_surfaces[i].lm_texnum = faces[i].lm_texnum;
2061 r_surfaces[i].effect = faces[i].effect;
2062 Vector2Copy(faces[i].mesh_cp, r_surfaces[i].patch_cp);
2063 VectorCopy(faces[i].v_norm, r_surfaces[i].v_norm);
2064 VectorCopy(faces[i].v_orig, r_surfaces[i].v_orig);
2065 BoxCopy(faces[i].bbox, r_surfaces[i].bbox);
2066 r_surfaces[i].indextype = r_numflares[1]++;
2067 face_list[i].face = &r_surfaces[i];
2068 break;
2069 }
2070 default:
2071 face_list[i].face = NULL;
2072 break;
2073 }
2074 }
2075
2076 cake_free(faces);
2077
2078 // Reset other faces
2079 for (i = r_numsurfaces[0]; i < r_numsurfaces[1]; ++i) face_list[i].face = NULL;
2080 }
2081
InitSurfaces(void)2082 void Q3BSP::InitSurfaces(void)
2083 {
2084 gConsole->Insertln("Initializing faces...");
2085
2086 int i;
2087
2088 if (!(r_faces = new Surface*[r_numfaces[1]]))
2089 ThrowException(ALLOCATION_ERROR, "Q3BSP::InitSurfaces.r_faces");
2090 if (!(r_patches = new Surface*[r_numpatches[1]]))
2091 ThrowException(ALLOCATION_ERROR, "Q3BSP::InitSurfaces.r_patches");
2092 if (!(r_meshes = new Surface*[r_nummeshes[1]]))
2093 ThrowException(ALLOCATION_ERROR, "Q3BSP::InitSurfaces.r_meshes");
2094 if (!(r_flares = new Surface*[r_numflares[1]]))
2095 ThrowException(ALLOCATION_ERROR, "Q3BSP::InitSurfaces.r_flares");
2096
2097 int cfactor = gVars->IntForKey("r_curvefactor");
2098 if (cfactor < 1) cfactor = 1;
2099 gVars->SetKeyValue("r_curvefactor", cfactor);
2100
2101 for (i = 0; i < r_numsurfaces[0]; ++i)
2102 {
2103 switch (r_surfaces[i].facetype)
2104 {
2105 case FACETYPE_PLANAR:
2106 r_faces[r_numfaces[0]++] = &r_surfaces[i];
2107 break;
2108 case FACETYPE_PATCH:
2109 {
2110 r_patches[r_numpatches[0]++] = &r_surfaces[i];
2111 BuildBezierPatch(&r_surfaces[i], cfactor);
2112 }
2113 break;
2114 case FACETYPE_MESH:
2115 r_meshes[r_nummeshes[0]++] = &r_surfaces[i];
2116 break;
2117 case FACETYPE_FLARE:
2118 r_flares[r_numflares[0]++] = &r_surfaces[i];
2119 break;
2120 default:
2121 break;
2122 }
2123 }
2124
2125 // Creates the patches groups
2126 CreatePatchesGroups();
2127
2128 // Compute the bounding box of each face
2129 // Note: The bounding box should not be calculated before because patches
2130 // have special bounding box that are used for the patches groups
2131 // construction.
2132 for (i = 0; i < r_numsurfaces[0]; ++i) CalcFaceBounds(&r_surfaces[i]);
2133
2134 // Creates the patch brushes for collisions with patches
2135 CreatePatchesForLeafs();
2136 }
2137
BuildBezierPatch(Surface * surf,int curvefactor)2138 void Q3BSP::BuildBezierPatch(Surface* surf, int curvefactor)
2139 {
2140 // Generate the patches
2141 // Get patch flatness
2142 int flat[2], tess[2], size[2], n;
2143 vertex_t *v;
2144
2145 vec4_t *in_xyz = (vec4_t*) cake_malloc(surf->numverts[0]*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.in_xyz");
2146 vec4_t *in_colors = (vec4_t*) cake_malloc(surf->numverts[0]*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.in_colors");
2147 vec4_t *in_normals = (vec4_t*) cake_malloc(surf->numverts[0]*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.in_normals");
2148 vec4_t *in_lm_st = (vec4_t*) cake_malloc(surf->numverts[0]*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.in_lm_st");
2149 vec4_t *in_tex_st = (vec4_t*) cake_malloc(surf->numverts[0]*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.in_tex_st");
2150 if (!in_xyz || !in_colors || !in_normals || !in_lm_st || !in_tex_st)
2151 {
2152 gConsole->Insertln("^1Q3BSP::BuildBezierPatch.inBuffers: Cannot allocate required size");
2153 return;
2154 }
2155
2156 v = surf->firstvert[0];
2157 for (n = 0; n < surf->numverts[0]; ++n, ++v)
2158 {
2159 VectorCopy(v->v_point, in_xyz[n]);
2160 VectorCopy(v->v_norm, in_normals[n]);
2161 Vector4Scale(v->colour, (1.f/255.f), in_colors[n]);
2162 Vector2Copy(v->tex_st, in_tex_st[n]);
2163 Vector2Copy(v->lm_st, in_lm_st[n]);
2164 }
2165 v = NULL;
2166
2167 Patch_GetFlatness((float) curvefactor, in_xyz, surf->patch_cp, flat);
2168
2169 // Create levels
2170 for (int lvl = 1; lvl < surf->levels; ++lvl)
2171 {
2172 int *tempElemsArray, *elems, p, numverts, numelems;
2173 vec4_t *tmp_buffer;
2174
2175 tess[0] = (((flat[0]*(lvl-1))>>1)+1)*(1<<flat[0]);
2176 tess[1] = (((flat[1]*(lvl-1))>>1)+1)*(1<<flat[1]);
2177 size[0] = (surf->patch_cp[0]>>1)*tess[0]+1;
2178 size[1] = (surf->patch_cp[1]>>1)*tess[1]+1;
2179 numverts = size[0]*size[1];
2180
2181 surf->numverts[lvl] = numverts;
2182
2183 // Allocate vertices memory
2184 surf->firstvert[lvl] = (vertex_t*) cake_malloc(numverts*sizeof(vertex_t), "Q3BSP::BuildBezierPatch.surf->firstvert[lvl]");
2185 if (!surf->firstvert[lvl])
2186 {
2187 gConsole->Insertln("^1Q3BSP::BuildBezierPatch.surf->firstvert[lvl]: Cannot allocate required size");
2188 continue;
2189 }
2190
2191 // Create temp buffer
2192 tmp_buffer = (vec4_t*) cake_malloc(numverts*sizeof(vec4_t), "Q3BSP::BuildBezierPatch.tmp_buffer");
2193 if (!tmp_buffer)
2194 {
2195 gConsole->Insertln("^1Q3BSP::BuildBezierPatch.tmp_buffer: Cannot allocate required size");
2196 continue;
2197 }
2198
2199 // vertices
2200 Patch_Evaluate(in_xyz, surf->patch_cp, tess, tmp_buffer);
2201 for (n = 0; n < numverts; ++n)
2202 {
2203 VectorCopy(tmp_buffer[n], surf->firstvert[lvl][n].v_point);
2204 }
2205
2206 // colours
2207 vec4_t c;
2208 Patch_Evaluate(in_colors, surf->patch_cp, tess, tmp_buffer);
2209 for (n = 0; n < numverts; ++n)
2210 {
2211 ColorNormalize(tmp_buffer[n], c);
2212 surf->firstvert[lvl][n].colour[0] = (unsigned char) (255.f * c[0]);
2213 surf->firstvert[lvl][n].colour[1] = (unsigned char) (255.f * c[1]);
2214 surf->firstvert[lvl][n].colour[2] = (unsigned char) (255.f * c[2]);
2215 surf->firstvert[lvl][n].colour[3] = (unsigned char) (255.f * c[3]);
2216 }
2217
2218 // normals
2219 Patch_Evaluate(in_normals, surf->patch_cp, tess, tmp_buffer);
2220 for (n = 0; n < numverts; ++n)
2221 {
2222 VectorNormalize2(tmp_buffer[n], surf->firstvert[lvl][n].v_norm);
2223 }
2224
2225 // lightmap coords
2226 Patch_Evaluate(in_lm_st, surf->patch_cp, tess, tmp_buffer);
2227 for (n = 0; n < numverts; ++n)
2228 {
2229 Vector2Copy(tmp_buffer[n], surf->firstvert[lvl][n].lm_st);
2230 }
2231
2232 // texture coords
2233 Patch_Evaluate(in_tex_st, surf->patch_cp, tess, tmp_buffer);
2234 for (n = 0; n < numverts; ++n)
2235 {
2236 Vector2Copy(tmp_buffer[n], surf->firstvert[lvl][n].tex_st);
2237 }
2238
2239 // Free temp variables
2240 cake_free(tmp_buffer);
2241
2242 // Compute new elems avoiding adding invalid triangles
2243
2244 numelems = 0;
2245 tempElemsArray = (int*) cake_malloc(6*numverts*sizeof(int), "Q3BSP::BuildBezierPatch.tempElemsArray");
2246 if (!tempElemsArray)
2247 {
2248 gConsole->Insertln("^1Q3BSP::BuildBezierPatch.tempElemsArray: Cannot allocate required size");
2249 continue;
2250 }
2251
2252 elems = tempElemsArray;
2253 for (int y = 0; y < size[1]-1; ++y)
2254 {
2255 for (int x = 0; x < size[0]-1; ++x)
2256 {
2257 elems[0] = p = y * size[0] + x;
2258 elems[1] = p + size[0];
2259 elems[2] = p + 1;
2260
2261 if (!VectorCompare(surf->firstvert[lvl][elems[0]].v_point, surf->firstvert[lvl][elems[1]].v_point) &&
2262 !VectorCompare(surf->firstvert[lvl][elems[0]].v_point, surf->firstvert[lvl][elems[2]].v_point) &&
2263 !VectorCompare(surf->firstvert[lvl][elems[1]].v_point, surf->firstvert[lvl][elems[2]].v_point))
2264 {
2265 if (numelems >= 6*numverts)
2266 {
2267 gConsole->Insertln("Array overflow !");
2268 continue;
2269 }
2270 elems += 3;
2271 numelems += 3;
2272 }
2273
2274 elems[0] = p + 1;
2275 elems[1] = p + size[0];
2276 elems[2] = p + size[0] + 1;
2277
2278 if (!VectorCompare(surf->firstvert[lvl][elems[0]].v_point, surf->firstvert[lvl][elems[1]].v_point) &&
2279 !VectorCompare(surf->firstvert[lvl][elems[0]].v_point, surf->firstvert[lvl][elems[2]].v_point) &&
2280 !VectorCompare(surf->firstvert[lvl][elems[1]].v_point, surf->firstvert[lvl][elems[2]].v_point))
2281 {
2282 if (numelems >= 6*numverts)
2283 {
2284 gConsole->Insertln("Array overflow !");
2285 continue;
2286 }
2287 elems += 3;
2288 numelems += 3;
2289 }
2290 }
2291 }
2292
2293 // Allocate elems table
2294 surf->numelems[lvl] = numelems;
2295 surf->firstelem[lvl] = (int*) cake_malloc(numelems*sizeof(int), "Q3BSP::BuildBezierPatch.surf->firstelem[lvl]");
2296 if (!surf->firstelem[lvl])
2297 {
2298 gConsole->Insertln("^1Q3BSP::BuildBezierPatch.surf->firstelem[lvl]: Cannot allocate required size");
2299 continue;
2300 }
2301 memcpy(surf->firstelem[lvl], tempElemsArray, numelems*sizeof(int));
2302 cake_free(tempElemsArray);
2303 }
2304
2305 cake_free(in_tex_st);
2306 cake_free(in_lm_st);
2307 cake_free(in_normals);
2308 cake_free(in_colors);
2309 cake_free(in_xyz);
2310 }
2311
2312 // Load the lightmaps from the bsp
LoadLightmaps(void)2313 void Q3BSP::LoadLightmaps(void)
2314 {
2315 BYTE *lightmapdata;
2316
2317 int lightmapsize = ReadLump(LIGHTMAPS, (void**)&lightmapdata, 1);
2318 r_numlightmaps[0] = r_numlightmaps[1] = lightmapsize/LIGHTMAP_SIZE;
2319 r_lightmapinfos = (texinfo*) cake_malloc(r_numlightmaps[1]*sizeof(texinfo), "Q3BSP::LoadLightmaps.r_lightmapinfos");
2320 // lightmaps are allways overbrightened
2321 const float overbright = 4.0f;
2322 unsigned int top, r, g, b;
2323 for (int i = 0; i < r_numlightmaps[0]; ++i)
2324 {
2325 r_lightmapinfos[i].mem = &lightmapdata[i * LIGHTMAP_SIZE];
2326 r_lightmapinfos[i].bpp = 3;
2327 r_lightmapinfos[i].height = 128;
2328 r_lightmapinfos[i].width = 128;
2329 r_lightmapinfos[i].num = ~0;
2330
2331 if (overbright != 1.0f)
2332 {
2333 int j;
2334 BYTE *c;
2335
2336 c = &lightmapdata[i * LIGHTMAP_SIZE];
2337
2338 for (j = 0; j < LIGHTMAP_SIZE/3; ++j, c += 3)
2339 {
2340 top =
2341 r = (unsigned int) ((float) c[0] * overbright);
2342 g = (unsigned int) ((float) c[1] * overbright);
2343 b = (unsigned int) ((float) c[2] * overbright);
2344 if (g > top) top = g;
2345 if (b > top) top = b;
2346 if (top > 255)
2347 {
2348 top = (255 << 8) / top;
2349 r = (r * top) >> 8;
2350 g = (g * top) >> 8;
2351 b = (b * top) >> 8;
2352 }
2353
2354 c[0] = r;
2355 c[1] = g;
2356 c[2] = b;
2357 }
2358 }
2359
2360 gRender->RegisterTexInfo(&r_lightmapinfos[i],
2361 LF_LIGHTMAP | LF_NOMIPMAP | LF_NOPICMIP | LF_CLAMP);
2362
2363 r_lightmapinfos[i].mem = NULL;
2364 }
2365
2366 // We don't need this data any more
2367 cake_free(lightmapdata);
2368 lightmapdata = NULL;
2369 }
2370
LoadLightVols(void)2371 void Q3BSP::LoadLightVols(void)
2372 {
2373 r_numlightvols[0] = r_numlightvols[1] = ReadLump(LIGHTVOLS, (void**)&r_lightvols, sizeof(*r_lightvols));
2374 }
2375
LoadVisibility(void)2376 void Q3BSP::LoadVisibility(void)
2377 {
2378 r_numvisibility[0] = r_numvisibility[1] = ReadLump(VISIBILITY, (void**)&r_visibility, 1);
2379 }
2380
DisplayLevelshot(void)2381 void Q3BSP::DisplayLevelshot(void)
2382 {
2383 gOver->Quad(levelshot, 0, 0, (float) gRender->GetWidth(), (float) gRender->GetHeight());
2384 gOver->Quad(levelshotdetail, 0, 0, (float) gRender->GetWidth(), (float) gRender->GetHeight(), 2.5, 2);
2385 gOver->Render(&gFramework->shaders);
2386 }
2387
DisplayLoadingMessage(const char * msg,int line)2388 void Q3BSP::DisplayLoadingMessage(const char *msg, int line)
2389 {
2390 float l = (float) (SMALL_CHAR_HEIGHT*line);
2391 if (l < 0) l = (float)(gRender->GetHeight()-SMALL_CHAR_HEIGHT)/2.f;
2392
2393 gOver->Quad(levelshot, 0, 0, (float) gRender->GetWidth(), (float) gRender->GetHeight());
2394 gOver->Quad(levelshotdetail, 0, 0, (float) gRender->GetWidth(), (float) gRender->GetHeight(), 2.5, 2);
2395
2396 if (worldname)
2397 {
2398 gOver->String(worldname,
2399 gFramework->GetFont(NORMAL_CHAR),
2400 (float) (gRender->GetWidth()-SMALL_CHAR_WIDTH*strlen(worldname))/2.f,
2401 l - 2*SMALL_CHAR_HEIGHT);
2402 }
2403 gOver->String(msg,
2404 gFramework->GetFont(NORMAL_CHAR),
2405 (float) (gRender->GetWidth()-SMALL_CHAR_WIDTH*strlen(msg))/2.f,
2406 l);
2407
2408 gOver->Render(&gFramework->shaders);
2409 gRender->SwapBuffers();
2410 }
2411
2412 // Loads a levelshot in framework
LoadLevelshot(const char * map_name)2413 void Q3BSP::LoadLevelshot(const char* map_name)
2414 {
2415 char levelshot_name[256] = { '\0' };
2416 int levelshot_found = 0;
2417
2418 // search levelshot having TGA or JPG extension
2419 sprintf(levelshot_name, "levelshots/%s.jpg", map_name);
2420 levelshot_found = FileExist(levelshot_name, 1, 0);
2421 if (!levelshot_found)
2422 {
2423 sprintf(levelshot_name, "levelshots/%s.tga", map_name);
2424 levelshot_found = FileExist(levelshot_name, 1, 0);
2425 }
2426
2427 if (!levelshot_found)
2428 strcpy(levelshot_name, "menu/art/unknownmap.jpg");
2429
2430 levelshotdetail = gFramework->shaders.AddShader("levelShotDetail", 0, 0, FACETYPE_MESH);
2431 levelshot = gFramework->shaders.AddShader(levelshot_name, 0, 0, FACETYPE_MESH);
2432
2433 gFramework->Update();
2434 }
2435
2436 //-----------------------------------------------------------------------------
2437 // Data Preprocessing Routines
2438 //-----------------------------------------------------------------------------
2439
2440 // Calculate the parent of each leaf and each node
SetParent(int node,cnode_t * parent)2441 void Q3BSP::SetParent(int node, cnode_t *parent)
2442 {
2443 if (node < 0) // is a leaf
2444 {
2445 r_leafs[~node].parent = parent;
2446 return;
2447 }
2448
2449 r_nodes[node].parent = parent;
2450 SetParent(r_nodes[node].children[0], &r_nodes[node]);
2451 SetParent(r_nodes[node].children[1], &r_nodes[node]);
2452 }
2453
InitAutosprite(Surface * surf,int type)2454 void Q3BSP::InitAutosprite(Surface *surf, int type)
2455 {
2456 float mat[16], tmp;
2457 vec3_t n, s, t, m, backup[4];
2458 int i;
2459
2460 VectorClear(m);
2461 tmp = 1.f/(float)surf->numverts[0];
2462 for (i = 0; i < surf->numverts[0]; ++i)
2463 {
2464 VectorAdd(m, surf->firstvert[0][i].v_point, m);
2465 }
2466 VectorScale(m, tmp, m);
2467
2468 VectorSub(surf->firstvert[0][surf->firstelem[0][1]].v_point, surf->firstvert[0][surf->firstelem[0][0]].v_point, s);
2469 tmp = InverseSqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2]);
2470 VectorScale(s, tmp, s);
2471
2472 VectorSub(surf->firstvert[0][surf->firstelem[0][0]].v_point, surf->firstvert[0][surf->firstelem[0][2]].v_point, t);
2473 tmp = InverseSqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);
2474 VectorScale(t, tmp, t);
2475
2476 CrossProduct(s, t, n);
2477
2478 mat[0] = s[0]; mat[1] = s[1]; mat[2] = s[2]; mat[3] = 0;
2479 mat[4] = t[0]; mat[5] = t[1]; mat[6] = t[2]; mat[7] = 0;
2480 mat[8] = n[0]; mat[9] = n[1]; mat[10] = n[2]; mat[11] = 0;
2481 mat[12] = 0; mat[13] = 0; mat[14] = 0; mat[15] = 1;
2482
2483 glMatrixMode(GL_MODELVIEW);
2484 glPushMatrix();
2485 glLoadMatrixf(mat);
2486 glRotatef( 90, 1, 0, 0);
2487 glRotatef(-90, 0, 1, 0);
2488 glGetFloatv(GL_MODELVIEW_MATRIX, mat);
2489 glPopMatrix();
2490 gRender->CheckGLError(7);
2491
2492 for (int v = 0; v < surf->numverts[0]; v += 4)
2493 {
2494 VectorCopy(surf->firstvert[0][v].v_point, backup[0]);
2495 VectorSub(surf->firstvert[0][v].v_point, m, surf->firstvert[0][v].v_point);
2496 MultVect4x4(mat, surf->firstvert[0][v].v_point, surf->firstvert[0][v].v_point);
2497 VectorAdd(surf->firstvert[0][v].v_point, m, surf->firstvert[0][v].v_point);
2498
2499 VectorCopy(surf->firstvert[0][v+1].v_point, backup[1]);
2500 VectorSub(surf->firstvert[0][v+1].v_point, m, surf->firstvert[0][v+1].v_point);
2501 MultVect4x4(mat, surf->firstvert[0][v+1].v_point, surf->firstvert[0][v+1].v_point);
2502 VectorAdd(surf->firstvert[0][v+1].v_point, m, surf->firstvert[0][v+1].v_point);
2503
2504 VectorCopy(surf->firstvert[0][v+2].v_point, backup[2]);
2505 VectorSub(surf->firstvert[0][v+2].v_point, m, surf->firstvert[0][v+2].v_point);
2506 MultVect4x4(mat, surf->firstvert[0][v+2].v_point, surf->firstvert[0][v+2].v_point);
2507 VectorAdd(surf->firstvert[0][v+2].v_point, m, surf->firstvert[0][v+2].v_point);
2508
2509 VectorCopy(surf->firstvert[0][v+3].v_point, backup[3]);
2510 VectorSub(surf->firstvert[0][v+3].v_point, m, surf->firstvert[0][v+3].v_point);
2511 MultVect4x4(mat, surf->firstvert[0][v+3].v_point, surf->firstvert[0][v+3].v_point);
2512 VectorAdd(surf->firstvert[0][v+3].v_point, m, surf->firstvert[0][v+3].v_point);
2513
2514 if (type == DEFORMVERTEXES_AUTOSPRITE2)
2515 {
2516 // get longer axis
2517 float dx = (float) (pow(surf->firstvert[0][v+1].v_point[0]-surf->firstvert[0][v].v_point[0], 2)+
2518 pow(surf->firstvert[0][v+2].v_point[0]-surf->firstvert[0][v].v_point[0], 2)+
2519 pow(surf->firstvert[0][v+3].v_point[0]-surf->firstvert[0][v].v_point[0], 2));
2520 float dy = (float) (pow(surf->firstvert[0][v+1].v_point[1]-surf->firstvert[0][v].v_point[1], 2)+
2521 pow(surf->firstvert[0][v+2].v_point[1]-surf->firstvert[0][v].v_point[1], 2)+
2522 pow(surf->firstvert[0][v+3].v_point[1]-surf->firstvert[0][v].v_point[1], 2));
2523 float dz = (float) (pow(surf->firstvert[0][v+1].v_point[2]-surf->firstvert[0][v].v_point[2], 2)+
2524 pow(surf->firstvert[0][v+2].v_point[2]-surf->firstvert[0][v].v_point[2], 2)+
2525 pow(surf->firstvert[0][v+3].v_point[2]-surf->firstvert[0][v].v_point[2], 2));
2526 if (dx > dz)
2527 {
2528 surf->autosprite2_axis = 0;
2529 // restore initial rotation
2530 // TODO: terminate this stuff !!
2531 VectorCopy(backup[0], surf->firstvert[0][v ].v_point);
2532 VectorCopy(backup[1], surf->firstvert[0][v+1].v_point);
2533 VectorCopy(backup[2], surf->firstvert[0][v+2].v_point);
2534 VectorCopy(backup[3], surf->firstvert[0][v+3].v_point);
2535 }
2536 else surf->autosprite2_axis = 2;
2537 }
2538 }
2539
2540 VectorCopy(m, surf->v_orig);
2541 MultVect4x4(mat, n, surf->v_norm);
2542 }
2543
2544 #define cm_subdivlevel 15
2545
CreateBrush(cbrush_t * brush,vec3_t * verts,int surface_shader)2546 void Q3BSP::CreateBrush(cbrush_t *brush, vec3_t *verts, int surface_shader)
2547 {
2548 int i, j, k, sign;
2549 vec3_t v1, v2, v3, v4, v5, v6, normal, absmins, absmaxs;
2550 cbrushside_t *side;
2551 cplane_t *plane;
2552 static cplane_t mainplane, patchplanes[20];
2553 bool skip[20];
2554 int numpatchplanes = 0;
2555
2556 // calc absmins & absmaxs
2557 ClearBounds(absmins, absmaxs);
2558 AddPointToBounds(verts[0], absmins, absmaxs);
2559 AddPointToBounds(verts[1], absmins, absmaxs);
2560 AddPointToBounds(verts[2], absmins, absmaxs);
2561
2562 PlaneFromPoints(verts, &mainplane);
2563
2564 // front plane
2565 plane = &patchplanes[numpatchplanes++];
2566 *plane = mainplane;
2567
2568 // back plane
2569 plane = &patchplanes[numpatchplanes++];
2570 VectorNegate(mainplane.normal, plane->normal);
2571 plane->dist = -mainplane.dist;
2572
2573 // axial planes
2574 for (sign = -1; sign <= 1; sign += 2)
2575 {
2576 plane = &patchplanes[numpatchplanes++];
2577 VectorClear(plane->normal);
2578 plane->normal[0] = (vec_t) sign;
2579 plane->dist = sign > 0 ? absmaxs[0] : -absmins[0];
2580 }
2581 for (sign = -1; sign <= 1; sign += 2)
2582 {
2583 plane = &patchplanes[numpatchplanes++];
2584 VectorClear(plane->normal);
2585 plane->normal[1] = (vec_t) sign;
2586 plane->dist = sign > 0 ? absmaxs[1] : -absmins[1];
2587 }
2588 for (sign = -1; sign <= 1; sign += 2)
2589 {
2590 plane = &patchplanes[numpatchplanes++];
2591 VectorClear(plane->normal);
2592 plane->normal[2] = (vec_t) sign;
2593 plane->dist = sign > 0 ? absmaxs[2] : -absmins[2];
2594 }
2595
2596 // edge planes
2597
2598 VectorCopy(verts[0], v1);
2599 VectorCopy(verts[1%3], v2);
2600 VectorCopy(verts[1], v3);
2601 VectorCopy(verts[2%3], v4);
2602 VectorCopy(verts[2], v5);
2603 VectorCopy(verts[3%3], v6);
2604
2605 for (k = 0; k < 3; k++)
2606 {
2607 normal[k] = 0;
2608 normal[(k+1)%3] = v1[(k+2)%3] - v2[(k+2)%3];
2609 normal[(k+2)%3] = -(v1[(k+1)%3] - v2[(k+1)%3]);
2610
2611 if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0)
2612 {
2613 plane = &patchplanes[numpatchplanes++];
2614
2615 VectorNormalize(normal);
2616 VectorCopy(normal, plane->normal);
2617 plane->dist = DotProduct(plane->normal, v1);
2618
2619 if (DotProduct(verts[(0+2)%3], normal) - plane->dist > 0)
2620 {
2621 // invert
2622 VectorInverse ( plane->normal );
2623 plane->dist = -plane->dist;
2624 }
2625 }
2626
2627 normal[k] = 0;
2628 normal[(k+1)%3] = v3[(k+2)%3] - v4[(k+2)%3];
2629 normal[(k+2)%3] = -(v3[(k+1)%3] - v4[(k+1)%3]);
2630
2631 if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0)
2632 {
2633 plane = &patchplanes[numpatchplanes++];
2634
2635 VectorNormalize(normal);
2636 VectorCopy(normal, plane->normal);
2637 plane->dist = DotProduct(plane->normal, v3);
2638
2639 if (DotProduct(verts[3%3], normal) - plane->dist > 0)
2640 {
2641 // invert
2642 VectorInverse ( plane->normal );
2643 plane->dist = -plane->dist;
2644 }
2645 }
2646
2647 normal[k] = 0;
2648 normal[(k+1)%3] = v5[(k+2)%3] - v6[(k+2)%3];
2649 normal[(k+2)%3] = -(v5[(k+1)%3] - v6[(k+1)%3]);
2650
2651 if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0)
2652 {
2653 plane = &patchplanes[numpatchplanes++];
2654
2655 VectorNormalize(normal);
2656 VectorCopy(normal, plane->normal);
2657 plane->dist = DotProduct(plane->normal, v5);
2658
2659 if (DotProduct(verts[4%3], normal) - plane->dist > 0)
2660 {
2661 // invert
2662 VectorInverse ( plane->normal );
2663 plane->dist = -plane->dist;
2664 }
2665 }
2666 }
2667
2668 // set plane->type and mark duplicate planes for removal
2669 for (i = 0; i < numpatchplanes; i++)
2670 {
2671 CategorizePlane(&patchplanes[i]);
2672 skip[i] = false;
2673
2674 for (j = i + 1; j < numpatchplanes; j++)
2675 if (patchplanes[j].dist == patchplanes[i].dist &&
2676 VectorCompare(patchplanes[j].normal, patchplanes[i].normal))
2677 {
2678 skip[i] = true;
2679 break;
2680 }
2681 }
2682
2683 brush->numsides = 0;
2684 brush->firstbrushside = r_numbrushsides[0];
2685
2686 for (k = 0; k < 2; k++)
2687 {
2688 for (i = 0; i < numpatchplanes; i++)
2689 {
2690 if (skip[i]) continue;
2691
2692 // first, store all axially aligned planes
2693 // then store everything else
2694 // does it give a noticeable speedup?
2695 if (!k && patchplanes[i].type >= 3) continue;
2696
2697 skip[i] = true;
2698
2699 while (r_numplanes[0] >= r_numplanes[1])
2700 {
2701 // force reallocation
2702 r_numplanes[1] += (MAX_CM_PLANES+12);
2703 if (!(r_planes = (cplane_t*) cake_realloc(r_planes, r_numplanes[1]*sizeof(cplane_t), "Q3BSP::CreateBrush.r_planes")))
2704 ThrowException(ALLOCATION_ERROR, "Q3BSP::CreateBrushr_planes");
2705 }
2706
2707 plane = &r_planes[r_numplanes[0]];
2708 *plane = patchplanes[i];
2709
2710 while (r_numbrushsides[0] >= r_numbrushsides[1])
2711 {
2712 // force reallocation
2713 r_numbrushsides[1] += (MAX_CM_BRUSHSIDES+6);
2714 if (!(r_brushsides = (cbrushside_t*) cake_realloc(r_brushsides, r_numbrushsides[1]*sizeof(cbrushside_t), "Q3BSP::CreateBrush.r_brushsides")))
2715 ThrowException(ALLOCATION_ERROR, "Q3BSP::CreateBrush.r_brushsides");
2716 }
2717
2718 side = &r_brushsides[r_numbrushsides[0]++];
2719 side->planeidx = r_numplanes[0]++;
2720
2721 if (DotProduct(plane->normal, mainplane.normal) >= 0) side->shader = surface_shader;
2722 else side->shader = -1; // don't clip against this side
2723
2724 brush->numsides++;
2725 }
2726 }
2727 }
2728
CreatePatch(cpatch_t * patch,int numverts,vec4_t * verts,int * patch_cp)2729 void Q3BSP::CreatePatch(cpatch_t *patch, int numverts, vec4_t *verts, int *patch_cp)
2730 {
2731 int step[2], size[2], flat[2], i, u, v;
2732 vec4_t points[MAX_CM_PATCH_VERTS];
2733 vec3_t tverts[4], tverts2[4];
2734 Shader* shad = world->shaders.GetShader(patch->shader);
2735 int brushidx;
2736
2737 // find the degree of subdivision in the u and v directions
2738 Patch_GetFlatness(cm_subdivlevel, verts, patch_cp, flat);
2739
2740 step[0] = (1 << flat[0]);
2741 step[1] = (1 << flat[1]);
2742 size[0] = (patch_cp[0]>>1) * step[0] + 1;
2743 size[1] = (patch_cp[1]>>1) * step[1] + 1;
2744
2745 if (size[0]*size[1] > MAX_CM_PATCH_VERTS)
2746 {
2747 gConsole->Insertln("CM_CreatePatch: patch has too many vertices");
2748 return;
2749 }
2750
2751 // fill in
2752 Patch_Evaluate(verts, patch_cp, step, points);
2753
2754 patch->firstbrush = brushidx = r_numbrushes[0];
2755 patch->numbrushes = 0;
2756
2757 ClearBounds(patch->absmins, patch->absmaxs);
2758
2759 // create a set of brushes
2760 for (v = 0; v < size[1]-1; v++)
2761 {
2762 for (u = 0; u < size[0]-1; u++)
2763 {
2764 while (r_numbrushes[0] >= r_numbrushes[1])
2765 {
2766 // force reallocation
2767 r_numbrushes[1] += (MAX_CM_BRUSHES+1);
2768 if (!(r_brushes = (cbrush_t*) cake_realloc(r_brushes, r_numbrushes[1]*sizeof(cbrush_t), "Q3BSP::CreateBrush.r_brushes")))
2769 ThrowException(ALLOCATION_ERROR, "Q3BSP::CreateBrush.r_brushes");
2770 }
2771
2772 i = v*size[0]+u;
2773 VectorCopy(points[i], tverts[0]);
2774 VectorCopy(points[i+size[0]], tverts[1]);
2775 VectorCopy(points[i+1], tverts[2]);
2776 VectorCopy(points[i+size[0]+1], tverts[3]);
2777
2778 AddPointToBounds(tverts[0], patch->absmins, patch->absmaxs);
2779 AddPointToBounds(tverts[1], patch->absmins, patch->absmaxs);
2780 AddPointToBounds(tverts[2], patch->absmins, patch->absmaxs);
2781 AddPointToBounds(tverts[3], patch->absmins, patch->absmaxs);
2782
2783 // create two brushes
2784 CreateBrush(&r_brushes[brushidx], tverts, patch->shader);
2785
2786 r_brushes[brushidx].contents = shad?shad->content_flags:0;
2787 brushidx++; r_numbrushes[0]++; patch->numbrushes++;
2788
2789 VectorCopy(tverts[2], tverts2[0]);
2790 VectorCopy(tverts[1], tverts2[1]);
2791 VectorCopy(tverts[3], tverts2[2]);
2792 CreateBrush(&r_brushes[brushidx], tverts2, patch->shader);
2793
2794 r_brushes[brushidx].contents = shad?shad->content_flags:0;
2795 brushidx++; r_numbrushes[0]++; patch->numbrushes++;
2796 }
2797 }
2798 }
2799
CreatePatchesForLeafs(void)2800 void Q3BSP::CreatePatchesForLeafs(void)
2801 {
2802 gConsole->Insertln("Creating patches for leafs...");
2803
2804 int i, j, k;
2805 cleaf_t *leaf;
2806 Surface *face;
2807 cpatch_t *patch;
2808 Shader *shad;
2809 int *checkout = new int [r_numsurfaces[0]];
2810
2811 memset(checkout, -1, sizeof(int)*r_numsurfaces[0]);
2812
2813 // Destroy existing (shouldn't exist one) leafpatches
2814 if (r_leafpatches)
2815 {
2816 cake_free(r_leafpatches);
2817 gConsole->Insertln("^5WARNING: leafpatch structure deleted (shouldn't be defined !)");
2818 }
2819 r_numleafpatches[0] = 0;
2820 r_numleafpatches[1] = MAX_CM_LEAFFACES;
2821 if (!(r_leafpatches = (int*) cake_realloc(r_leafpatches, r_numleafpatches[1]*sizeof(int), "Q3BSP::CreatePatchesForLeafs.r_leafpatches")))
2822 {
2823 gConsole->Insertln("^1Q3BSP::CreatePatchesForLeafs.r_leafpatches: Cannot allocate required size");
2824 return;
2825 }
2826
2827 // Destroy existing cpatches (shouldn't exist any)
2828 r_numcpatches[0] = 0;
2829 r_numcpatches[1] = MAX_CM_PATCHES;
2830 if (!(r_cpatches = (cpatch_t*) cake_malloc(r_numcpatches[1]*sizeof(cpatch_t), "Q3BSP::CreatePatchesForLeafs.r_cpatches")))
2831 {
2832 gConsole->Insertln("^1Q3BSP::CreatePatchesForLeafs.r_cpatches: Cannot allocate required size");
2833 return;
2834 }
2835 memset(r_cpatches, 0, r_numcpatches[1]*sizeof(cpatch_t));
2836
2837 for (i = 0, leaf = r_leafs; i < r_numleafs[0]; i++, leaf++)
2838 {
2839 leaf->numleafpatches = 0;
2840 leaf->firstleafpatch = r_numleafpatches[0];
2841
2842 if (leaf->cluster == -1) continue;
2843
2844 for (j = 0; j < leaf->numleaffaces; j++)
2845 {
2846 k = leaf->firstleafface + j;
2847 if (k >= r_numleaffaces[0]) break;
2848
2849 k = r_leaffaces[k];
2850 face = &r_surfaces[k];
2851
2852 if (face->facetype != FACETYPE_PATCH || face->numverts[0] <= 0) continue;
2853 if (face->patch_cp[0] <= 0 || face->patch_cp[1] <= 0) continue;
2854 if (!(shad = world->shaders.GetShader(face->shader))) continue;
2855 if (!shad->content_flags || (shad->surface_flags & SURF_NONSOLID)) continue;
2856
2857 while (r_numleafpatches[0] >= r_numleafpatches[1])
2858 {
2859 // force reallocation
2860 r_numleafpatches[1] += MAX_CM_LEAFFACES;
2861 if (!(r_leafpatches = (int*) cake_realloc(r_leafpatches, r_numleafpatches[1]*sizeof(int), "Q3BSP::CreatePatchesForLeafs.r_leafpatches")))
2862 ThrowException(ALLOCATION_ERROR, "Q3BSP::CreatePatchesForLeafs.r_leafpatches");
2863 }
2864
2865 // the patch was already built
2866 if (checkout[k] != -1)
2867 {
2868 r_leafpatches[r_numleafpatches[0]] = checkout[k];
2869 patch = &r_cpatches[checkout[k]];
2870 }
2871 else
2872 {
2873 while (r_numcpatches[0] >= r_numcpatches[1])
2874 {
2875 // force reallocation
2876 r_numcpatches[1] += MAX_CM_PATCHES;
2877 if (!(r_cpatches = (cpatch_t*) cake_realloc(r_cpatches, r_numcpatches[1]*sizeof(cpatch_t), "Q3BSP::CreatePatchesForLeafs.r_patches")))
2878 ThrowException(ALLOCATION_ERROR, "Q3BSP::CreatePatchesForLeafs.r_patches");
2879 }
2880
2881 patch = &r_cpatches[r_numcpatches[0]];
2882 patch->shader = face->shader;
2883 r_leafpatches[r_numleafpatches[0]] = r_numcpatches[0];
2884 checkout[k] = r_numcpatches[0]++;
2885
2886 // Create a verts array for the CreatePatch function
2887 vec4_t *verts = new vec4_t[face->numverts[0]];
2888 if (!verts) ThrowException(ALLOCATION_ERROR, "Q3BSP::BuildBezierPatch.verts");
2889
2890 for (int n = 0; n < face->numverts[0]; ++n)
2891 {
2892 VectorCopy(face->firstvert[0][n].v_point, verts[n]);
2893 }
2894
2895 CreatePatch(patch, face->numverts[0], verts, face->patch_cp);
2896
2897 delete [] verts;
2898 }
2899
2900 if ((shad = world->shaders.GetShader(patch->shader)))
2901 leaf->contents |= shad->content_flags;
2902 else
2903 leaf->contents |= -1;
2904 leaf->numleafpatches++;
2905
2906 r_numleafpatches[0]++;
2907 }
2908 }
2909
2910 delete [] checkout;
2911 }
2912
2913 // ----------------------------------------------------------------------------
2914
2915 #define PLANE_EPSILON 0.001f
PointInsideBrush(int brushnum,vec3_t p)2916 bool Q3BSP::PointInsideBrush(int brushnum, vec3_t p)
2917 {
2918 cbrush_t *brush = &r_brushes[brushnum];
2919 cbrushside_t *side;
2920
2921 for (int i = 0; i < brush->numsides; ++i)
2922 {
2923 side = &r_brushsides[brush->firstbrushside+i];
2924 if (PointDistance(p, r_planes+side->planeidx) > PLANE_EPSILON) return false;
2925 }
2926
2927 return true;
2928 }
2929
2930 // ------------------------------------------------------------
2931 // Movement clipping
2932 // ------------------------------------------------------------
CheckMove(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,int head_node,int brushmask)2933 trace_t Q3BSP::CheckMove(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int head_node, int brushmask)
2934 {
2935 trace_t trace_trace;
2936 vec3_t point;
2937
2938 ++checkcount; // for multi-check avoidance
2939
2940 // fill in a default trace
2941 memset(&trace_trace, 0, sizeof(trace_trace));
2942 trace_trace.fraction = 1;
2943 trace_trace.contents = 0;
2944 trace_trace.shader = -1;
2945 // trace_trace.ent = NULL;
2946
2947 if (!r_numnodes[0]) return trace_trace;
2948
2949 trace_trace.tracemask = brushmask;
2950 VectorCopy(start, trace_trace.start);
2951 VectorCopy(end, trace_trace.end);
2952 VectorCopy(mins, trace_trace.mins);
2953 VectorCopy(maxs, trace_trace.maxs);
2954
2955 // build a bounding box of the entire move
2956 ClearBounds(trace_trace.absmins, trace_trace.absmaxs);
2957 VectorAdd(start, trace_trace.mins, point);
2958 AddPointToBounds(point, trace_trace.absmins, trace_trace.absmaxs);
2959 VectorAdd(start, trace_trace.maxs, point);
2960 AddPointToBounds(point, trace_trace.absmins, trace_trace.absmaxs);
2961 VectorAdd(end, trace_trace.mins, point);
2962 AddPointToBounds(point, trace_trace.absmins, trace_trace.absmaxs);
2963 VectorAdd(end, trace_trace.maxs, point);
2964 AddPointToBounds(point, trace_trace.absmins, trace_trace.absmaxs);
2965
2966 // Check for position test special case
2967 if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2])
2968 {
2969 int leafs[1024];
2970 int i, numleafs;
2971 vec3_t c1, c2;
2972 int topnode;
2973
2974 VectorAdd(start, mins, c1);
2975 VectorAdd(start, maxs, c2);
2976
2977 c1[0] -= 1; c2[0] += 1;
2978 c1[1] -= 1; c2[1] += 1;
2979 c1[2] -= 1; c2[2] += 1;
2980
2981 numleafs = BoxLeafnums_headnode(c1, c2, leafs, 1024, head_node, &topnode);
2982 for (i = 0; i < numleafs; ++i)
2983 {
2984 TestInLeaf(leafs[i], &trace_trace);
2985 if (trace_trace.allSolid) break;
2986 }
2987 VectorCopy(start, trace_trace.end);
2988 return trace_trace;
2989 }
2990
2991 // check for point special case
2992 if (mins[0] == 0 && maxs[0] == 0 &&
2993 mins[1] == 0 && maxs[1] == 0 &&
2994 mins[2] == 0 && maxs[2] == 0)
2995 {
2996 trace_trace.isPoint = true;
2997 VectorClear(trace_trace.size);
2998 }
2999 else
3000 {
3001 trace_trace.isPoint = false;
3002 trace_trace.size[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0];
3003 trace_trace.size[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1];
3004 trace_trace.size[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2];
3005 }
3006
3007 RecursiveHullCheck(0, 1, start, end, head_node, &trace_trace);
3008
3009 // Calculate final coordinates
3010 if (trace_trace.fraction == 1)
3011 {
3012 VectorCopy(end, trace_trace.end);
3013 }
3014 else
3015 {
3016 trace_trace.end[0] = start[0] + trace_trace.fraction * (end[0] - start[0]);
3017 trace_trace.end[1] = start[1] + trace_trace.fraction * (end[1] - start[1]);
3018 trace_trace.end[2] = start[2] + trace_trace.fraction * (end[2] - start[2]);
3019 }
3020
3021 return trace_trace;
3022 }
3023
RecursiveHullCheck(float sf,float ef,const vec3_t sp,const vec3_t ep,int node_num,trace_t * trace_trace)3024 void Q3BSP::RecursiveHullCheck(float sf, float ef,
3025 const vec3_t sp, const vec3_t ep,
3026 int node_num, trace_t *trace_trace)
3027 {
3028 float t1, t2, offset;
3029
3030 // If the path was blocked by a nearer obstacle, don't bother checking
3031 if (trace_trace->fraction <= sf) return;
3032
3033 // We found a leaf, check the whole path against its brushes
3034 if (node_num < 0)
3035 {
3036 TraceToLeaf(~node_num, trace_trace);
3037 return;
3038 }
3039
3040 cnode_t* node = r_nodes + node_num;
3041 cplane_t* plane = r_planes + node->planeidx;
3042
3043 if (plane->type < 3)
3044 {
3045 t1 = sp[plane->type] - plane->dist;
3046 t2 = ep[plane->type] - plane->dist;
3047 offset = trace_trace->size[plane->type];
3048 }
3049 else
3050 {
3051 t1 = DotProduct(sp, plane->normal) - plane->dist;
3052 t2 = DotProduct(ep, plane->normal) - plane->dist;
3053 if (trace_trace->isPoint)
3054 offset = 0;
3055 else
3056 offset = (fabsf(trace_trace->size[0]*plane->normal[0]) +
3057 fabsf(trace_trace->size[1]*plane->normal[1]) +
3058 fabsf(trace_trace->size[2]*plane->normal[2]));
3059 }
3060
3061 #if 0
3062 RecursiveHullCheck(sf, ef, sp, ep, node->children[0], trace_trace); // front
3063 RecursiveHullCheck(sf, ef, sp, ep, node->children[1], trace_trace); // back
3064 return;
3065 #endif
3066
3067 // The whole volume is in front of the plane
3068 // See which sides we need to consider
3069 if ((t1 >= offset) && (t2 >= offset))
3070 {
3071 RecursiveHullCheck(sf, ef, sp, ep, node->children[0], trace_trace); // front
3072 return;
3073 }
3074
3075 // The whole volume is in the back of the plane
3076 if ((t1 < -offset) && (t2 < -offset))
3077 {
3078 RecursiveHullCheck(sf, ef, sp, ep, node->children[1], trace_trace); // back
3079 return;
3080 }
3081
3082 // Else, the box is split. Check the two halves.
3083 int side;
3084 float idist, frac, frac2, midf;
3085 vec3_t midp;
3086
3087 // Put the crosspoint DIST_EPSILON pixels on the near side
3088 if (t1 < t2)
3089 {
3090 idist = 1.f / (t1 - t2);
3091 side = 1; // back
3092 frac = (t1 - offset + DIST_EPSILON) * idist;
3093 frac2 = (t1 + offset + DIST_EPSILON) * idist;
3094 }
3095 else if (t1 > t2)
3096 {
3097 idist = 1.f / (t1 - t2);
3098 side = 0; // front
3099 frac = (t1 + offset + DIST_EPSILON) * idist;
3100 frac2 = (t1 - offset - DIST_EPSILON) * idist;
3101 }
3102 else
3103 {
3104 side = 0; // front
3105 frac = 1;
3106 frac2 = 0;
3107 }
3108
3109 // Move from start to the plane (move up to the node)
3110 if (frac < 0) frac = 0;
3111 if (frac > 1) frac = 1;
3112
3113 midf = sf + (ef - sf)*frac;
3114 midp[0] = sp[0] + frac*(ep[0] - sp[0]);
3115 midp[1] = sp[1] + frac*(ep[1] - sp[1]);
3116 midp[2] = sp[2] + frac*(ep[2] - sp[2]);
3117
3118 RecursiveHullCheck(sf, midf, sp, midp, node->children[side], trace_trace);
3119
3120 // Move from the plane to the end
3121 // Go past the node
3122 if (frac2 < 0) frac2 = 0;
3123 if (frac2 > 1) frac2 = 1;
3124
3125 midf = sf + (ef - sf)*frac2;
3126 midp[0] = sp[0] + frac2*(ep[0] - sp[0]);
3127 midp[1] = sp[1] + frac2*(ep[1] - sp[1]);
3128 midp[2] = sp[2] + frac2*(ep[2] - sp[2]);
3129
3130 RecursiveHullCheck(midf, ef, midp, ep, node->children[side^1], trace_trace);
3131 }
3132
TraceToLeaf(int leafnum,trace_t * trace_trace)3133 void Q3BSP::TraceToLeaf(int leafnum, trace_t *trace_trace)
3134 {
3135 cleaf_t* leaf = &r_leafs[leafnum];
3136 if (!(leaf->contents & trace_trace->tracemask)) return;
3137
3138 int i, brushnum, patchnum;
3139 cbrush_t *cbrush;
3140 cpatch_t *cpatch;
3141 Shader* shad;
3142
3143 for (i = 0; i < leaf->numleafbrushes; ++i)
3144 {
3145 brushnum = r_leafbrushes[leaf->firstleafbrush+i];
3146 cbrush = &r_brushes[brushnum];
3147
3148 if (cbrush->checkcount == checkcount) continue; // already checked this brush in another leaf
3149 cbrush->checkcount = checkcount;
3150
3151 if (!(cbrush->contents & trace_trace->tracemask)) continue;
3152
3153 ClipBoxToBrush(cbrush, trace_trace);
3154
3155 // Already fully blocked
3156 if (!trace_trace->fraction) return;
3157 }
3158
3159 if (r_nocurves.ivalue) return;
3160
3161 for (i = 0; i < leaf->numleafpatches; ++i)
3162 {
3163 patchnum = r_leafpatches[leaf->firstleafpatch+i];
3164 cpatch = &r_cpatches[patchnum];
3165
3166 if (cpatch->checkcount == checkcount) continue; // already checked this patch in another leaf
3167 cpatch->checkcount = checkcount;
3168
3169 if (!(shad = world->shaders.GetShader(cpatch->shader))) continue;
3170 if (!(shad->content_flags & trace_trace->tracemask)) continue;
3171 if (!BoundsIntersect(cpatch->absmins, cpatch->absmaxs, trace_trace->absmins, trace_trace->absmaxs)) continue;
3172
3173 for (int j = 0; j < cpatch->numbrushes; ++j)
3174 {
3175 ClipBoxToPatch(&r_brushes[cpatch->firstbrush+j], trace_trace);
3176 if (!trace_trace->fraction) return;
3177 }
3178 }
3179 }
3180
TestInLeaf(int leafnum,trace_t * trace_trace)3181 void Q3BSP::TestInLeaf(int leafnum, trace_t *trace_trace)
3182 {
3183 cleaf_t* leaf = &r_leafs[leafnum];
3184 if (!(leaf->contents & trace_trace->tracemask)) return;
3185
3186 int i, brushnum, patchnum;
3187 cbrush_t *cbrush;
3188 cpatch_t *cpatch;
3189 Shader *shad;
3190
3191 for (i = 0; i < leaf->numleafbrushes; ++i)
3192 {
3193 brushnum = r_leafbrushes[leaf->firstleafbrush+i];
3194 cbrush = &r_brushes[brushnum];
3195
3196 if (cbrush->checkcount == checkcount) continue; // already checked this brush in another leaf
3197 cbrush->checkcount = checkcount;
3198
3199 if (!(cbrush->contents & trace_trace->tracemask)) continue;
3200
3201 TestBoxInBrush(cbrush, trace_trace);
3202
3203 // Already fully blocked
3204 if (!trace_trace->fraction) return;
3205 }
3206
3207 if (r_nocurves.ivalue) return;
3208
3209 for (i = 0; i < leaf->numleafpatches; ++i)
3210 {
3211 patchnum = r_leafpatches[leaf->firstleafpatch+i];
3212 cpatch = &r_cpatches[patchnum];
3213
3214 if (cpatch->checkcount == checkcount) continue; // already checked this patch in another leaf
3215 cpatch->checkcount = checkcount;
3216
3217 if (!(shad = world->shaders.GetShader(cpatch->shader))) continue;
3218 if (!(shad->content_flags & trace_trace->tracemask)) continue;
3219 if (!BoundsIntersect(cpatch->absmins, cpatch->absmaxs, trace_trace->absmins, trace_trace->absmaxs)) continue;
3220
3221 for (int j = 0; j < cpatch->numbrushes; ++j)
3222 {
3223 TestBoxInPatch(&r_brushes[cpatch->firstbrush+j], trace_trace);
3224 if (!trace_trace->fraction) return;
3225 }
3226 }
3227 }
3228
ClipBoxToBrush(cbrush_t * brush,trace_t * trace)3229 void Q3BSP::ClipBoxToBrush(cbrush_t *brush, trace_t *trace)
3230 {
3231 if (brush->numsides <= 0) return;
3232
3233 cbrushside_t *side, *leadside = NULL;
3234 cplane_t* plane, *clipplane = NULL;
3235 vec3_t ofs;
3236 float d1, d2, f;
3237 float enterfrac = -1;
3238 float leavefrac = 1;
3239 bool startout = false;
3240 bool getout = false;
3241 vec3_t hitNormal = { 0, 0, 0 };
3242
3243 for (int i = 0; i < brush->numsides; ++i)
3244 {
3245 side = &r_brushsides[brush->firstbrushside+i];
3246 plane = &r_planes[side->planeidx];
3247
3248 // FIXME: special case for axial
3249
3250 if (!trace->isPoint)
3251 {
3252 // Calculate distances, taking the bounding box dimensions into account
3253 if (plane->normal[0] < 0) ofs[0] = trace->maxs[0]; else ofs[0] = trace->mins[0];
3254 if (plane->normal[1] < 0) ofs[1] = trace->maxs[1]; else ofs[1] = trace->mins[1];
3255 if (plane->normal[2] < 0) ofs[2] = trace->maxs[2]; else ofs[2] = trace->mins[2];
3256
3257 if (plane->type < 3)
3258 {
3259 d1 = trace->start[plane->type] + ofs[plane->type] - plane->dist;
3260 d2 = trace->end[plane->type] + ofs[plane->type] - plane->dist;
3261 }
3262 else
3263 {
3264 d1 = (trace->start[0] + ofs[0]) * plane->normal[0] +
3265 (trace->start[1] + ofs[1]) * plane->normal[1] +
3266 (trace->start[2] + ofs[2]) * plane->normal[2] - plane->dist;
3267 d2 = (trace->end[0] + ofs[0]) * plane->normal[0] +
3268 (trace->end[1] + ofs[1]) * plane->normal[1] +
3269 (trace->end[2] + ofs[2]) * plane->normal[2] - plane->dist;
3270 }
3271 }
3272 else
3273 { // special point case
3274 if (plane->type < 3)
3275 {
3276 d1 = trace->start[plane->type] - plane->dist;
3277 d2 = trace->end[plane->type] - plane->dist;
3278 }
3279 else
3280 {
3281 d1 = DotProduct(trace->start, plane->normal) - plane->dist;
3282 d2 = DotProduct(trace->end, plane->normal) - plane->dist;
3283 }
3284 }
3285
3286 #if 0
3287 if (d2 >= -DIST_EPSILON) getout = true;
3288 if (d1 >= -DIST_EPSILON) startout = true;
3289 #else
3290 if (d2 > 0) getout = true;
3291 if (d1 > 0) startout = true;
3292 #endif
3293
3294 // Both in front of face : outside this brush (completely in front of face, no intersection)
3295 if ((d1 > 0) && (d2 >= d1)) return;
3296
3297 // Both behind the face : will get clipped by another plane
3298 if ((d1 <= 0) && (d2 <= 0)) continue;
3299
3300 // crosses face
3301 if (d1 > d2) // Entering the brush
3302 {
3303 f = (d1 - DIST_EPSILON) / (d1 - d2);
3304 if (f > enterfrac)
3305 {
3306 enterfrac = f;
3307 VectorCopy(plane->normal, hitNormal);
3308 clipplane = plane;
3309 leadside = side;
3310 }
3311 }
3312 else
3313 {
3314 f = (d1 + DIST_EPSILON) / (d1 - d2);
3315 if (f < leavefrac) leavefrac = f;
3316 }
3317 }
3318
3319 if (!startout)
3320 {
3321 // original point was inside brush
3322 trace->startSolid = true;
3323 if (!getout) trace->allSolid = true;
3324 return;
3325 }
3326
3327 if (enterfrac < leavefrac)
3328 {
3329 if (enterfrac > -1 && enterfrac < trace->fraction)
3330 {
3331 if (enterfrac < 0) enterfrac = 0;
3332 trace->fraction = enterfrac;
3333 trace->plane = *clipplane;
3334 trace->shader = leadside->shader;
3335 trace->contents = brush->contents;
3336 }
3337 }
3338 }
3339
ClipBoxToPatch(cbrush_t * brush,trace_t * trace)3340 void Q3BSP::ClipBoxToPatch(cbrush_t *brush, trace_t *trace)
3341 {
3342 if (brush->numsides <= 0) return;
3343
3344 cbrushside_t *side, *leadside = NULL;
3345 cplane_t* plane, *clipplane = NULL;
3346 vec3_t ofs;
3347 float d1, d2, f;
3348 float enterfrac = -1;
3349 float leavefrac = 1;
3350 bool startout = false;
3351 vec3_t hitNormal = { 0, 0, 0 };
3352
3353 for (int i = 0; i < brush->numsides; ++i)
3354 {
3355 side = &r_brushsides[brush->firstbrushside+i];
3356 plane = &r_planes[side->planeidx];
3357
3358 if (!trace->isPoint)
3359 {
3360 if (plane->normal[0] < 0) ofs[0] = trace->maxs[0]; else ofs[0] = trace->mins[0];
3361 if (plane->normal[1] < 0) ofs[1] = trace->maxs[1]; else ofs[1] = trace->mins[1];
3362 if (plane->normal[2] < 0) ofs[2] = trace->maxs[2]; else ofs[2] = trace->mins[2];
3363
3364 if (plane->type < 3)
3365 {
3366 d1 = trace->start[plane->type] + ofs[plane->type] - plane->dist;
3367 d2 = trace->end[plane->type] + ofs[plane->type] - plane->dist;
3368 }
3369 else
3370 {
3371 d1 = (trace->start[0] + ofs[0]) * plane->normal[0] +
3372 (trace->start[1] + ofs[1]) * plane->normal[1] +
3373 (trace->start[2] + ofs[2]) * plane->normal[2] - plane->dist;
3374 d2 = (trace->end[0] + ofs[0]) * plane->normal[0] +
3375 (trace->end[1] + ofs[1]) * plane->normal[1] +
3376 (trace->end[2] + ofs[2]) * plane->normal[2] - plane->dist;
3377 }
3378 }
3379 else
3380 { // special point case
3381 if (plane->type < 3)
3382 {
3383 d1 = trace->start[plane->type] - plane->dist;
3384 d2 = trace->end[plane->type] - plane->dist;
3385 }
3386 else
3387 {
3388 d1 = DotProduct(trace->start, plane->normal) - plane->dist;
3389 d2 = DotProduct(trace->end, plane->normal) - plane->dist;
3390 }
3391 }
3392
3393 if (d1 > 0) startout = true;
3394
3395 // if completely in front of face, no intersection
3396 if (d1 > 0 && d2 >= d1) return;
3397 if (d1 <= 0 && d2 <= 0) continue;
3398
3399 // crosses face
3400 if (d1 > d2)
3401 { // enter
3402 f = (d1-DIST_EPSILON) / (d1-d2);
3403 if (f > enterfrac)
3404 {
3405 enterfrac = f;
3406 clipplane = plane;
3407 VectorCopy(plane->normal, hitNormal);
3408 leadside = side;
3409 }
3410 }
3411 else
3412 { // leave
3413 f = (d1 /*+ DIST_EPSILON*/) / (d1-d2);
3414 if (f < leavefrac) leavefrac = f;
3415 }
3416 }
3417
3418 if (!startout) return; // original point is inside the patch
3419
3420 if (enterfrac < leavefrac)
3421 {
3422 if (leadside && leadside->shader >= 0 && enterfrac < trace->fraction)
3423 {
3424 if (enterfrac < 0) enterfrac = 0;
3425 trace->fraction = enterfrac;
3426 trace->plane = *clipplane;
3427 trace->shader = leadside->shader;
3428 trace->contents = brush->contents;
3429 }
3430 }
3431 }
3432
TestBoxInBrush(cbrush_t * brush,trace_t * trace)3433 void Q3BSP::TestBoxInBrush(cbrush_t *brush, trace_t *trace)
3434 {
3435 if (brush->numsides <= 0) return;
3436
3437 int i;
3438 vec3_t ofs;
3439 float d1;
3440 cbrushside_t *side;
3441 cplane_t* plane;
3442
3443 for (i = 0; i < brush->numsides; ++i)
3444 {
3445 side = &r_brushsides[brush->firstbrushside+i];
3446 plane = r_planes + side->planeidx;
3447
3448 // general box case
3449
3450 // push the plane out appropriately for mins/maxs
3451
3452 // FIXME: use signbits into 8 way lookup for each mins/maxs
3453 if (plane->normal[0] < 0) ofs[0] = trace->maxs[0]; else ofs[0] = trace->mins[0];
3454 if (plane->normal[1] < 0) ofs[1] = trace->maxs[1]; else ofs[1] = trace->mins[1];
3455 if (plane->normal[2] < 0) ofs[2] = trace->maxs[2]; else ofs[2] = trace->mins[2];
3456
3457 if (plane->type < 3)
3458 {
3459 d1 = trace->start[plane->type] + ofs[plane->type] - plane->dist;
3460 }
3461 else
3462 {
3463 d1 = (trace->start[0] + ofs[0]) * plane->normal[0] +
3464 (trace->start[1] + ofs[1]) * plane->normal[1] +
3465 (trace->start[2] + ofs[2]) * plane->normal[2] - plane->dist;
3466 }
3467
3468 // if completely in front of face, no intersection
3469 if (d1 > 0) return;
3470 }
3471
3472 // inside this brush
3473 trace->startSolid = trace->allSolid = true;
3474 trace->fraction = 0;
3475 trace->contents = brush->contents;
3476 }
3477
TestBoxInPatch(cbrush_t * brush,trace_t * trace)3478 void Q3BSP::TestBoxInPatch(cbrush_t *brush, trace_t *trace)
3479 {
3480 if (brush->numsides <= 0) return;
3481
3482 int i;
3483 vec3_t ofs;
3484 float d1, maxdist;
3485 cbrushside_t *side;
3486 cplane_t * plane;
3487
3488 maxdist = -9999;
3489
3490 for (i = 0; i < brush->numsides; ++i)
3491 {
3492 side = &r_brushsides[brush->firstbrushside+i];
3493 plane = r_planes + side->planeidx;
3494
3495 // general box case
3496
3497 // push the plane out appropriately for mins/maxs
3498
3499 // FIXME: use signbits into 8 way lookup for each mins/maxs
3500 if (plane->normal[0] < 0) ofs[0] = trace->maxs[0]; else ofs[0] = trace->mins[0];
3501 if (plane->normal[1] < 0) ofs[1] = trace->maxs[1]; else ofs[1] = trace->mins[1];
3502 if (plane->normal[2] < 0) ofs[2] = trace->maxs[2]; else ofs[2] = trace->mins[2];
3503
3504 if (plane->type < 3)
3505 {
3506 d1 = trace->start[plane->type] + ofs[plane->type] - plane->dist;
3507 }
3508 else
3509 {
3510 d1 = (trace->start[0] + ofs[0]) * plane->normal[0] +
3511 (trace->start[1] + ofs[1]) * plane->normal[1] +
3512 (trace->start[2] + ofs[2]) * plane->normal[2] - plane->dist;
3513 }
3514
3515 // if completely in front of face, no intersection
3516 if (d1 > 0) return;
3517
3518 if (side->shader >= 0 && d1 > maxdist) maxdist = d1;
3519 }
3520
3521 // FIXME
3522 // if (maxdist < -0.25)
3523 // return; // deep inside the patch
3524
3525 // inside this patch
3526 trace->startSolid = trace->allSolid = true;
3527 trace->fraction = 0;
3528 trace->contents = brush->contents;
3529 }
3530
BoxLeafnums_headnode(vec3_t mins,vec3_t maxs,int * list,int listsize,int headnode,int * topnode)3531 int Q3BSP::BoxLeafnums_headnode(vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode)
3532 {
3533 leaf_list = list;
3534 leaf_count = 0;
3535 leaf_maxcount = listsize;
3536 leaf_mins = mins;
3537 leaf_maxs = maxs;
3538 leaf_topnode = -1;
3539
3540 BoxLeafnums_r(headnode);
3541
3542 if (topnode) *topnode = leaf_topnode;
3543
3544 return leaf_count;
3545 }
3546
BoxLeafnums_r(int nodenum)3547 void Q3BSP::BoxLeafnums_r(int nodenum)
3548 {
3549 cplane_t *plane;
3550 cnode_t *node;
3551 int s;
3552
3553 while (1)
3554 {
3555 if (nodenum < 0)
3556 {
3557 if (leaf_count >= leaf_maxcount) return;
3558 leaf_list[leaf_count++] = -1 - nodenum;
3559 return;
3560 }
3561
3562 node = &r_nodes[nodenum];
3563 plane = r_planes + node->planeidx;
3564 s = BoxOnPlaneSide(leaf_mins, leaf_maxs, plane);
3565 // s = BOX_ON_PLANE_SIDE(leaf_mins, leaf_maxs, plane);
3566 if (s == 1) nodenum = node->children[0];
3567 else if (s == 2) nodenum = node->children[1];
3568 else
3569 { // go down both
3570 if (leaf_topnode == -1)
3571 leaf_topnode = nodenum;
3572 BoxLeafnums_r(node->children[0]);
3573 nodenum = node->children[1];
3574 }
3575 }
3576 }
3577