1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: r_bsp.cpp 4350 2010-12-17 15:36:16Z dj_jl $
11 //**
12 //** Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //** This program is free software; you can redistribute it and/or
15 //** modify it under the terms of the GNU General Public License
16 //** as published by the Free Software Foundation; either version 2
17 //** of the License, or (at your option) any later version.
18 //**
19 //** This program is distributed in the hope that it will be useful,
20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 //** GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 //**
26 //** BSP traversal, handling of LineSegs for rendering.
27 //**
28 //**************************************************************************
29
30 // HEADER FILES ------------------------------------------------------------
31
32 #include "gamedefs.h"
33 #include "r_local.h"
34
35 // MACROS ------------------------------------------------------------------
36
37 #define HORIZON_SURF_SIZE (sizeof(surface_t) + sizeof(TVec) * 3)
38
39 // TYPES -------------------------------------------------------------------
40
41 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
42
43 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
44
45 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
46
47 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
48
49 // PUBLIC DATA DEFINITIONS -------------------------------------------------
50
51 // PRIVATE DATA DEFINITIONS ------------------------------------------------
52
53 static subsector_t* r_sub;
54 static subregion_t* r_subregion;
55 static sec_region_t* r_region;
56 static bool MirrorClipSegs;
57
58 static VCvarI r_maxmirrors("r_maxmirrors", "4", CVAR_Archive);
59
60 // CODE --------------------------------------------------------------------
61
62 //==========================================================================
63 //
64 // VRenderLevelShared::SetUpFrustumIndexes
65 //
66 //==========================================================================
67
SetUpFrustumIndexes()68 void VRenderLevelShared::SetUpFrustumIndexes()
69 {
70 guard(VRenderLevelShared::SetUpFrustumIndexes);
71 for (int i = 0; i < 4; i++)
72 {
73 int *pindex = FrustumIndexes[i];
74 for (int j = 0; j < 3; j++)
75 {
76 if (view_clipplanes[i].normal[j] < 0)
77 {
78 pindex[j] = j;
79 pindex[j + 3] = j + 3;
80 }
81 else
82 {
83 pindex[j] = j + 3;
84 pindex[j + 3] = j;
85 }
86 }
87 }
88 unguard;
89 }
90
91 //==========================================================================
92 //
93 // VRenderLevel::QueueWorldSurface
94 //
95 //==========================================================================
96
QueueWorldSurface(surface_t * surf)97 void VRenderLevel::QueueWorldSurface(surface_t* surf)
98 {
99 guard(VRenderLevel::QueueWorldSurface);
100 bool lightmaped = surf->lightmap != NULL ||
101 surf->dlightframe == r_dlightframecount;
102
103 if (lightmaped)
104 {
105 CacheSurface(surf);
106 if (Drawer->HaveMultiTexture)
107 {
108 return;
109 }
110 }
111
112 QueueSimpleSurf(surf);
113 unguard;
114 }
115
116 //==========================================================================
117 //
118 // VAdvancedRenderLevel::QueueWorldSurface
119 //
120 //==========================================================================
121
QueueWorldSurface(surface_t * surf)122 void VAdvancedRenderLevel::QueueWorldSurface(surface_t* surf)
123 {
124 guard(VAdvancedRenderLevel::QueueWorldSurface);
125 QueueSimpleSurf(surf);
126 unguard;
127 }
128
129 //==========================================================================
130 //
131 // VRenderLevelShared::DrawSurfaces
132 //
133 //==========================================================================
134
QueueSimpleSurf(surface_t * surf)135 void VRenderLevelShared::QueueSimpleSurf(surface_t* surf)
136 {
137 guard(VRenderLevelShared::QueueSimpleSurf);
138 if (SimpleSurfsTail)
139 {
140 SimpleSurfsTail->DrawNext = surf;
141 SimpleSurfsTail = surf;
142 }
143 else
144 {
145 SimpleSurfsHead = surf;
146 SimpleSurfsTail = surf;
147 }
148 surf->DrawNext = NULL;
149 unguard;
150 }
151
152 //==========================================================================
153 //
154 // VRenderLevelShared::QueueSkyPortal
155 //
156 //==========================================================================
157
QueueSkyPortal(surface_t * surf)158 void VRenderLevelShared::QueueSkyPortal(surface_t* surf)
159 {
160 guard(VRenderLevelShared::QueueSkyPortal);
161 if (SkyPortalsTail)
162 {
163 SkyPortalsTail->DrawNext = surf;
164 SkyPortalsTail = surf;
165 }
166 else
167 {
168 SkyPortalsHead = surf;
169 SkyPortalsTail = surf;
170 }
171 surf->DrawNext = NULL;
172 unguard;
173 }
174
175 //==========================================================================
176 //
177 // VRenderLevelShared::QueueHorizonPortal
178 //
179 //==========================================================================
180
QueueHorizonPortal(surface_t * surf)181 void VRenderLevelShared::QueueHorizonPortal(surface_t* surf)
182 {
183 guard(VRenderLevelShared::QueueHorizonPortal);
184 if (HorizonPortalsTail)
185 {
186 HorizonPortalsTail->DrawNext = surf;
187 HorizonPortalsTail = surf;
188 }
189 else
190 {
191 HorizonPortalsHead = surf;
192 HorizonPortalsTail = surf;
193 }
194 surf->DrawNext = NULL;
195 unguard;
196 }
197
198 //==========================================================================
199 //
200 // VRenderLevelShared::DrawSurfaces
201 //
202 //==========================================================================
203
DrawSurfaces(surface_t * InSurfs,texinfo_t * texinfo,VEntity * SkyBox,int LightSourceSector,int SideLight,bool AbsSideLight,bool CheckSkyBoxAlways)204 void VRenderLevelShared::DrawSurfaces(surface_t* InSurfs, texinfo_t *texinfo,
205 VEntity* SkyBox, int LightSourceSector, int SideLight, bool AbsSideLight,
206 bool CheckSkyBoxAlways)
207 {
208 guard(VRenderLevelShared::DrawSurfaces);
209 surface_t* surfs = InSurfs;
210 if (!surfs)
211 {
212 return;
213 }
214
215 if (texinfo->Tex->Type == TEXTYPE_Null)
216 {
217 return;
218 }
219
220 sec_params_t* LightParams = LightSourceSector == -1 ? r_region->params :
221 &Level->Sectors[LightSourceSector].params;
222 int lLev = (AbsSideLight ? 0 : LightParams->lightlevel) + SideLight;
223 lLev = FixedLight ? FixedLight : lLev + ExtraLight;
224 lLev = MID(0, lLev, 255);
225 if (r_darken)
226 {
227 lLev = light_remap[lLev];
228 }
229 vuint32 Fade = GetFade(r_region);
230
231 if (SkyBox && (SkyBox->EntityFlags & VEntity::EF_FixedModel))
232 {
233 SkyBox = NULL;
234 }
235 bool IsStack = SkyBox && SkyBox->eventSkyBoxGetAlways();
236 if (texinfo->Tex == GTextureManager[skyflatnum] ||
237 IsStack && CheckSkyBoxAlways)
238 {
239 VSky* Sky = NULL;
240 if (!SkyBox && r_sub->sector->Sky & SKY_FROM_SIDE)
241 {
242 int Tex;
243 bool Flip;
244 if (r_sub->sector->Sky == SKY_FROM_SIDE)
245 {
246 Tex = Level->LevelInfo->Sky2Texture;
247 Flip = true;
248 }
249 else
250 {
251 side_t* Side = &Level->Sides[(r_sub->sector->Sky &
252 (SKY_FROM_SIDE - 1)) - 1];
253 Tex = Side->TopTexture;
254 Flip = !!Level->Lines[Side->LineNum].arg3;
255 }
256 if (GTextureManager[Tex]->Type != TEXTYPE_Null)
257 {
258 for (int i = 0; i < SideSkies.Num(); i++)
259 {
260 if (SideSkies[i]->SideTex == Tex &&
261 SideSkies[i]->SideFlip == Flip)
262 {
263 Sky = SideSkies[i];
264 break;
265 }
266 }
267 if (!Sky)
268 {
269 Sky = new VSky;
270 Sky->Init(Tex, Tex, 0, 0, false,
271 !!(Level->LevelInfo->LevelInfoFlags &
272 VLevelInfo::LIF_ForceNoSkyStretch), Flip, false);
273 SideSkies.Append(Sky);
274 }
275 }
276 }
277 if (!Sky && !SkyBox)
278 {
279 InitSky();
280 Sky = &BaseSky;
281 }
282
283 VPortal* Portal = NULL;
284 if (SkyBox)
285 {
286 for (int i = 0; i < Portals.Num(); i++)
287 {
288 if (Portals[i] && Portals[i]->MatchSkyBox(SkyBox))
289 {
290 Portal = Portals[i];
291 break;
292 }
293 }
294 if (!Portal)
295 {
296 if (IsStack)
297 {
298 Portal = new VSectorStackPortal(this, SkyBox);
299 }
300 else
301 {
302 Portal = new VSkyBoxPortal(this, SkyBox);
303 }
304 Portals.Append(Portal);
305 }
306 }
307 else
308 {
309 for (int i = 0; i < Portals.Num(); i++)
310 {
311 if (Portals[i] && Portals[i]->MatchSky(Sky))
312 {
313 Portal = Portals[i];
314 break;
315 }
316 }
317 if (!Portal)
318 {
319 Portal = new VSkyPortal(this, Sky);
320 Portals.Append(Portal);
321 }
322 }
323 do
324 {
325 Portal->Surfs.Append(surfs);
326 if (IsStack && CheckSkyBoxAlways &&
327 SkyBox->eventSkyBoxGetPlaneAlpha())
328 {
329 surfs->Light = (lLev << 24) | LightParams->LightColour;
330 surfs->Fade = Fade;
331 surfs->dlightframe = r_sub->dlightframe;
332 surfs->dlightbits = r_sub->dlightbits;
333 DrawTranslucentPoly(surfs, surfs->verts, surfs->count,
334 0, SkyBox->eventSkyBoxGetPlaneAlpha(), false, 0,
335 false, 0, 0, TVec(), 0, TVec(), TVec(), TVec());
336 }
337
338 if (!Drawer->HaveStencil)
339 {
340 if (PortalLevel == 0)
341 {
342 world_surf_t& S = WorldSurfs.Alloc();
343 S.Surf = surfs;
344 S.Type = 1;
345 }
346 else
347 {
348 QueueSkyPortal(surfs);
349 }
350 }
351
352 surfs = surfs->next;
353 } while (surfs);
354 return;
355 }
356
357 do
358 {
359 surfs->Light = (lLev << 24) | LightParams->LightColour;
360 surfs->Fade = Fade;
361 surfs->dlightframe = r_sub->dlightframe;
362 surfs->dlightbits = r_sub->dlightbits;
363
364 if (texinfo->Alpha > 1.0)
365 {
366 if (PortalLevel == 0)
367 {
368 world_surf_t& S = WorldSurfs.Alloc();
369 S.Surf = surfs;
370 S.Type = 0;
371 }
372 else
373 {
374 QueueWorldSurface(surfs);
375 }
376 }
377 else
378 {
379 DrawTranslucentPoly(surfs, surfs->verts, surfs->count,
380 0, texinfo->Alpha, texinfo->Additive, 0, false, 0, 0,
381 TVec(), 0, TVec(), TVec(), TVec());
382 }
383 surfs = surfs->next;
384 } while (surfs);
385 unguard;
386 }
387
388 //==========================================================================
389 //
390 // VRenderLevelShared::RenderHorizon
391 //
392 //==========================================================================
393
RenderHorizon(drawseg_t * dseg)394 void VRenderLevelShared::RenderHorizon(drawseg_t* dseg)
395 {
396 guard(VRenderLevelShared::RenderHorizon);
397 seg_t* Seg = dseg->seg;
398
399 if (!dseg->HorizonTop)
400 {
401 dseg->HorizonTop = (surface_t*)Z_Malloc(HORIZON_SURF_SIZE);
402 dseg->HorizonBot = (surface_t*)Z_Malloc(HORIZON_SURF_SIZE);
403 memset(dseg->HorizonTop, 0, HORIZON_SURF_SIZE);
404 memset(dseg->HorizonBot, 0, HORIZON_SURF_SIZE);
405 }
406
407 // Horizon is not supported in sectors with slopes, so just use TexZ.
408 float TopZ = r_region->ceiling->TexZ;
409 float BotZ = r_region->floor->TexZ;
410 float HorizonZ = vieworg.z;
411
412 // Handle top part.
413 if (TopZ > HorizonZ)
414 {
415 sec_surface_t* Ceil = r_subregion->ceil;
416
417 // Calculate light and fade.
418 sec_params_t* LightParams = Ceil->secplane->LightSourceSector != -1 ?
419 &Level->Sectors[Ceil->secplane->LightSourceSector].params :
420 r_region->params;
421 int lLev = FixedLight ? FixedLight :
422 MIN(255, LightParams->lightlevel + ExtraLight);
423 if (r_darken)
424 {
425 lLev = light_remap[lLev];
426 }
427 vuint32 Fade = GetFade(r_region);
428
429 surface_t* Surf = dseg->HorizonTop;
430 Surf->plane = dseg->seg;
431 Surf->texinfo = &Ceil->texinfo;
432 Surf->HorizonPlane = Ceil->secplane;
433 Surf->Light = (lLev << 24) | LightParams->LightColour;
434 Surf->Fade = Fade;
435 Surf->count = 4;
436 Surf->verts[0] = *Seg->v1;
437 Surf->verts[0].z = MAX(BotZ, HorizonZ);
438 Surf->verts[1] = *Seg->v1;
439 Surf->verts[1].z = TopZ;
440 Surf->verts[2] = *Seg->v2;
441 Surf->verts[2].z = TopZ;
442 Surf->verts[3] = *Seg->v2;
443 Surf->verts[3].z = MAX(BotZ, HorizonZ);
444 if (Ceil->secplane->pic == skyflatnum)
445 {
446 // If it's a sky, render it as a regular sky surface.
447 DrawSurfaces(Surf, &Ceil->texinfo, r_region->ceiling->SkyBox, -1,
448 Seg->sidedef->Light, !!(Seg->sidedef->Flags & SDF_ABSLIGHT),
449 false);
450 }
451 else
452 {
453 if (PortalLevel == 0)
454 {
455 world_surf_t& S = WorldSurfs.Alloc();
456 S.Surf = Surf;
457 S.Type = 2;
458 }
459 else
460 {
461 QueueHorizonPortal(Surf);
462 }
463 }
464 }
465
466 // Handle bottom part.
467 if (BotZ < HorizonZ)
468 {
469 sec_surface_t* Floor = r_subregion->floor;
470
471 // Calculate light and fade.
472 sec_params_t* LightParams = Floor->secplane->LightSourceSector != -1 ?
473 &Level->Sectors[Floor->secplane->LightSourceSector].params :
474 r_region->params;
475 int lLev = FixedLight ? FixedLight :
476 MIN(255, LightParams->lightlevel + ExtraLight);
477 if (r_darken)
478 {
479 lLev = light_remap[lLev];
480 }
481 vuint32 Fade = GetFade(r_region);
482
483 surface_t* Surf = dseg->HorizonBot;
484 Surf->plane = dseg->seg;
485 Surf->texinfo = &Floor->texinfo;
486 Surf->HorizonPlane = Floor->secplane;
487 Surf->Light = (lLev << 24) | LightParams->LightColour;
488 Surf->Fade = Fade;
489 Surf->count = 4;
490 Surf->verts[0] = *Seg->v1;
491 Surf->verts[0].z = BotZ;
492 Surf->verts[1] = *Seg->v1;
493 Surf->verts[1].z = MIN(TopZ, HorizonZ);
494 Surf->verts[2] = *Seg->v2;
495 Surf->verts[2].z = MIN(TopZ, HorizonZ);
496 Surf->verts[3] = *Seg->v2;
497 Surf->verts[3].z = BotZ;
498 if (Floor->secplane->pic == skyflatnum)
499 {
500 // If it's a sky, render it as a regular sky surface.
501 DrawSurfaces(Surf, &Floor->texinfo, r_region->floor->SkyBox, -1,
502 Seg->sidedef->Light, !!(Seg->sidedef->Flags & SDF_ABSLIGHT),
503 false);
504 }
505 else
506 {
507 if (PortalLevel == 0)
508 {
509 world_surf_t& S = WorldSurfs.Alloc();
510 S.Surf = Surf;
511 S.Type = 2;
512 }
513 else
514 {
515 QueueHorizonPortal(Surf);
516 }
517 }
518 }
519 unguard;
520 }
521
522 //==========================================================================
523 //
524 // VRenderLevelShared::RenderMirror
525 //
526 //==========================================================================
527
RenderMirror(drawseg_t * dseg)528 void VRenderLevelShared::RenderMirror(drawseg_t* dseg)
529 {
530 guard(VRenderLevelShared::RenderMirror);
531 seg_t* Seg = dseg->seg;
532
533 if (Drawer->HaveStencil && MirrorLevel < r_maxmirrors)
534 {
535 VPortal* Portal = NULL;
536 for (int i = 0; i < Portals.Num(); i++)
537 {
538 if (Portals[i] && Portals[i]->MatchMirror(Seg))
539 {
540 Portal = Portals[i];
541 break;
542 }
543 }
544 if (!Portal)
545 {
546 Portal = new VMirrorPortal(this, Seg);
547 Portals.Append(Portal);
548 }
549
550 surface_t* surfs = dseg->mid->surfs;
551 do
552 {
553 Portal->Surfs.Append(surfs);
554 surfs = surfs->next;
555 } while (surfs);
556 }
557 else
558 {
559 DrawSurfaces(dseg->mid->surfs, &dseg->mid->texinfo,
560 r_region->ceiling->SkyBox, -1, Seg->sidedef->Light,
561 !!(Seg->sidedef->Flags & SDF_ABSLIGHT), false);
562 }
563 unguard;
564 }
565
566 //==========================================================================
567 //
568 // VRenderLevelShared::RenderLine
569 //
570 // Clips the given segment and adds any visible pieces to the line list.
571 //
572 //==========================================================================
573
RenderLine(drawseg_t * dseg)574 void VRenderLevelShared::RenderLine(drawseg_t* dseg)
575 {
576 guard(VRenderLevelShared::RenderLine);
577 seg_t *line = dseg->seg;
578
579 if (!line->linedef)
580 {
581 // Miniseg
582 return;
583 }
584
585 float dist = DotProduct(vieworg, line->normal) - line->dist;
586 if (dist <= 0)
587 {
588 // Viewer is in back side or on plane
589 return;
590 }
591
592 float a1 = ViewClip.PointToClipAngle(*line->v2);
593 float a2 = ViewClip.PointToClipAngle(*line->v1);
594 if (!ViewClip.IsRangeVisible(a1, a2))
595 {
596 return;
597 }
598
599 if (MirrorClipSegs)
600 {
601 // Clip away segs that are behind mirror.
602 float Dist1 = DotProduct(*line->v1, view_clipplanes[4].normal) -
603 view_clipplanes[4].dist;
604 float Dist2 = DotProduct(*line->v2, view_clipplanes[4].normal) -
605 view_clipplanes[4].dist;
606 if (Dist1 <= 0 && Dist2 <= 0)
607 {
608 // Behind mirror.
609 return;
610 }
611 }
612
613 line_t *linedef = line->linedef;
614 side_t *sidedef = line->sidedef;
615
616 //FIXME this marks all lines
617 // mark the segment as visible for auto map
618 linedef->flags |= ML_MAPPED;
619
620 if (!line->backsector)
621 {
622 // single sided line
623 if (line->linedef->special == LNSPEC_LineHorizon)
624 {
625 RenderHorizon(dseg);
626 }
627 else if (line->linedef->special == LNSPEC_LineMirror)
628 {
629 RenderMirror(dseg);
630 }
631 else
632 {
633 DrawSurfaces(dseg->mid->surfs, &dseg->mid->texinfo,
634 r_region->ceiling->SkyBox, -1, sidedef->Light,
635 !!(sidedef->Flags & SDF_ABSLIGHT), false);
636 }
637 DrawSurfaces(dseg->topsky->surfs, &dseg->topsky->texinfo,
638 r_region->ceiling->SkyBox, -1, sidedef->Light,
639 !!(sidedef->Flags & SDF_ABSLIGHT), false);
640 }
641 else
642 {
643 // two sided line
644 DrawSurfaces(dseg->top->surfs, &dseg->top->texinfo,
645 r_region->ceiling->SkyBox, -1, sidedef->Light,
646 !!(sidedef->Flags & SDF_ABSLIGHT), false);
647 DrawSurfaces(dseg->topsky->surfs, &dseg->topsky->texinfo,
648 r_region->ceiling->SkyBox, -1, sidedef->Light,
649 !!(sidedef->Flags & SDF_ABSLIGHT), false);
650 DrawSurfaces(dseg->bot->surfs, &dseg->bot->texinfo,
651 r_region->ceiling->SkyBox, -1, sidedef->Light,
652 !!(sidedef->Flags & SDF_ABSLIGHT), false);
653 DrawSurfaces(dseg->mid->surfs, &dseg->mid->texinfo,
654 r_region->ceiling->SkyBox, -1, sidedef->Light,
655 !!(sidedef->Flags & SDF_ABSLIGHT), false);
656 for (segpart_t *sp = dseg->extra; sp; sp = sp->next)
657 {
658 DrawSurfaces(sp->surfs, &sp->texinfo,r_region->ceiling->SkyBox,
659 -1, sidedef->Light, !!(sidedef->Flags & SDF_ABSLIGHT), false);
660 }
661 }
662 unguard;
663 }
664
665 //==========================================================================
666 //
667 // VRenderLevelShared::RenderSecSurface
668 //
669 //==========================================================================
670
RenderSecSurface(sec_surface_t * ssurf,VEntity * SkyBox)671 void VRenderLevelShared::RenderSecSurface(sec_surface_t* ssurf,
672 VEntity* SkyBox)
673 {
674 guard(VRenderLevelShared::RenderSecSurface);
675 sec_plane_t& plane = *ssurf->secplane;
676
677 if (!plane.pic)
678 {
679 return;
680 }
681
682 float dist = DotProduct(vieworg, plane.normal) - plane.dist;
683 if (dist <= 0)
684 {
685 // Viewer is in back side or on plane
686 return;
687 }
688
689 if (plane.MirrorAlpha < 1.0 && Drawer->HaveStencil &&
690 MirrorLevel < r_maxmirrors)
691 {
692 VPortal* Portal = NULL;
693 for (int i = 0; i < Portals.Num(); i++)
694 {
695 if (Portals[i] && Portals[i]->MatchMirror(&plane))
696 {
697 Portal = Portals[i];
698 break;
699 }
700 }
701 if (!Portal)
702 {
703 Portal = new VMirrorPortal(this, &plane);
704 Portals.Append(Portal);
705 }
706
707 surface_t* surfs = ssurf->surfs;
708 do
709 {
710 Portal->Surfs.Append(surfs);
711 surfs = surfs->next;
712 } while (surfs);
713
714 if (plane.MirrorAlpha <= 0.0)
715 {
716 return;
717 }
718 ssurf->texinfo.Alpha = plane.MirrorAlpha;
719 }
720
721 DrawSurfaces(ssurf->surfs, &ssurf->texinfo, SkyBox,
722 plane.LightSourceSector, 0, false, true);
723 unguard;
724 }
725
726 //==========================================================================
727 //
728 // VRenderLevelShared::RenderSubRegion
729 //
730 // Determine floor/ceiling planes.
731 // Draw one or more line segments.
732 //
733 //==========================================================================
734
RenderSubRegion(subregion_t * region)735 void VRenderLevelShared::RenderSubRegion(subregion_t* region)
736 {
737 guard(VRenderLevelShared::RenderSubRegion);
738 int count;
739 int polyCount;
740 seg_t** polySeg;
741 float d;
742
743 d = DotProduct(vieworg, region->floor->secplane->normal) -
744 region->floor->secplane->dist;
745 if (region->next && d <= 0.0)
746 {
747 RenderSubRegion(region->next);
748 }
749
750 r_subregion = region;
751 r_region = region->secregion;
752
753 if (r_sub->poly)
754 {
755 // Render the polyobj in the subsector first
756 polyCount = r_sub->poly->numsegs;
757 polySeg = r_sub->poly->segs;
758 while (polyCount--)
759 {
760 RenderLine((*polySeg)->drawsegs);
761 polySeg++;
762 }
763 }
764
765 count = r_sub->numlines;
766 drawseg_t *ds = region->lines;
767 while (count--)
768 {
769 RenderLine(ds);
770 ds++;
771 }
772
773 RenderSecSurface(region->floor, r_region->floor->SkyBox);
774 RenderSecSurface(region->ceil, r_region->ceiling->SkyBox);
775
776 if (region->next && d > 0.0)
777 {
778 RenderSubRegion(region->next);
779 }
780 unguard;
781 }
782
783 //==========================================================================
784 //
785 // VRenderLevelShared::RenderSubsector
786 //
787 //==========================================================================
788
RenderSubsector(int num)789 void VRenderLevelShared::RenderSubsector(int num)
790 {
791 guard(VRenderLevelShared::RenderSubsector);
792 subsector_t* Sub = &Level->Subsectors[num];
793 r_sub = Sub;
794
795 if (Sub->VisFrame != r_visframecount)
796 {
797 return;
798 }
799
800 if (!Sub->sector->linecount)
801 {
802 // Skip sectors containing original polyobjs
803 return;
804 }
805
806 if (!ViewClip.ClipCheckSubsector(Sub))
807 {
808 return;
809 }
810
811 BspVis[num >> 3] |= 1 << (num & 7);
812
813 RenderSubRegion(Sub->regions);
814
815 // Add subsector's segs to the clipper. Clipping against mirror
816 // is done only for vertical mirror planes.
817 ViewClip.ClipAddSubsectorSegs(Sub, MirrorClipSegs ? &view_clipplanes[4] :
818 NULL);
819 unguard;
820 }
821
822 //==========================================================================
823 //
824 // VRenderLevelShared::RenderBSPNode
825 //
826 // Renders all subsectors below a given node, traversing subtree
827 // recursively. Just call with BSP root.
828 //
829 //==========================================================================
830
RenderBSPNode(int bspnum,float * bbox,int AClipflags)831 void VRenderLevelShared::RenderBSPNode(int bspnum, float* bbox, int AClipflags)
832 {
833 guard(VRenderLevelShared::RenderBSPNode);
834 if (ViewClip.ClipIsFull())
835 {
836 return;
837 }
838 int clipflags = AClipflags;
839 // cull the clipping planes if not trivial accept
840 if (clipflags)
841 {
842 for (int i = 0; i < 5; i++)
843 {
844 if (!(clipflags & view_clipplanes[i].clipflag))
845 {
846 continue; // don't need to clip against it
847 }
848
849 // generate accept and reject points
850
851 int *pindex = FrustumIndexes[i];
852
853 TVec rejectpt;
854
855 rejectpt[0] = bbox[pindex[0]];
856 rejectpt[1] = bbox[pindex[1]];
857 rejectpt[2] = bbox[pindex[2]];
858
859 float d;
860
861 d = DotProduct(rejectpt, view_clipplanes[i].normal);
862 d -= view_clipplanes[i].dist;
863 if (d <= 0)
864 {
865 return;
866 }
867
868 TVec acceptpt;
869
870 acceptpt[0] = bbox[pindex[3+0]];
871 acceptpt[1] = bbox[pindex[3+1]];
872 acceptpt[2] = bbox[pindex[3+2]];
873
874 d = DotProduct(acceptpt, view_clipplanes[i].normal);
875 d -= view_clipplanes[i].dist;
876
877 if (d >= 0)
878 {
879 clipflags ^= view_clipplanes[i].clipflag; // node is entirely on screen
880 }
881 }
882 }
883
884 if (!ViewClip.ClipIsBBoxVisible(bbox))
885 {
886 return;
887 }
888
889 // Found a subsector?
890 if (bspnum & NF_SUBSECTOR)
891 {
892 if (bspnum == -1)
893 {
894 RenderSubsector(0);
895 }
896 else
897 {
898 RenderSubsector(bspnum & (~NF_SUBSECTOR));
899 }
900 return;
901 }
902
903 node_t* bsp = &Level->Nodes[bspnum];
904
905 if (bsp->VisFrame != r_visframecount)
906 {
907 return;
908 }
909
910 // Decide which side the view point is on.
911 int side = bsp->PointOnSide(vieworg);
912
913 // Recursively divide front space.
914 RenderBSPNode(bsp->children[side], bsp->bbox[side], clipflags);
915
916 // Divide back space.
917 RenderBSPNode(bsp->children[side ^ 1], bsp->bbox[side ^ 1], clipflags);
918 unguard;
919 }
920
921 //==========================================================================
922 //
923 // VRenderLevelShared::RenderBspWorld
924 //
925 //==========================================================================
926
RenderBspWorld(const refdef_t * rd,const VViewClipper * Range)927 void VRenderLevelShared::RenderBspWorld(const refdef_t* rd, const VViewClipper* Range)
928 {
929 guard(VRenderLevelShared::RenderBspWorld);
930 float dummy_bbox[6] = {-99999, -99999, -99999, 99999, 99999, 99999};
931
932 SetUpFrustumIndexes();
933 ViewClip.ClearClipNodes(vieworg, Level);
934 ViewClip.ClipInitFrustrumRange(viewangles, viewforward, viewright, viewup,
935 rd->fovx, rd->fovy);
936 if (Range)
937 {
938 // Range contains a valid range, so we must clip away holes in it.
939 ViewClip.ClipToRanges(*Range);
940 }
941 memset(BspVis, 0, VisSize);
942 if (PortalLevel == 0)
943 {
944 WorldSurfs.Resize(4096);
945 }
946 MirrorClipSegs = MirrorClip && !view_clipplanes[4].normal.z;
947
948 // head node is the last node output
949 RenderBSPNode(Level->NumNodes - 1, dummy_bbox, MirrorClip ? 31 : 15);
950
951 if (PortalLevel == 0)
952 {
953 guard(Best sky);
954 // Draw the most complex sky portal behind the scene first, without
955 // the need to use stencil buffer.
956 VPortal* BestSky = NULL;
957 int BestSkyIndex = -1;
958 for (int i = 0; i < Portals.Num(); i++)
959 {
960 if (Portals[i] && Portals[i]->IsSky() &&
961 (!BestSky || BestSky->Surfs.Num() < Portals[i]->Surfs.Num()))
962 {
963 BestSky = Portals[i];
964 BestSkyIndex = i;
965 }
966 }
967 if (BestSky)
968 {
969 PortalLevel = 1;
970 BestSky->Draw(false);
971 delete BestSky;
972 BestSky = NULL;
973 Portals.RemoveIndex(BestSkyIndex);
974 PortalLevel = 0;
975 }
976 unguard;
977
978 guard(World surfaces);
979 for (int i = 0; i < WorldSurfs.Num(); i++)
980 {
981 switch (WorldSurfs[i].Type)
982 {
983 case 0:
984 QueueWorldSurface(WorldSurfs[i].Surf);
985 break;
986 case 1:
987 QueueSkyPortal(WorldSurfs[i].Surf);
988 break;
989 case 2:
990 QueueHorizonPortal(WorldSurfs[i].Surf);
991 break;
992 }
993 }
994 WorldSurfs.Clear();
995 unguard;
996 }
997 unguard;
998 }
999
1000 //==========================================================================
1001 //
1002 // VRenderLevelShared::RenderPortals
1003 //
1004 //==========================================================================
1005
RenderPortals()1006 void VRenderLevelShared::RenderPortals()
1007 {
1008 guard(VRenderLevelShared::RenderPortals);
1009 PortalLevel++;
1010 if (Drawer->HaveStencil)
1011 {
1012 for (int i = 0; i < Portals.Num(); i++)
1013 {
1014 if (Portals[i] && Portals[i]->Level == PortalLevel)
1015 {
1016 Portals[i]->Draw(true);
1017 }
1018 }
1019 }
1020 for (int i = 0; i < Portals.Num(); i++)
1021 {
1022 if (Portals[i] && Portals[i]->Level == PortalLevel)
1023 {
1024 delete Portals[i];
1025 Portals[i] = NULL;
1026 }
1027 }
1028 PortalLevel--;
1029 if (PortalLevel == 0)
1030 {
1031 Portals.Clear();
1032 }
1033 unguard;
1034 }
1035
1036 //==========================================================================
1037 //
1038 // VRenderLevel::RenderWorld
1039 //
1040 //==========================================================================
1041
RenderWorld(const refdef_t * rd,const VViewClipper * Range)1042 void VRenderLevel::RenderWorld(const refdef_t* rd, const VViewClipper* Range)
1043 {
1044 guard(VRenderLevel::RenderWorld);
1045 RenderBspWorld(rd, Range);
1046
1047 Drawer->WorldDrawing();
1048
1049 RenderPortals();
1050 unguard;
1051 }
1052
1053 //==========================================================================
1054 //
1055 // VAdvancedRenderLevel::RenderWorld
1056 //
1057 //==========================================================================
1058
RenderWorld(const refdef_t * rd,const VViewClipper * Range)1059 void VAdvancedRenderLevel::RenderWorld(const refdef_t* rd, const VViewClipper* Range)
1060 {
1061 guard(VAdvancedRenderLevel::RenderWorld);
1062 RenderBspWorld(rd, Range);
1063
1064 Drawer->DrawWorldAmbientPass();
1065
1066 RenderPortals();
1067 unguard;
1068 }
1069