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