1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: r_surf.cpp 4340 2010-12-15 21:48:23Z 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 // HEADER FILES ------------------------------------------------------------
27
28 #include "gamedefs.h"
29 #include "r_local.h"
30
31 // MACROS ------------------------------------------------------------------
32
33 #define MAXSPLITVERTS 128
34 #define ON_EPSILON 0.1
35 #define subdivide_size 240
36
37 #define MAXWVERTS 8
38 #define WSURFSIZE (sizeof(surface_t) + sizeof(TVec) * (MAXWVERTS - 1))
39
40 // This is used to compare floats like ints which is faster
41 #define FASI(var) (*(int*)&var)
42
43 // TYPES -------------------------------------------------------------------
44
45 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
46
47 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
48
49 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
50
51 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
52
53 extern int light_mem;
54
55 // PUBLIC DATA DEFINITIONS -------------------------------------------------
56
57 // PRIVATE DATA DEFINITIONS ------------------------------------------------
58
59 static subsector_t* r_sub;
60 static sec_plane_t* r_floor;
61 static sec_plane_t* r_ceiling;
62
63 static segpart_t* pspart;
64
65 // CODE --------------------------------------------------------------------
66
67 //**************************************************************************
68 //
69 // Scaling
70 //
71 //**************************************************************************
72
73 //==========================================================================
74 //
75 // TextureSScale
76 //
77 //==========================================================================
78
TextureSScale(VTexture * pic)79 inline float TextureSScale(VTexture* pic)
80 {
81 return pic->SScale;
82 }
83
84 //==========================================================================
85 //
86 // TextureTScale
87 //
88 //==========================================================================
89
TextureTScale(VTexture * pic)90 inline float TextureTScale(VTexture* pic)
91 {
92 return pic->TScale;
93 }
94
95 //==========================================================================
96 //
97 // TextureOffsetSScale
98 //
99 //==========================================================================
100
TextureOffsetSScale(VTexture * pic)101 inline float TextureOffsetSScale(VTexture* pic)
102 {
103 if (pic->bWorldPanning)
104 return pic->SScale;
105 return 1.0;
106 }
107
108 //==========================================================================
109 //
110 // TextureOffsetTScale
111 //
112 //==========================================================================
113
TextureOffsetTScale(VTexture * pic)114 inline float TextureOffsetTScale(VTexture* pic)
115 {
116 if (pic->bWorldPanning)
117 return pic->TScale;
118 return 1.0;
119 }
120
121 //==========================================================================
122 //
123 // IsSky
124 //
125 //==========================================================================
126
IsSky(sec_plane_t * SPlane)127 inline bool IsSky(sec_plane_t* SPlane)
128 {
129 return SPlane->pic == skyflatnum || (SPlane->SkyBox &&
130 SPlane->SkyBox->eventSkyBoxGetAlways());
131 }
132
133 //**************************************************************************
134 //**
135 //** Sector surfaces
136 //**
137 //**************************************************************************
138
139 //==========================================================================
140 //
141 // VRenderLevelShared::SetupSky
142 //
143 //==========================================================================
144
SetupSky()145 void VRenderLevelShared::SetupSky()
146 {
147 guard(VRenderLevelShared::SetupSky);
148 skyheight = -99999.0;
149 for (int i = 0; i < Level->NumSectors; i++)
150 {
151 if (Level->Sectors[i].ceiling.pic == skyflatnum &&
152 Level->Sectors[i].ceiling.maxz > skyheight)
153 {
154 skyheight = Level->Sectors[i].ceiling.maxz;
155 }
156 }
157 // Make it a bit higher to avoid clipping of the sprites.
158 skyheight += 8 * 1024;
159 memset(&sky_plane, 0, sizeof(sky_plane));
160 sky_plane.Set(TVec(0, 0, -1), -skyheight);
161 sky_plane.pic = skyflatnum;
162 sky_plane.Alpha = 1.1;
163 sky_plane.LightSourceSector = -1;
164 sky_plane.MirrorAlpha = 1.0;
165 sky_plane.XScale = 1.0;
166 sky_plane.YScale = 1.0;
167 unguard;
168 }
169
170 //==========================================================================
171 //
172 // VRenderLevel::InitSurfs
173 //
174 //==========================================================================
175
InitSurfs(surface_t * ASurfs,texinfo_t * texinfo,TPlane * plane,subsector_t * sub)176 void VRenderLevel::InitSurfs(surface_t* ASurfs, texinfo_t *texinfo,
177 TPlane *plane, subsector_t* sub)
178 {
179 guard(VRenderLevel::InitSurfs);
180 surface_t* surfs = ASurfs;
181 int i;
182 float dot;
183 float mins;
184 float maxs;
185 int bmins;
186 int bmaxs;
187
188 while (surfs)
189 {
190 if (plane)
191 {
192 surfs->texinfo = texinfo;
193 surfs->plane = plane;
194 }
195
196 mins = 99999.0;
197 maxs = -99999.0;
198 for (i = 0; i < surfs->count; i++)
199 {
200 dot = DotProduct(surfs->verts[i], texinfo->saxis) + texinfo->soffs;
201 if (dot < mins)
202 mins = dot;
203 if (dot > maxs)
204 maxs = dot;
205 }
206 bmins = (int)floor(mins / 16);
207 bmaxs = (int)ceil(maxs / 16);
208 surfs->texturemins[0] = bmins * 16;
209 surfs->extents[0] = (bmaxs - bmins) * 16;
210 if (surfs->extents[0] > 256)
211 {
212 Sys_Error("Bad extents");
213 }
214
215 mins = 99999.0;
216 maxs = -99999.0;
217 for (i = 0; i < surfs->count; i++)
218 {
219 dot = DotProduct(surfs->verts[i], texinfo->taxis) + texinfo->toffs;
220 if (dot < mins)
221 mins = dot;
222 if (dot > maxs)
223 maxs = dot;
224 }
225 bmins = (int)floor(mins / 16);
226 bmaxs = (int)ceil(maxs / 16);
227 surfs->texturemins[1] = bmins * 16;
228 surfs->extents[1] = (bmaxs - bmins) * 16;
229 if (surfs->extents[1] > 256)
230 {
231 Sys_Error("Bad extents");
232 }
233
234 LightFace(surfs, sub);
235
236 surfs = surfs->next;
237 }
238 unguard;
239 }
240
241 //==========================================================================
242 //
243 // VAdvancedRenderLevel::InitSurfs
244 //
245 //==========================================================================
246
InitSurfs(surface_t * surfs,texinfo_t * texinfo,TPlane * plane,subsector_t *)247 void VAdvancedRenderLevel::InitSurfs(surface_t* surfs, texinfo_t *texinfo,
248 TPlane *plane, subsector_t*)
249 {
250 guard(VAdvancedRenderLevel::InitSurfs);
251 // It's always one surface.
252 if (surfs && plane)
253 {
254 surfs->texinfo = texinfo;
255 surfs->plane = plane;
256 }
257 unguard;
258 }
259
260 //==========================================================================
261 //
262 // VRenderLevelShared::FlushSurfCaches
263 //
264 //==========================================================================
265
FlushSurfCaches(surface_t * InSurfs)266 void VRenderLevelShared::FlushSurfCaches(surface_t* InSurfs)
267 {
268 guard(VRenderLevelShared::FlushSurfCaches);
269 surface_t* surfs = InSurfs;
270 while (surfs)
271 {
272 if (surfs->CacheSurf)
273 {
274 FreeSurfCache(surfs->CacheSurf);
275 }
276 surfs = surfs->next;
277 }
278 unguard;
279 }
280
281 //==========================================================================
282 //
283 // VRenderLevel::SubdivideFace
284 //
285 //==========================================================================
286
SubdivideFace(surface_t * InF,const TVec & axis,const TVec * nextaxis)287 surface_t* VRenderLevel::SubdivideFace(surface_t* InF, const TVec &axis,
288 const TVec *nextaxis)
289 {
290 guard(VRenderLevel::SubdivideFace);
291 surface_t* f = InF;
292 int i;
293 float dot;
294 float mins = 99999.0;
295 float maxs = -99999.0;
296
297 for (i = 0; i < f->count; i++)
298 {
299 dot = DotProduct(f->verts[i], axis);
300 if (dot < mins)
301 mins = dot;
302 if (dot > maxs)
303 maxs = dot;
304 }
305
306 if (maxs - mins <= subdivide_size)
307 {
308 if (nextaxis)
309 {
310 f = SubdivideFace(f, *nextaxis, NULL);
311 }
312 return f;
313 }
314
315 c_subdivides++;
316
317 if (f->count > MAXSPLITVERTS)
318 {
319 Host_Error("f->count > MAXSPLITVERTS\n");
320 }
321
322 TPlane plane;
323
324 plane.normal = axis;
325 dot = Length(plane.normal);
326 plane.normal = Normalise(plane.normal);
327 plane.dist = (mins + subdivide_size - 16) / dot;
328
329 float dots[MAXSPLITVERTS + 1];
330 int sides[MAXSPLITVERTS + 1];
331
332 for (i = 0; i < f->count; i++)
333 {
334 dot = DotProduct(f->verts[i], plane.normal) - plane.dist;
335 dots[i] = dot;
336 if (dot < -ON_EPSILON)
337 sides[i] = -1;
338 else if (dot > ON_EPSILON)
339 sides[i] = 1;
340 else
341 sides[i] = 0;
342 }
343 dots[f->count] = dots[0];
344 sides[f->count] = sides[0];
345
346 TVec verts1[MAXSPLITVERTS];
347 TVec verts2[MAXSPLITVERTS];
348 int count1 = 0;
349 int count2 = 0;
350
351 for (i = 0; i < f->count; i++)
352 {
353 if (sides[i] == 0)
354 {
355 verts1[count1++] = f->verts[i];
356 verts2[count2++] = f->verts[i];
357 continue;
358 }
359 if (sides[i] == 1)
360 {
361 verts1[count1++] = f->verts[i];
362 }
363 else
364 {
365 verts2[count2++] = f->verts[i];
366 }
367 if (sides[i + 1] == 0 || sides[i] == sides[i + 1])
368 {
369 continue;
370 }
371
372 // generate a split point
373 TVec mid;
374 TVec &p1 = f->verts[i];
375 TVec &p2 = f->verts[(i + 1) % f->count];
376
377 dot = dots[i] / (dots[i] - dots[i + 1]);
378 for (int j = 0; j < 3; j++)
379 {
380 // avoid round off error when possible
381 if (plane.normal[j] == 1)
382 mid[j] = plane.dist;
383 else if (plane.normal[j] == -1)
384 mid[j] = -plane.dist;
385 else
386 mid[j] = p1[j] + dot * (p2[j] - p1[j]);
387 }
388
389 verts1[count1++] = mid;
390 verts2[count2++] = mid;
391 }
392
393 surface_t *next = f->next;
394 Z_Free(f);
395
396 surface_t *back = (surface_t*)Z_Calloc(sizeof(surface_t) +
397 (count2 - 1) * sizeof(TVec));
398 back->count = count2;
399 memcpy(back->verts, verts2, count2 * sizeof(TVec));
400
401 surface_t *front = (surface_t*)Z_Calloc(sizeof(surface_t) +
402 (count1 - 1) * sizeof(TVec));
403 front->count = count1;
404 memcpy(front->verts, verts1, count1 * sizeof(TVec));
405
406 front->next = next;
407 back->next = SubdivideFace(front, axis, nextaxis);
408 if (nextaxis)
409 {
410 back = SubdivideFace(back, *nextaxis, NULL);
411 }
412 return back;
413 unguard;
414 }
415
416 //==========================================================================
417 //
418 // VAdvancedRenderLevel::SubdivideFace
419 //
420 //==========================================================================
421
SubdivideFace(surface_t * f,const TVec &,const TVec *)422 surface_t* VAdvancedRenderLevel::SubdivideFace(surface_t* f, const TVec&,
423 const TVec*)
424 {
425 // Advanced renderer can draw whole surface.
426 return f;
427 }
428
429 //==========================================================================
430 //
431 // VRenderLevelShared::CreateSecSurface
432 //
433 //==========================================================================
434
CreateSecSurface(subsector_t * sub,sec_plane_t * InSplane)435 sec_surface_t* VRenderLevelShared::CreateSecSurface(subsector_t* sub,
436 sec_plane_t* InSplane)
437 {
438 guard(VRenderLevelShared::CreateSecSurface);
439 sec_plane_t* splane = InSplane;
440 sec_surface_t *ssurf;
441 surface_t *surf;
442
443 ssurf = new sec_surface_t;
444 memset(ssurf, 0, sizeof(sec_surface_t));
445 surf = (surface_t*)Z_Calloc(sizeof(surface_t) +
446 (sub->numlines - 1) * sizeof(TVec));
447
448 if (splane->pic == skyflatnum && splane->normal.z < 0.0)
449 {
450 splane = &sky_plane;
451 }
452 ssurf->secplane = splane;
453 ssurf->dist = splane->dist;
454
455 VTexture* Tex = GTextureManager(splane->pic);
456 if (fabs(splane->normal.z) > 0.1)
457 {
458 ssurf->texinfo.saxis = TVec(mcos(splane->BaseAngle - splane->Angle),
459 msin(splane->BaseAngle - splane->Angle), 0) * TextureSScale(Tex) *
460 splane->XScale;
461 ssurf->texinfo.taxis = TVec(msin(splane->BaseAngle - splane->Angle),
462 -mcos(splane->BaseAngle - splane->Angle), 0) * TextureTScale(Tex) *
463 splane->YScale;
464 }
465 else
466 {
467 ssurf->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(Tex) *
468 splane->YScale;
469 ssurf->texinfo.saxis = Normalise(CrossProduct(splane->normal,
470 ssurf->texinfo.taxis)) * TextureSScale(Tex) * splane->XScale;
471 }
472 ssurf->texinfo.soffs = splane->xoffs;
473 ssurf->texinfo.toffs = splane->yoffs + splane->BaseYOffs;
474 ssurf->texinfo.Tex = Tex;
475 ssurf->texinfo.Alpha = splane->Alpha < 1.0 ? splane->Alpha : 1.1;
476 ssurf->texinfo.Additive = !!(splane->flags & SPF_ADDITIVE);
477 ssurf->texinfo.ColourMap = 0;
478 ssurf->XScale = splane->XScale;
479 ssurf->YScale = splane->YScale;
480 ssurf->Angle = splane->BaseAngle - splane->Angle;
481
482 surf->count = sub->numlines;
483 seg_t *line = &Level->Segs[sub->firstline];
484 int vlindex = (splane->normal.z < 0);
485 for (int i = 0; i < surf->count; i++)
486 {
487 TVec &v = *line[vlindex ? surf->count - i - 1 : i].v1;
488 TVec &dst = surf->verts[i];
489 dst = v;
490 dst.z = splane->GetPointZ(dst);
491 }
492
493 if (splane->pic == skyflatnum)
494 {
495 // Don't subdivide sky
496 ssurf->surfs = surf;
497 surf->texinfo = &ssurf->texinfo;
498 surf->plane = splane;
499 }
500 else
501 {
502 ssurf->surfs = SubdivideFace(surf, ssurf->texinfo.saxis,
503 &ssurf->texinfo.taxis);
504 InitSurfs(ssurf->surfs, &ssurf->texinfo, splane, sub);
505 }
506
507 return ssurf;
508 unguard;
509 }
510
511 //==========================================================================
512 //
513 // VRenderLevelShared::UpdateSecSurface
514 //
515 //==========================================================================
516
UpdateSecSurface(sec_surface_t * ssurf,sec_plane_t * RealPlane,subsector_t * sub)517 void VRenderLevelShared::UpdateSecSurface(sec_surface_t *ssurf,
518 sec_plane_t* RealPlane, subsector_t* sub)
519 {
520 guard(VRenderLevelShared::UpdateSecSurface);
521 sec_plane_t *plane = ssurf->secplane;
522
523 if (!plane->pic)
524 {
525 return;
526 }
527
528 if (plane != RealPlane)
529 {
530 // Check for sky changes.
531 if (plane->pic == skyflatnum && RealPlane->pic != skyflatnum)
532 {
533 ssurf->secplane = RealPlane;
534 plane = RealPlane;
535 if (!ssurf->surfs->extents[0])
536 {
537 ssurf->surfs = SubdivideFace(ssurf->surfs,
538 ssurf->texinfo.saxis, &ssurf->texinfo.taxis);
539 InitSurfs(ssurf->surfs, &ssurf->texinfo, plane, sub);
540 }
541 }
542 else if (plane->pic != skyflatnum && RealPlane->pic == skyflatnum)
543 {
544 ssurf->secplane = &sky_plane;
545 plane = &sky_plane;
546 }
547 }
548
549 ssurf->texinfo.ColourMap = ColourMap;
550 if (ssurf->texinfo.Tex != GTextureManager(plane->pic))
551 {
552 ssurf->texinfo.Tex = GTextureManager(plane->pic);
553 }
554 if (FASI(ssurf->dist) != FASI(plane->dist))
555 {
556 ssurf->dist = plane->dist;
557 for (surface_t *surf = ssurf->surfs; surf; surf = surf->next)
558 {
559 for (int i = 0; i < surf->count; i++)
560 {
561 surf->verts[i].z = plane->GetPointZ(surf->verts[i]);
562 }
563 }
564 if (plane->pic != skyflatnum)
565 {
566 FlushSurfCaches(ssurf->surfs);
567 InitSurfs(ssurf->surfs, &ssurf->texinfo, NULL, sub);
568 }
569 }
570 if (FASI(ssurf->XScale) != FASI(plane->XScale) ||
571 FASI(ssurf->YScale) != FASI(plane->YScale) ||
572 ssurf->Angle != plane->BaseAngle - plane->Angle)
573 {
574 if (fabs(plane->normal.z) > 0.1)
575 {
576 ssurf->texinfo.saxis = TVec(mcos(plane->BaseAngle - plane->Angle),
577 msin(plane->BaseAngle - plane->Angle), 0) *
578 TextureSScale(ssurf->texinfo.Tex) * plane->XScale;
579 ssurf->texinfo.taxis = TVec(msin(plane->BaseAngle - plane->Angle),
580 -mcos(plane->BaseAngle - plane->Angle), 0) *
581 TextureTScale(ssurf->texinfo.Tex) * plane->YScale;
582 }
583 else
584 {
585 ssurf->texinfo.taxis = TVec(0, 0, -1) *
586 TextureTScale(ssurf->texinfo.Tex) * plane->YScale;
587 ssurf->texinfo.saxis = Normalise(CrossProduct(plane->normal,
588 ssurf->texinfo.taxis)) * TextureSScale(ssurf->texinfo.Tex) *
589 plane->XScale;
590 }
591 ssurf->texinfo.soffs = plane->xoffs;
592 ssurf->texinfo.toffs = plane->yoffs + plane->BaseYOffs;
593 ssurf->XScale = plane->XScale;
594 ssurf->YScale = plane->YScale;
595 ssurf->Angle = plane->BaseAngle - plane->Angle;
596 if (plane->pic != skyflatnum)
597 {
598 FreeSurfaces(ssurf->surfs);
599 surface_t* surf = (surface_t*)Z_Calloc(sizeof(surface_t) +
600 (sub->numlines - 1) * sizeof(TVec));
601 surf->count = sub->numlines;
602 seg_t* line = &Level->Segs[sub->firstline];
603 int vlindex = (plane->normal.z < 0);
604 for (int i = 0; i < surf->count; i++)
605 {
606 TVec &v = *line[vlindex ? surf->count - i - 1 : i].v1;
607 TVec &dst = surf->verts[i];
608 dst = v;
609 dst.z = plane->GetPointZ(dst);
610 }
611 ssurf->surfs = SubdivideFace(surf, ssurf->texinfo.saxis,
612 &ssurf->texinfo.taxis);
613 InitSurfs(ssurf->surfs, &ssurf->texinfo, plane, sub);
614 }
615 }
616 else if (FASI(ssurf->texinfo.soffs) != FASI(plane->xoffs) ||
617 ssurf->texinfo.toffs != plane->yoffs + plane->BaseYOffs)
618 {
619 ssurf->texinfo.soffs = plane->xoffs;
620 ssurf->texinfo.toffs = plane->yoffs + plane->BaseYOffs;
621 if (plane->pic != skyflatnum)
622 {
623 FlushSurfCaches(ssurf->surfs);
624 InitSurfs(ssurf->surfs, &ssurf->texinfo, NULL, sub);
625 }
626 }
627 unguard;
628 }
629
630 //**************************************************************************
631 //**
632 //** Seg surfaces
633 //**
634 //**************************************************************************
635
636 //==========================================================================
637 //
638 // VRenderLevelShared::NewWSurf
639 //
640 //==========================================================================
641
NewWSurf()642 surface_t* VRenderLevelShared::NewWSurf()
643 {
644 guard(VRenderLevelShared::NewWSurf);
645 if (!free_wsurfs)
646 {
647 // Allocate some more surfs
648 byte* tmp = (byte*)Z_Malloc(WSURFSIZE * 32 + sizeof(void*));
649 *(void**)tmp = AllocatedWSurfBlocks;
650 AllocatedWSurfBlocks = tmp;
651 tmp += sizeof(void*);
652 for (int i = 0; i < 32; i++)
653 {
654 ((surface_t*)tmp)->next = free_wsurfs;
655 free_wsurfs = (surface_t*)tmp;
656 tmp += WSURFSIZE;
657 }
658 }
659 surface_t *surf = free_wsurfs;
660 free_wsurfs = surf->next;
661
662 memset(surf, 0, WSURFSIZE);
663
664 return surf;
665 unguard;
666 }
667
668 //==========================================================================
669 //
670 // VRenderLevelShared::FreeWSurfs
671 //
672 //==========================================================================
673
FreeWSurfs(surface_t * InSurfs)674 void VRenderLevelShared::FreeWSurfs(surface_t* InSurfs)
675 {
676 guard(VRenderLevelShared::FreeWSurfs);
677 surface_t* surfs = InSurfs;
678 FlushSurfCaches(surfs);
679 while (surfs)
680 {
681 if (surfs->lightmap)
682 {
683 Z_Free(surfs->lightmap);
684 }
685 if (surfs->lightmap_rgb)
686 {
687 Z_Free(surfs->lightmap_rgb);
688 }
689 surface_t *next = surfs->next;
690 surfs->next = free_wsurfs;
691 free_wsurfs = surfs;
692 surfs = next;
693 }
694 unguard;
695 }
696
697 //==========================================================================
698 //
699 // VRenderLevel::SubdivideSeg
700 //
701 //==========================================================================
702
SubdivideSeg(surface_t * InSurf,const TVec & axis,const TVec * nextaxis)703 surface_t* VRenderLevel::SubdivideSeg(surface_t* InSurf,
704 const TVec &axis, const TVec *nextaxis)
705 {
706 guard(VRenderLevel::SubdivideSeg);
707 surface_t* surf = InSurf;
708 int i;
709 float dot;
710 float mins = 99999.0;
711 float maxs = -99999.0;
712
713 for (i = 0; i < surf->count; i++)
714 {
715 dot = DotProduct(surf->verts[i], axis);
716 if (dot < mins)
717 mins = dot;
718 if (dot > maxs)
719 maxs = dot;
720 }
721
722 if (maxs - mins <= subdivide_size)
723 {
724 if (nextaxis)
725 {
726 surf = SubdivideSeg(surf, *nextaxis, NULL);
727 }
728 return surf;
729 }
730
731 c_seg_div++;
732
733 TPlane plane;
734
735 plane.normal = axis;
736 dot = Length(plane.normal);
737 plane.normal = Normalise(plane.normal);
738 plane.dist = (mins + subdivide_size - 16) / dot;
739
740 float dots[MAXWVERTS + 1];
741 int sides[MAXWVERTS + 1];
742
743 for (i = 0; i < surf->count; i++)
744 {
745 dot = DotProduct(surf->verts[i], plane.normal) - plane.dist;
746 dots[i] = dot;
747 if (dot < -ON_EPSILON)
748 sides[i] = -1;
749 else if (dot > ON_EPSILON)
750 sides[i] = 1;
751 else
752 sides[i] = 0;
753 }
754 dots[surf->count] = dots[0];
755 sides[surf->count] = sides[0];
756
757 TVec verts1[MAXWVERTS];
758 TVec verts2[MAXWVERTS];
759 int count1 = 0;
760 int count2 = 0;
761
762 for (i = 0; i < surf->count; i++)
763 {
764 if (sides[i] == 0)
765 {
766 verts1[count1++] = surf->verts[i];
767 verts2[count2++] = surf->verts[i];
768 continue;
769 }
770 if (sides[i] == 1)
771 {
772 verts1[count1++] = surf->verts[i];
773 }
774 else
775 {
776 verts2[count2++] = surf->verts[i];
777 }
778 if (sides[i + 1] == 0 || sides[i] == sides[i + 1])
779 {
780 continue;
781 }
782
783 // generate a split point
784 TVec mid;
785 TVec &p1 = surf->verts[i];
786 TVec &p2 = surf->verts[(i + 1) % surf->count];
787
788 dot = dots[i] / (dots[i] - dots[i + 1]);
789 for (int j = 0; j < 3; j++)
790 {
791 // avoid round off error when possible
792 if (plane.normal[j] == 1)
793 mid[j] = plane.dist;
794 else if (plane.normal[j] == -1)
795 mid[j] = -plane.dist;
796 else
797 mid[j] = p1[j] + dot * (p2[j] - p1[j]);
798 }
799
800 verts1[count1++] = mid;
801 verts2[count2++] = mid;
802 }
803
804 surf->count = count2;
805 memcpy(surf->verts, verts2, count2 * sizeof(TVec));
806
807 surface_t *news = NewWSurf();
808 news->count = count1;
809 memcpy(news->verts, verts1, count1 * sizeof(TVec));
810
811 news->next = surf->next;
812 surf->next = SubdivideSeg(news, axis, nextaxis);
813 if (nextaxis)
814 {
815 surf = SubdivideSeg(surf, *nextaxis, NULL);
816 }
817 return surf;
818 unguard;
819 }
820
821 //==========================================================================
822 //
823 // VAdvancedRenderLevel::SubdivideSeg
824 //
825 //==========================================================================
826
SubdivideSeg(surface_t * surf,const TVec &,const TVec *)827 surface_t* VAdvancedRenderLevel::SubdivideSeg(surface_t* surf, const TVec&,
828 const TVec*)
829 {
830 // Advanced renderer can draw whole surface.
831 return surf;
832 }
833
834 //==========================================================================
835 //
836 // VRenderLevelShared::CreateWSurfs
837 //
838 //==========================================================================
839
CreateWSurfs(TVec * wv,texinfo_t * texinfo,seg_t * seg,subsector_t * sub)840 surface_t* VRenderLevelShared::CreateWSurfs(TVec* wv, texinfo_t* texinfo,
841 seg_t* seg, subsector_t* sub)
842 {
843 guard(VRenderLevelShared::CreateWSurfs);
844 if (wv[1].z <= wv[0].z && wv[2].z <= wv[3].z)
845 {
846 return NULL;
847 }
848
849 if (texinfo->Tex->Type == TEXTYPE_Null)
850 {
851 return NULL;
852 }
853
854 surface_t *surf = NewWSurf();
855 surf->next = NULL;
856 surf->count = 4;
857 memcpy(surf->verts, wv, 4 * sizeof(TVec));
858
859 if (texinfo->Tex == GTextureManager[skyflatnum])
860 {
861 // Never split sky surfaces
862 surf->texinfo = texinfo;
863 surf->plane = seg;
864 return surf;
865 }
866
867 surf = SubdivideSeg(surf, texinfo->saxis, &texinfo->taxis);
868 InitSurfs(surf, texinfo, seg, sub);
869 return surf;
870 unguard;
871 }
872
873 //==========================================================================
874 //
875 // VRenderLevelShared::CountSegParts
876 //
877 //==========================================================================
878
CountSegParts(seg_t * seg)879 int VRenderLevelShared::CountSegParts(seg_t* seg)
880 {
881 guard(VRenderLevelShared::CountSegParts);
882 if (!seg->linedef)
883 {
884 // Miniseg
885 return 0;
886 }
887 int count;
888 if (!seg->backsector)
889 {
890 count = 2;
891 }
892 else
893 {
894 count = 4;
895 for (sec_region_t *reg = seg->backsector->topregion;
896 reg->prev; reg = reg->prev)
897 {
898 count++;
899 }
900 }
901 return count;
902 unguard;
903 }
904
905 //==========================================================================
906 //
907 // VRenderLevelShared::CreateSegParts
908 //
909 //==========================================================================
910
CreateSegParts(drawseg_t * dseg,seg_t * seg)911 void VRenderLevelShared::CreateSegParts(drawseg_t* dseg, seg_t *seg)
912 {
913 guard(VRenderLevelShared::CreateSegParts);
914 TVec wv[4];
915 segpart_t *sp;
916
917 dseg->seg = seg;
918 dseg->next = seg->drawsegs;
919 seg->drawsegs = dseg;
920
921 if (!seg->linedef)
922 {
923 // Miniseg
924 return;
925 }
926
927 side_t *sidedef = seg->sidedef;
928 line_t *linedef = seg->linedef;
929
930 TVec segdir = (*seg->v2 - *seg->v1) / seg->length;
931
932 float topz1 = r_ceiling->GetPointZ(*seg->v1);
933 float topz2 = r_ceiling->GetPointZ(*seg->v2);
934 float botz1 = r_floor->GetPointZ(*seg->v1);
935 float botz2 = r_floor->GetPointZ(*seg->v2);
936
937 if (!seg->backsector)
938 {
939 dseg->mid = pspart++;
940 sp = dseg->mid;
941
942 VTexture* MTex = GTextureManager(sidedef->MidTexture);
943 sp->texinfo.saxis = segdir * TextureSScale(MTex);
944 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(MTex);
945 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
946 seg->offset * TextureSScale(MTex) +
947 sidedef->MidTextureOffset * TextureOffsetSScale(MTex);
948 sp->texinfo.Tex = MTex;
949 sp->texinfo.Alpha = 1.1;
950 sp->texinfo.Additive = false;
951 sp->texinfo.ColourMap = 0;
952
953 if (linedef->flags & ML_DONTPEGBOTTOM)
954 {
955 // bottom of texture at bottom
956 sp->texinfo.toffs = r_floor->TexZ + MTex->GetScaledHeight();
957 }
958 else if (linedef->flags & ML_DONTPEGTOP)
959 {
960 // top of texture at top of top region
961 sp->texinfo.toffs =
962 r_sub->sector->topregion->ceiling->TexZ;
963 }
964 else
965 {
966 // top of texture at top
967 sp->texinfo.toffs = r_ceiling->TexZ;
968 }
969 sp->texinfo.toffs *= TextureTScale(MTex);
970 sp->texinfo.toffs += sidedef->MidRowOffset * TextureOffsetTScale(MTex);
971
972 wv[0].x = wv[1].x = seg->v1->x;
973 wv[0].y = wv[1].y = seg->v1->y;
974 wv[2].x = wv[3].x = seg->v2->x;
975 wv[2].y = wv[3].y = seg->v2->y;
976
977 wv[0].z = botz1;
978 wv[1].z = topz1;
979 wv[2].z = topz2;
980 wv[3].z = botz2;
981
982 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
983
984 sp->frontTopDist = r_ceiling->dist;
985 sp->frontBotDist = r_floor->dist;
986 sp->TextureOffset = sidedef->MidTextureOffset;
987 sp->RowOffset = sidedef->MidRowOffset;
988
989 // Sky above line.
990 dseg->topsky = pspart++;
991 sp = dseg->topsky;
992 sp->texinfo.Tex = GTextureManager[skyflatnum];
993 sp->texinfo.Alpha = 1.1;
994 sp->texinfo.Additive = false;
995 sp->texinfo.ColourMap = 0;
996 if (IsSky(r_ceiling))
997 {
998 wv[0].x = wv[1].x = seg->v1->x;
999 wv[0].y = wv[1].y = seg->v1->y;
1000 wv[2].x = wv[3].x = seg->v2->x;
1001 wv[2].y = wv[3].y = seg->v2->y;
1002
1003 wv[0].z = topz1;
1004 wv[1].z = wv[2].z = skyheight;
1005 wv[3].z = topz2;
1006
1007 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1008
1009 sp->frontTopDist = r_ceiling->dist;
1010 }
1011 }
1012 else
1013 {
1014 // two sided line
1015
1016 sec_plane_t* back_floor = &seg->backsector->floor;
1017 sec_plane_t* back_ceiling = &seg->backsector->ceiling;
1018 if (seg->backsector->fakefloors)
1019 {
1020 if (back_floor == &seg->backsector->floor)
1021 {
1022 back_floor = &seg->backsector->fakefloors->floorplane;
1023 }
1024 if (back_ceiling == &seg->backsector->ceiling)
1025 {
1026 back_ceiling = &seg->backsector->fakefloors->ceilplane;
1027 }
1028 }
1029
1030 VTexture* TTex = GTextureManager(sidedef->TopTexture);
1031
1032 float back_topz1 = back_ceiling->GetPointZ(*seg->v1);
1033 float back_topz2 = back_ceiling->GetPointZ(*seg->v2);
1034 float back_botz1 = back_floor->GetPointZ(*seg->v1);
1035 float back_botz2 = back_floor->GetPointZ(*seg->v2);
1036
1037 // hack to allow height changes in outdoor areas
1038 float top_topz1 = topz1;
1039 float top_topz2 = topz2;
1040 float top_TexZ = r_ceiling->TexZ;
1041 if (IsSky(r_ceiling) && IsSky(back_ceiling))
1042 {
1043 if (r_ceiling->SkyBox == back_ceiling->SkyBox)
1044 {
1045 top_topz1 = back_topz1;
1046 top_topz2 = back_topz2;
1047 top_TexZ = back_ceiling->TexZ;
1048 }
1049 else
1050 {
1051 TTex = GTextureManager[skyflatnum];
1052 }
1053 }
1054
1055 // top wall
1056 dseg->top = pspart++;
1057 sp = dseg->top;
1058
1059 sp->texinfo.saxis = segdir * TextureSScale(TTex);
1060 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(TTex);
1061 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
1062 seg->offset * TextureSScale(TTex) +
1063 sidedef->TopTextureOffset * TextureOffsetSScale(TTex);
1064 sp->texinfo.Tex = TTex;
1065 sp->texinfo.Alpha = 1.1;
1066 sp->texinfo.Additive = false;
1067 sp->texinfo.ColourMap = 0;
1068
1069 if (linedef->flags & ML_DONTPEGTOP)
1070 {
1071 // top of texture at top
1072 sp->texinfo.toffs = top_TexZ;
1073 }
1074 else
1075 {
1076 // bottom of texture
1077 sp->texinfo.toffs = back_ceiling->TexZ + TTex->GetScaledHeight();
1078 }
1079 sp->texinfo.toffs *= TextureTScale(TTex);
1080 sp->texinfo.toffs += sidedef->TopRowOffset * TextureOffsetTScale(TTex);
1081
1082 wv[0].x = wv[1].x = seg->v1->x;
1083 wv[0].y = wv[1].y = seg->v1->y;
1084 wv[2].x = wv[3].x = seg->v2->x;
1085 wv[2].y = wv[3].y = seg->v2->y;
1086
1087 wv[0].z = MAX(back_topz1, botz1);
1088 wv[1].z = top_topz1;
1089 wv[2].z = top_topz2;
1090 wv[3].z = MAX(back_topz2, botz2);
1091
1092 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1093
1094 sp->frontTopDist = r_ceiling->dist;
1095 sp->frontBotDist = r_floor->dist;
1096 sp->backTopDist = back_ceiling->dist;
1097 sp->backBotDist = back_floor->dist;
1098 sp->TextureOffset = sidedef->TopTextureOffset;
1099 sp->RowOffset = sidedef->TopRowOffset;
1100
1101 // Sky above top
1102 dseg->topsky = pspart++;
1103 if (IsSky(r_ceiling) && !IsSky(back_ceiling))
1104 {
1105 sp = dseg->topsky;
1106
1107 sp->texinfo.Tex = GTextureManager[skyflatnum];
1108 sp->texinfo.Alpha = 1.1;
1109 sp->texinfo.Additive = false;
1110 sp->texinfo.ColourMap = 0;
1111
1112 wv[0].x = wv[1].x = seg->v1->x;
1113 wv[0].y = wv[1].y = seg->v1->y;
1114 wv[2].x = wv[3].x = seg->v2->x;
1115 wv[2].y = wv[3].y = seg->v2->y;
1116
1117 wv[0].z = topz1;
1118 wv[1].z = wv[2].z = skyheight;
1119 wv[3].z = topz2;
1120
1121 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1122
1123 sp->frontTopDist = r_ceiling->dist;
1124 }
1125
1126 // bottom wall
1127 dseg->bot = pspart++;
1128 sp = dseg->bot;
1129
1130 VTexture* BTex = GTextureManager(sidedef->BottomTexture);
1131 sp->texinfo.saxis = segdir * TextureSScale(BTex);
1132 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(BTex);
1133 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
1134 seg->offset * TextureSScale(BTex) +
1135 sidedef->BotTextureOffset * TextureOffsetSScale(BTex);
1136 sp->texinfo.Tex = BTex;
1137 sp->texinfo.Alpha = 1.1;
1138 sp->texinfo.Additive = false;
1139 sp->texinfo.ColourMap = 0;
1140
1141 if (linedef->flags & ML_DONTPEGBOTTOM)
1142 {
1143 // bottom of texture at bottom
1144 // top of texture at top
1145 sp->texinfo.toffs = top_TexZ;
1146 }
1147 else
1148 {
1149 // top of texture at top
1150 sp->texinfo.toffs = back_floor->TexZ;
1151 }
1152 sp->texinfo.toffs *= TextureTScale(BTex);
1153 sp->texinfo.toffs += sidedef->BotRowOffset * TextureOffsetTScale(BTex);
1154
1155 wv[0].x = wv[1].x = seg->v1->x;
1156 wv[0].y = wv[1].y = seg->v1->y;
1157 wv[2].x = wv[3].x = seg->v2->x;
1158 wv[2].y = wv[3].y = seg->v2->y;
1159
1160 wv[0].z = botz1;
1161 wv[1].z = MIN(back_botz1, topz1);
1162 wv[2].z = MIN(back_botz2, topz2);
1163 wv[3].z = botz2;
1164
1165 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1166
1167 sp->frontTopDist = r_ceiling->dist;
1168 sp->frontBotDist = r_floor->dist;
1169 sp->backTopDist = back_ceiling->dist;
1170 sp->backBotDist = back_floor->dist;
1171 sp->TextureOffset = sidedef->BotTextureOffset;
1172 sp->RowOffset = sidedef->BotRowOffset;
1173
1174 float midtopz1 = topz1;
1175 float midtopz2 = topz2;
1176 float midbotz1 = botz1;
1177 float midbotz2 = botz2;
1178 if (topz1 > back_topz1 && sidedef->TopTexture > 0)
1179 {
1180 midtopz1 = back_topz1;
1181 midtopz2 = back_topz2;
1182 }
1183 if (botz1 < back_botz1 && sidedef->BottomTexture > 0)
1184 {
1185 midbotz1 = back_botz1;
1186 midbotz2 = back_botz2;
1187 }
1188
1189 dseg->mid = pspart++;
1190 sp = dseg->mid;
1191
1192 VTexture* MTex = GTextureManager(sidedef->MidTexture);
1193 sp->texinfo.Tex = MTex;
1194 sp->texinfo.ColourMap = 0;
1195 if (MTex->Type != TEXTYPE_Null)
1196 {
1197 // masked MidTexture
1198 float texh = MTex->GetScaledHeight();
1199
1200 float z_org;
1201
1202 sp->texinfo.saxis = segdir * TextureSScale(MTex);
1203 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(MTex);
1204 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
1205 seg->offset * TextureSScale(MTex) +
1206 sidedef->MidTextureOffset * TextureOffsetSScale(MTex);
1207 sp->texinfo.Alpha = linedef->alpha;
1208 sp->texinfo.Additive = !!(linedef->flags & ML_ADDITIVE);
1209
1210 if (linedef->flags & ML_DONTPEGBOTTOM)
1211 {
1212 // bottom of texture at bottom
1213 // top of texture at top
1214 z_org = MAX(seg->frontsector->floor.TexZ,
1215 seg->backsector->floor.TexZ) + texh;
1216 }
1217 else
1218 {
1219 // top of texture at top
1220 z_org = MIN(seg->frontsector->ceiling.TexZ,
1221 seg->backsector->ceiling.TexZ);
1222 }
1223 z_org += sidedef->MidRowOffset * (!MTex->bWorldPanning ?
1224 1.0 : 1.0 / MTex->TScale);
1225
1226 sp->texinfo.toffs = z_org * TextureTScale(MTex);
1227
1228 wv[0].x = wv[1].x = seg->v1->x;
1229 wv[0].y = wv[1].y = seg->v1->y;
1230 wv[2].x = wv[3].x = seg->v2->x;
1231 wv[2].y = wv[3].y = seg->v2->y;
1232
1233 if (linedef->flags & ML_WRAP_MIDTEX)
1234 {
1235 wv[0].z = midbotz1;
1236 wv[1].z = midtopz1;
1237 wv[2].z = midtopz2;
1238 wv[3].z = midbotz2;
1239 }
1240 else
1241 {
1242 wv[0].z = MAX(midbotz1, z_org - texh);
1243 wv[1].z = MIN(midtopz1, z_org);
1244 wv[2].z = MIN(midtopz2, z_org);
1245 wv[3].z = MAX(midbotz2, z_org - texh);
1246 }
1247
1248 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1249 }
1250
1251 sp->frontTopDist = r_ceiling->dist;
1252 sp->frontBotDist = r_floor->dist;
1253 sp->backTopDist = back_ceiling->dist;
1254 sp->backBotDist = back_floor->dist;
1255 sp->TextureOffset = sidedef->MidTextureOffset;
1256 sp->RowOffset = sidedef->MidRowOffset;
1257
1258 sec_region_t *reg;
1259 for (reg = seg->backsector->topregion; reg->prev; reg = reg->prev)
1260 {
1261 sp = pspart++;
1262 sp->next = dseg->extra;
1263 dseg->extra = sp;
1264
1265 sec_plane_t* extratop = reg->floor;
1266 sec_plane_t* extrabot = reg->prev->ceiling;
1267 side_t *extraside = &Level->Sides[reg->prev->extraline->sidenum[0]];
1268
1269 float extratopz1 = extratop->GetPointZ(*seg->v1);
1270 float extratopz2 = extratop->GetPointZ(*seg->v2);
1271 float extrabotz1 = extrabot->GetPointZ(*seg->v1);
1272 float extrabotz2 = extrabot->GetPointZ(*seg->v2);
1273
1274 VTexture* MTex = GTextureManager(extraside->MidTexture);
1275 sp->texinfo.saxis = segdir * TextureSScale(MTex);
1276 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(MTex);
1277 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
1278 seg->offset * TextureSScale(MTex) +
1279 sidedef->MidTextureOffset * TextureOffsetSScale(MTex);
1280
1281 sp->texinfo.toffs = extratop->TexZ *
1282 TextureTScale(MTex) + sidedef->MidRowOffset *
1283 TextureOffsetTScale(MTex);
1284 sp->texinfo.Tex = MTex;
1285 sp->texinfo.Alpha = extrabot->Alpha < 1.0 ? extrabot->Alpha : 1.1;
1286 sp->texinfo.Additive = !!(extrabot->flags & SPF_ADDITIVE);
1287 sp->texinfo.ColourMap = 0;
1288
1289 wv[0].x = wv[1].x = seg->v1->x;
1290 wv[0].y = wv[1].y = seg->v1->y;
1291 wv[2].x = wv[3].x = seg->v2->x;
1292 wv[2].y = wv[3].y = seg->v2->y;
1293
1294 wv[0].z = MAX(extrabotz1, botz1);
1295 wv[1].z = MIN(extratopz1, topz1);
1296 wv[2].z = MIN(extratopz2, topz2);
1297 wv[3].z = MAX(extrabotz2, botz2);
1298
1299 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1300
1301 sp->frontTopDist = r_ceiling->dist;
1302 sp->frontBotDist = r_floor->dist;
1303 sp->backTopDist = extratop->dist;
1304 sp->backBotDist = extrabot->dist;
1305 sp->TextureOffset = sidedef->MidTextureOffset;
1306 sp->RowOffset = sidedef->MidRowOffset;
1307 }
1308 }
1309 unguard;
1310 }
1311
1312 //==========================================================================
1313 //
1314 // VRenderLevelShared::UpdateRowOffset
1315 //
1316 //==========================================================================
1317
UpdateRowOffset(segpart_t * sp,float RowOffset)1318 void VRenderLevelShared::UpdateRowOffset(segpart_t *sp, float RowOffset)
1319 {
1320 guard(VRenderLevelShared::UpdateRowOffset);
1321 sp->texinfo.toffs += (RowOffset - sp->RowOffset) *
1322 TextureOffsetTScale(sp->texinfo.Tex);
1323 sp->RowOffset = RowOffset;
1324 FlushSurfCaches(sp->surfs);
1325 InitSurfs(sp->surfs, &sp->texinfo, NULL, r_sub);
1326 unguard;
1327 }
1328
1329 //==========================================================================
1330 //
1331 // VRenderLevelShared::UpdateTextureOffset
1332 //
1333 //==========================================================================
1334
UpdateTextureOffset(segpart_t * sp,float TextureOffset)1335 void VRenderLevelShared::UpdateTextureOffset(segpart_t* sp,
1336 float TextureOffset)
1337 {
1338 guard(VRenderLevelShared::UpdateTextureOffset);
1339 sp->texinfo.soffs += (TextureOffset - sp->TextureOffset) *
1340 TextureOffsetSScale(sp->texinfo.Tex);
1341 sp->TextureOffset = TextureOffset;
1342 FlushSurfCaches(sp->surfs);
1343 InitSurfs(sp->surfs, &sp->texinfo, NULL, r_sub);
1344 unguard;
1345 }
1346
1347 //==========================================================================
1348 //
1349 // VRenderLevelShared::UpdateDrawSeg
1350 //
1351 //==========================================================================
1352
UpdateDrawSeg(drawseg_t * dseg,bool ShouldClip)1353 void VRenderLevelShared::UpdateDrawSeg(drawseg_t* dseg, bool ShouldClip)
1354 {
1355 guard(VRenderLevelShared::UpdateDrawSeg);
1356 seg_t *seg = dseg->seg;
1357 segpart_t *sp;
1358 TVec wv[4];
1359
1360 if (!seg->linedef)
1361 {
1362 // Miniseg
1363 return;
1364 }
1365
1366 side_t* sidedef = seg->sidedef;
1367 line_t* linedef = seg->linedef;
1368
1369 if (ShouldClip)
1370 {
1371 float a1 = ViewClip.PointToClipAngle(*seg->v2);
1372 float a2 = ViewClip.PointToClipAngle(*seg->v1);
1373 if (!ViewClip.IsRangeVisible(a1, a2))
1374 {
1375 return;
1376 }
1377 }
1378
1379 if (!seg->backsector)
1380 {
1381 sp = dseg->mid;
1382 sp->texinfo.ColourMap = ColourMap;
1383 VTexture* MTex = GTextureManager(sidedef->MidTexture);
1384 if (FASI(sp->frontTopDist) != FASI(r_ceiling->dist) ||
1385 FASI(sp->frontBotDist) != FASI(r_floor->dist) ||
1386 sp->texinfo.Tex->SScale != MTex->SScale ||
1387 sp->texinfo.Tex->TScale != MTex->TScale ||
1388 sp->texinfo.Tex->GetHeight() != MTex->GetHeight())
1389 {
1390 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1391 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1392 float botz1 = r_floor->GetPointZ(*seg->v1);
1393 float botz2 = r_floor->GetPointZ(*seg->v2);
1394
1395 FreeWSurfs(sp->surfs);
1396 sp->surfs = NULL;
1397
1398 if (linedef->flags & ML_DONTPEGBOTTOM)
1399 {
1400 // bottom of texture at bottom
1401 sp->texinfo.toffs = r_floor->TexZ +
1402 MTex->GetScaledHeight();
1403 }
1404 else if (linedef->flags & ML_DONTPEGTOP)
1405 {
1406 // top of texture at top of top region
1407 sp->texinfo.toffs =
1408 r_sub->sector->topregion->ceiling->TexZ;
1409 }
1410 else
1411 {
1412 // top of texture at top
1413 sp->texinfo.toffs = r_ceiling->TexZ;
1414 }
1415 sp->texinfo.toffs *= TextureTScale(MTex);
1416 sp->texinfo.toffs += sidedef->MidRowOffset * TextureOffsetTScale(MTex);
1417 sp->texinfo.Tex = MTex;
1418
1419 wv[0].x = wv[1].x = seg->v1->x;
1420 wv[0].y = wv[1].y = seg->v1->y;
1421 wv[2].x = wv[3].x = seg->v2->x;
1422 wv[2].y = wv[3].y = seg->v2->y;
1423
1424 wv[0].z = botz1;
1425 wv[1].z = topz1;
1426 wv[2].z = topz2;
1427 wv[3].z = botz2;
1428
1429 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1430
1431 sp->frontTopDist = r_ceiling->dist;
1432 sp->frontBotDist = r_floor->dist;
1433 sp->RowOffset = sidedef->MidRowOffset;
1434 }
1435 else if (FASI(sp->RowOffset) != FASI(sidedef->MidRowOffset))
1436 {
1437 sp->texinfo.Tex = MTex;
1438 UpdateRowOffset(sp, sidedef->MidRowOffset);
1439 }
1440 else
1441 {
1442 sp->texinfo.Tex = MTex;
1443 }
1444 if (FASI(sp->TextureOffset) != FASI(sidedef->MidTextureOffset))
1445 {
1446 UpdateTextureOffset(sp, sidedef->MidTextureOffset);
1447 }
1448
1449 sp = dseg->topsky;
1450 sp->texinfo.ColourMap = ColourMap;
1451 if (IsSky(r_ceiling) &&
1452 FASI(sp->frontTopDist) != FASI(r_ceiling->dist))
1453 {
1454 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1455 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1456
1457 FreeWSurfs(sp->surfs);
1458 sp->surfs = NULL;
1459
1460 wv[0].x = wv[1].x = seg->v1->x;
1461 wv[0].y = wv[1].y = seg->v1->y;
1462 wv[2].x = wv[3].x = seg->v2->x;
1463 wv[2].y = wv[3].y = seg->v2->y;
1464
1465 wv[0].z = topz1;
1466 wv[1].z = wv[2].z = skyheight;
1467 wv[3].z = topz2;
1468
1469 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1470
1471 sp->frontTopDist = r_ceiling->dist;
1472 }
1473 }
1474 else
1475 {
1476 sec_plane_t* back_floor = &seg->backsector->floor;
1477 sec_plane_t* back_ceiling = &seg->backsector->ceiling;
1478 if (seg->backsector->fakefloors)
1479 {
1480 if (back_floor == &seg->backsector->floor)
1481 {
1482 back_floor = &seg->backsector->fakefloors->floorplane;
1483 }
1484 if (back_ceiling == &seg->backsector->ceiling)
1485 {
1486 back_ceiling = &seg->backsector->fakefloors->ceilplane;
1487 }
1488 }
1489
1490 // top wall
1491 sp = dseg->top;
1492 sp->texinfo.ColourMap = ColourMap;
1493 VTexture* TTex = GTextureManager(sidedef->TopTexture);
1494 if (IsSky(r_ceiling) && IsSky(back_ceiling) &&
1495 r_ceiling->SkyBox != back_ceiling->SkyBox)
1496 {
1497 TTex = GTextureManager[skyflatnum];
1498 }
1499 if (FASI(sp->frontTopDist) != FASI(r_ceiling->dist) ||
1500 FASI(sp->frontBotDist) != FASI(r_floor->dist) ||
1501 FASI(sp->backTopDist) != FASI(back_ceiling->dist) ||
1502 sp->texinfo.Tex->SScale != TTex->SScale ||
1503 sp->texinfo.Tex->TScale != TTex->TScale)
1504 {
1505 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1506 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1507 float botz1 = r_floor->GetPointZ(*seg->v1);
1508 float botz2 = r_floor->GetPointZ(*seg->v2);
1509
1510 float back_topz1 = back_ceiling->GetPointZ(*seg->v1);
1511 float back_topz2 = back_ceiling->GetPointZ(*seg->v2);
1512
1513 // hack to allow height changes in outdoor areas
1514 float top_topz1 = topz1;
1515 float top_topz2 = topz2;
1516 float top_TexZ = r_ceiling->TexZ;
1517 if (IsSky(r_ceiling) && IsSky(back_ceiling) &&
1518 r_ceiling->SkyBox == back_ceiling->SkyBox)
1519 {
1520 top_topz1 = back_topz1;
1521 top_topz2 = back_topz2;
1522 top_TexZ = back_ceiling->TexZ;
1523 }
1524
1525 FreeWSurfs(sp->surfs);
1526 sp->surfs = NULL;
1527
1528 if (linedef->flags & ML_DONTPEGTOP)
1529 {
1530 // top of texture at top
1531 sp->texinfo.toffs = top_TexZ;
1532 }
1533 else
1534 {
1535 // bottom of texture
1536 sp->texinfo.toffs = back_ceiling->TexZ + TTex->GetScaledHeight();
1537 }
1538 sp->texinfo.toffs *= TextureTScale(TTex);
1539 sp->texinfo.toffs += sidedef->TopRowOffset * TextureOffsetTScale(TTex);
1540 sp->texinfo.Tex = TTex;
1541
1542 wv[0].x = wv[1].x = seg->v1->x;
1543 wv[0].y = wv[1].y = seg->v1->y;
1544 wv[2].x = wv[3].x = seg->v2->x;
1545 wv[2].y = wv[3].y = seg->v2->y;
1546
1547 wv[0].z = MAX(back_topz1, botz1);
1548 wv[1].z = top_topz1;
1549 wv[2].z = top_topz2;
1550 wv[3].z = MAX(back_topz2, botz2);
1551
1552 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1553
1554 sp->frontTopDist = r_ceiling->dist;
1555 sp->frontBotDist = r_floor->dist;
1556 sp->backTopDist = back_ceiling->dist;
1557 sp->RowOffset = sidedef->TopRowOffset;
1558 }
1559 else if (FASI(sp->RowOffset) != FASI(sidedef->TopRowOffset))
1560 {
1561 sp->texinfo.Tex = TTex;
1562 UpdateRowOffset(sp, sidedef->TopRowOffset);
1563 }
1564 else
1565 {
1566 sp->texinfo.Tex = TTex;
1567 }
1568 if (FASI(sp->TextureOffset) != FASI(sidedef->TopTextureOffset))
1569 {
1570 UpdateTextureOffset(sp, sidedef->TopTextureOffset);
1571 }
1572
1573 // Sky above top
1574 sp = dseg->topsky;
1575 sp->texinfo.ColourMap = ColourMap;
1576 if (IsSky(r_ceiling) && !IsSky(back_ceiling) &&
1577 FASI(sp->frontTopDist) != FASI(r_ceiling->dist))
1578 {
1579 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1580 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1581
1582 FreeWSurfs(sp->surfs);
1583 sp->surfs = NULL;
1584
1585 sp->texinfo.Tex = GTextureManager[skyflatnum];
1586 sp->texinfo.Alpha = 1.1;
1587 sp->texinfo.Additive = false;
1588 sp->texinfo.ColourMap = 0;
1589
1590 wv[0].x = wv[1].x = seg->v1->x;
1591 wv[0].y = wv[1].y = seg->v1->y;
1592 wv[2].x = wv[3].x = seg->v2->x;
1593 wv[2].y = wv[3].y = seg->v2->y;
1594
1595 wv[0].z = topz1;
1596 wv[1].z = wv[2].z = skyheight;
1597 wv[3].z = topz2;
1598
1599 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1600
1601 sp->frontTopDist = r_ceiling->dist;
1602 }
1603
1604 // bottom wall
1605 sp = dseg->bot;
1606 sp->texinfo.ColourMap = ColourMap;
1607 VTexture* BTex = GTextureManager(sidedef->BottomTexture);
1608 sp->texinfo.Tex = BTex;
1609 if (FASI(sp->frontTopDist) != FASI(r_ceiling->dist) ||
1610 FASI(sp->frontBotDist) != FASI(r_floor->dist) ||
1611 FASI(sp->backBotDist) != FASI(back_floor->dist))
1612 {
1613 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1614 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1615 float botz1 = r_floor->GetPointZ(*seg->v1);
1616 float botz2 = r_floor->GetPointZ(*seg->v2);
1617 float top_TexZ = r_ceiling->TexZ;
1618
1619 float back_botz1 = back_floor->GetPointZ(*seg->v1);
1620 float back_botz2 = back_floor->GetPointZ(*seg->v2);
1621
1622 // hack to allow height changes in outdoor areas
1623 if (IsSky(r_ceiling) && IsSky(back_ceiling))
1624 {
1625 topz1 = back_ceiling->GetPointZ(*seg->v1);
1626 topz2 = back_ceiling->GetPointZ(*seg->v2);
1627 top_TexZ = back_ceiling->TexZ;
1628 }
1629
1630 FreeWSurfs(sp->surfs);
1631 sp->surfs = NULL;
1632
1633 if (linedef->flags & ML_DONTPEGBOTTOM)
1634 {
1635 // bottom of texture at bottom
1636 // top of texture at top
1637 sp->texinfo.toffs = top_TexZ;
1638 }
1639 else
1640 {
1641 // top of texture at top
1642 sp->texinfo.toffs = back_floor->TexZ;
1643 }
1644 sp->texinfo.toffs *= TextureTScale(BTex);
1645 sp->texinfo.toffs += sidedef->BotRowOffset *
1646 TextureOffsetTScale(BTex);
1647
1648 wv[0].x = wv[1].x = seg->v1->x;
1649 wv[0].y = wv[1].y = seg->v1->y;
1650 wv[2].x = wv[3].x = seg->v2->x;
1651 wv[2].y = wv[3].y = seg->v2->y;
1652
1653 wv[0].z = botz1;
1654 wv[1].z = MIN(back_botz1, topz1);
1655 wv[2].z = MIN(back_botz2, topz2);
1656 wv[3].z = botz2;
1657
1658 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1659
1660 sp->frontTopDist = r_ceiling->dist;
1661 sp->frontBotDist = r_floor->dist;
1662 sp->backBotDist = back_floor->dist;
1663 sp->RowOffset = sidedef->BotRowOffset;
1664 }
1665 else if (FASI(sp->RowOffset) != FASI(sidedef->BotRowOffset))
1666 {
1667 UpdateRowOffset(sp, sidedef->BotRowOffset);
1668 }
1669 if (FASI(sp->TextureOffset) != FASI(sidedef->BotTextureOffset))
1670 {
1671 UpdateTextureOffset(sp, sidedef->BotTextureOffset);
1672 }
1673
1674 // masked MidTexture
1675 sp = dseg->mid;
1676 sp->texinfo.ColourMap = ColourMap;
1677 VTexture* MTex = GTextureManager(sidedef->MidTexture);
1678 if (FASI(sp->frontTopDist) != FASI(r_ceiling->dist) ||
1679 FASI(sp->frontBotDist) != FASI(r_floor->dist) ||
1680 FASI(sp->backTopDist) != FASI(back_ceiling->dist) ||
1681 FASI(sp->backBotDist) != FASI(back_floor->dist) ||
1682 FASI(sp->RowOffset) != FASI(sidedef->MidRowOffset) ||
1683 sp->texinfo.Tex->SScale != MTex->SScale ||
1684 sp->texinfo.Tex->TScale != MTex->TScale ||
1685 sp->texinfo.Tex->GetHeight() != MTex->GetHeight() ||
1686 (sp->texinfo.Tex->Type == TEXTYPE_Null) != (MTex->Type == TEXTYPE_Null))
1687 {
1688 FreeWSurfs(sp->surfs);
1689 sp->surfs = NULL;
1690
1691 sp->texinfo.Tex = MTex;
1692 if (sidedef->MidTexture)
1693 {
1694 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1695 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1696 float botz1 = r_floor->GetPointZ(*seg->v1);
1697 float botz2 = r_floor->GetPointZ(*seg->v2);
1698
1699 float back_topz1 = back_ceiling->GetPointZ(*seg->v1);
1700 float back_topz2 = back_ceiling->GetPointZ(*seg->v2);
1701 float back_botz1 = back_floor->GetPointZ(*seg->v1);
1702 float back_botz2 = back_floor->GetPointZ(*seg->v2);
1703
1704 float midtopz1 = topz1;
1705 float midtopz2 = topz2;
1706 float midbotz1 = botz1;
1707 float midbotz2 = botz2;
1708 if (topz1 > back_topz1 && sidedef->TopTexture > 0)
1709 {
1710 midtopz1 = back_topz1;
1711 midtopz2 = back_topz2;
1712 }
1713 if (botz1 < back_botz1 && sidedef->BottomTexture > 0)
1714 {
1715 midbotz1 = back_botz1;
1716 midbotz2 = back_botz2;
1717 }
1718
1719 float texh = MTex->GetScaledHeight();
1720
1721 float z_org;
1722
1723 TVec segdir = (*seg->v2 - *seg->v1) / seg->length;
1724
1725 sp->texinfo.saxis = segdir * TextureSScale(MTex);
1726 sp->texinfo.taxis = TVec(0, 0, -1) * TextureTScale(MTex);
1727 sp->texinfo.soffs = -DotProduct(*seg->v1, sp->texinfo.saxis) +
1728 seg->offset * TextureSScale(MTex) +
1729 sidedef->MidTextureOffset * TextureOffsetSScale(MTex);
1730 sp->texinfo.Alpha = linedef->alpha;
1731 sp->texinfo.Additive = !!(linedef->flags & ML_ADDITIVE);
1732
1733 if (linedef->flags & ML_DONTPEGBOTTOM)
1734 {
1735 // bottom of texture at bottom
1736 // top of texture at top
1737 z_org = MAX(seg->frontsector->floor.TexZ,
1738 seg->backsector->floor.TexZ) + texh;
1739 }
1740 else
1741 {
1742 // top of texture at top
1743 z_org = MIN(seg->frontsector->ceiling.TexZ,
1744 seg->backsector->ceiling.TexZ);
1745 }
1746 z_org += sidedef->MidRowOffset * (!MTex->bWorldPanning ?
1747 1.0 : 1.0 / MTex->TScale);
1748
1749 sp->texinfo.toffs = z_org * TextureTScale(MTex);
1750
1751 wv[0].x = wv[1].x = seg->v1->x;
1752 wv[0].y = wv[1].y = seg->v1->y;
1753 wv[2].x = wv[3].x = seg->v2->x;
1754 wv[2].y = wv[3].y = seg->v2->y;
1755
1756 if (linedef->flags & ML_WRAP_MIDTEX)
1757 {
1758 wv[0].z = midbotz1;
1759 wv[1].z = midtopz1;
1760 wv[2].z = midtopz2;
1761 wv[3].z = midbotz2;
1762 }
1763 else
1764 {
1765 wv[0].z = MAX(midbotz1, z_org - texh);
1766 wv[1].z = MIN(midtopz1, z_org);
1767 wv[2].z = MIN(midtopz2, z_org);
1768 wv[3].z = MAX(midbotz2, z_org - texh);
1769 }
1770
1771 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1772 }
1773 else
1774 {
1775 sp->texinfo.Alpha = 1.1;
1776 sp->texinfo.Additive = false;
1777 }
1778
1779 sp->frontTopDist = r_ceiling->dist;
1780 sp->frontBotDist = r_floor->dist;
1781 sp->backTopDist = back_ceiling->dist;
1782 sp->backBotDist = back_floor->dist;
1783 sp->RowOffset = sidedef->MidRowOffset;
1784 }
1785 else
1786 {
1787 sp->texinfo.Tex = MTex;
1788 if (sidedef->MidTexture)
1789 {
1790 sp->texinfo.Alpha = linedef->alpha;
1791 sp->texinfo.Additive = !!(linedef->flags & ML_ADDITIVE);
1792 }
1793 }
1794 if (FASI(sp->TextureOffset) != FASI(sidedef->MidTextureOffset))
1795 {
1796 UpdateTextureOffset(sp, sidedef->MidTextureOffset);
1797 }
1798
1799 sec_region_t *reg;
1800 segpart_t *sp = dseg->extra;
1801 for (reg = seg->backsector->botregion; reg->next; reg = reg->next)
1802 {
1803 sec_plane_t* extratop = reg->next->floor;
1804 sec_plane_t* extrabot = reg->ceiling;
1805 side_t *extraside = &Level->Sides[reg->extraline->sidenum[0]];
1806
1807 sp->texinfo.ColourMap = ColourMap;
1808 VTexture* ETex = GTextureManager(extraside->MidTexture);
1809 sp->texinfo.Tex = ETex;
1810 if (FASI(sp->frontTopDist) != FASI(r_ceiling->dist) ||
1811 FASI(sp->frontBotDist) != FASI(r_floor->dist) ||
1812 FASI(sp->backTopDist) != FASI(extratop->dist) ||
1813 FASI(sp->backBotDist) != FASI(extrabot->dist))
1814 {
1815 float topz1 = r_ceiling->GetPointZ(*seg->v1);
1816 float topz2 = r_ceiling->GetPointZ(*seg->v2);
1817 float botz1 = r_floor->GetPointZ(*seg->v1);
1818 float botz2 = r_floor->GetPointZ(*seg->v2);
1819
1820 float extratopz1 = extratop->GetPointZ(*seg->v1);
1821 float extratopz2 = extratop->GetPointZ(*seg->v2);
1822 float extrabotz1 = extrabot->GetPointZ(*seg->v1);
1823 float extrabotz2 = extrabot->GetPointZ(*seg->v2);
1824
1825 FreeWSurfs(sp->surfs);
1826 sp->surfs = NULL;
1827
1828 sp->texinfo.toffs = extratop->TexZ *
1829 TextureTScale(ETex) + sidedef->MidRowOffset *
1830 TextureOffsetTScale(ETex);
1831
1832 wv[0].x = wv[1].x = seg->v1->x;
1833 wv[0].y = wv[1].y = seg->v1->y;
1834 wv[2].x = wv[3].x = seg->v2->x;
1835 wv[2].y = wv[3].y = seg->v2->y;
1836
1837 wv[0].z = MAX(extrabotz1, botz1);
1838 wv[1].z = MIN(extratopz1, topz1);
1839 wv[2].z = MIN(extratopz2, topz2);
1840 wv[3].z = MAX(extrabotz2, botz2);
1841
1842 sp->surfs = CreateWSurfs(wv, &sp->texinfo, seg, r_sub);
1843
1844 sp->frontTopDist = r_ceiling->dist;
1845 sp->frontBotDist = r_floor->dist;
1846 sp->backTopDist = extratop->dist;
1847 sp->backBotDist = extrabot->dist;
1848 sp->RowOffset = sidedef->MidRowOffset;
1849 }
1850 else if (FASI(sp->RowOffset) != FASI(sidedef->MidRowOffset))
1851 {
1852 UpdateRowOffset(sp, sidedef->MidRowOffset);
1853 }
1854 if (FASI(sp->TextureOffset) != FASI(sidedef->MidTextureOffset))
1855 {
1856 UpdateTextureOffset(sp, sidedef->MidTextureOffset);
1857 }
1858 sp = sp->next;
1859 }
1860 }
1861 unguard;
1862 }
1863
1864 //==========================================================================
1865 //
1866 // VRenderLevelShared::SegMoved
1867 //
1868 //==========================================================================
1869
SegMoved(seg_t * seg)1870 void VRenderLevelShared::SegMoved(seg_t* seg)
1871 {
1872 guard(VRenderLevelShared::SegMoved);
1873 if (!seg->drawsegs)
1874 {
1875 // Drawsegs not created yet
1876 return;
1877 }
1878 if (!seg->linedef)
1879 {
1880 Sys_Error("R_SegMoved: miniseg");
1881 }
1882
1883 VTexture* Tex = seg->drawsegs->mid->texinfo.Tex;
1884 seg->drawsegs->mid->texinfo.saxis = (*seg->v2 - *seg->v1) / seg->length *
1885 TextureSScale(Tex);
1886 seg->drawsegs->mid->texinfo.soffs = -DotProduct(*seg->v1,
1887 seg->drawsegs->mid->texinfo.saxis) +
1888 seg->offset * TextureSScale(Tex) +
1889 seg->sidedef->MidTextureOffset * TextureOffsetSScale(Tex);
1890
1891 // Force update
1892 seg->drawsegs->mid->frontTopDist += 0.346;
1893 unguard;
1894 }
1895
1896 //==========================================================================
1897 //
1898 // VRenderLevel::PreRender
1899 //
1900 //==========================================================================
1901
PreRender()1902 void VRenderLevel::PreRender()
1903 {
1904 guard(VRenderLevel::PreRender);
1905 c_subdivides = 0;
1906 c_seg_div = 0;
1907 light_mem = 0;
1908
1909 CreateWorldSurfaces();
1910
1911 GCon->Logf(NAME_Dev, "%d subdivides", c_subdivides);
1912 GCon->Logf(NAME_Dev, "%d seg subdivides", c_seg_div);
1913 GCon->Logf(NAME_Dev, "%dk light mem", light_mem / 1024);
1914 unguard;
1915 }
1916
1917 //==========================================================================
1918 //
1919 // VAdvancedRenderLevel::PreRender
1920 //
1921 //==========================================================================
1922
PreRender()1923 void VAdvancedRenderLevel::PreRender()
1924 {
1925 guard(VAdvancedRenderLevel::PreRender);
1926 CreateWorldSurfaces();
1927 unguard;
1928 }
1929
1930 //==========================================================================
1931 //
1932 // VRenderLevelShared::CreateWorldSurfaces
1933 //
1934 //==========================================================================
1935
CreateWorldSurfaces()1936 void VRenderLevelShared::CreateWorldSurfaces()
1937 {
1938 guard(VRenderLevelShared::CreateWorldSurfaces);
1939 int i, j;
1940 int count, dscount, spcount;
1941 subregion_t *sreg;
1942 subsector_t *sub;
1943 drawseg_t *pds;
1944 sec_region_t *reg;
1945
1946 free_wsurfs = NULL;
1947 SetupSky();
1948
1949 // Set up fake floors.
1950 for (i = 0; i < Level->NumSectors; i++)
1951 {
1952 if (Level->Sectors[i].heightsec)
1953 {
1954 SetupFakeFloors(&Level->Sectors[i]);
1955 }
1956 }
1957
1958 // Count regions in all subsectors
1959 count = 0;
1960 dscount = 0;
1961 spcount = 0;
1962 for (i = 0; i < Level->NumSubsectors; i++)
1963 {
1964 sub = &Level->Subsectors[i];
1965 if (!sub->sector->linecount)
1966 {
1967 // Skip sectors containing original polyobjs
1968 continue;
1969 }
1970 for (reg = sub->sector->botregion; reg; reg = reg->next)
1971 {
1972 count++;
1973 dscount += sub->numlines;
1974 if (sub->poly)
1975 {
1976 // Polyobj
1977 dscount += sub->poly->numsegs;
1978 }
1979 for (j = 0; j < sub->numlines; j++)
1980 {
1981 spcount += CountSegParts(&Level->Segs[sub->firstline + j]);
1982 }
1983 if (sub->poly)
1984 {
1985 int polyCount = sub->poly->numsegs;
1986 seg_t **polySeg = sub->poly->segs;
1987 while (polyCount--)
1988 {
1989 spcount += CountSegParts(*polySeg);
1990 polySeg++;
1991 }
1992 }
1993 }
1994 }
1995
1996 // Get some memory
1997 sreg = new subregion_t[count];
1998 pds = new drawseg_t[dscount];
1999 pspart = new segpart_t[spcount];
2000 memset(sreg, 0, sizeof(subregion_t) * count);
2001 memset(pds, 0, sizeof(drawseg_t) * dscount);
2002 memset(pspart, 0, sizeof(segpart_t) * spcount);
2003 AllocatedSubRegions = sreg;
2004 AllocatedDrawSegs = pds;
2005 AllocatedSegParts = pspart;
2006
2007 // Add dplanes
2008 for (i = 0; i < Level->NumSubsectors; i++)
2009 {
2010 if (!(i & 7))
2011 {
2012 CL_KeepaliveMessage();
2013 }
2014 sub = &Level->Subsectors[i];
2015 if (!sub->sector->linecount)
2016 {
2017 // Skip sectors containing original polyobjs
2018 continue;
2019 }
2020 r_sub = sub;
2021 for (reg = sub->sector->botregion; reg; reg = reg->next)
2022 {
2023 r_floor = reg->floor;
2024 r_ceiling = reg->ceiling;
2025 if (sub->sector->fakefloors)
2026 {
2027 if (r_floor == &sub->sector->floor)
2028 {
2029 r_floor = &sub->sector->fakefloors->floorplane;
2030 }
2031 if (r_ceiling == &sub->sector->ceiling)
2032 {
2033 r_ceiling = &sub->sector->fakefloors->ceilplane;
2034 }
2035 }
2036
2037 sreg->secregion = reg;
2038 sreg->floorplane = r_floor;
2039 sreg->ceilplane = r_ceiling;
2040 sreg->floor = CreateSecSurface(sub, r_floor);
2041 sreg->ceil = CreateSecSurface(sub, r_ceiling);
2042
2043 sreg->count = sub->numlines;
2044 if (sub->poly)
2045 {
2046 // Polyobj
2047 sreg->count += sub->poly->numsegs;
2048 }
2049 sreg->lines = pds;
2050 pds += sreg->count;
2051 for (j = 0; j < sub->numlines; j++)
2052 {
2053 CreateSegParts(&sreg->lines[j], &Level->Segs[sub->firstline + j]);
2054 }
2055 if (sub->poly)
2056 {
2057 // Polyobj
2058 int polyCount = sub->poly->numsegs;
2059 seg_t **polySeg = sub->poly->segs;
2060 while (polyCount--)
2061 {
2062 CreateSegParts(&sreg->lines[j], *polySeg);
2063 polySeg++;
2064 j++;
2065 }
2066 }
2067
2068 sreg->next = sub->regions;
2069 sub->regions = sreg;
2070 sreg++;
2071 }
2072 }
2073 unguard;
2074 }
2075
2076 //==========================================================================
2077 //
2078 // VRenderLevelShared::UpdateSubRegion
2079 //
2080 //==========================================================================
2081
UpdateSubRegion(subregion_t * region,bool ClipSegs)2082 void VRenderLevelShared::UpdateSubRegion(subregion_t* region, bool ClipSegs)
2083 {
2084 guard(VRenderLevelShared::UpdateSubRegion);
2085 int count;
2086 int polyCount;
2087 seg_t** polySeg;
2088
2089 r_floor = region->floorplane;
2090 r_ceiling = region->ceilplane;
2091 if (r_sub->sector->fakefloors)
2092 {
2093 if (r_floor == &r_sub->sector->floor)
2094 {
2095 r_floor = &r_sub->sector->fakefloors->floorplane;
2096 }
2097 if (r_ceiling == &r_sub->sector->ceiling)
2098 {
2099 r_ceiling = &r_sub->sector->fakefloors->ceilplane;
2100 }
2101 }
2102
2103 count = r_sub->numlines;
2104 drawseg_t *ds = region->lines;
2105 while (count--)
2106 {
2107 UpdateDrawSeg(ds, ClipSegs);
2108 ds++;
2109 }
2110
2111 UpdateSecSurface(region->floor, region->floorplane, r_sub);
2112 UpdateSecSurface(region->ceil, region->ceilplane, r_sub);
2113
2114 if (r_sub->poly)
2115 {
2116 // Update the polyobj
2117 polyCount = r_sub->poly->numsegs;
2118 polySeg = r_sub->poly->segs;
2119 while (polyCount--)
2120 {
2121 UpdateDrawSeg((*polySeg)->drawsegs, ClipSegs);
2122 polySeg++;
2123 }
2124 }
2125
2126 if (region->next)
2127 {
2128 UpdateSubRegion(region->next, ClipSegs);
2129 }
2130 unguard;
2131 }
2132
2133 //==========================================================================
2134 //
2135 // VRenderLevel::UpdateSubsector
2136 //
2137 //==========================================================================
2138
UpdateSubsector(int num,float * bbox)2139 void VRenderLevel::UpdateSubsector(int num, float *bbox)
2140 {
2141 guard(VRenderLevel::UpdateSubsector);
2142 r_sub = &Level->Subsectors[num];
2143
2144 if (r_sub->VisFrame != r_visframecount)
2145 {
2146 return;
2147 }
2148
2149 if (!r_sub->sector->linecount)
2150 {
2151 // Skip sectors containing original polyobjs
2152 return;
2153 }
2154
2155 if (!ViewClip.ClipCheckSubsector(r_sub))
2156 {
2157 return;
2158 }
2159
2160 bbox[2] = r_sub->sector->floor.minz;
2161 if (IsSky(&r_sub->sector->ceiling))
2162 {
2163 bbox[5] = skyheight;
2164 }
2165 else
2166 {
2167 bbox[5] = r_sub->sector->ceiling.maxz;
2168 }
2169
2170 UpdateSubRegion(r_sub->regions, true);
2171
2172 ViewClip.ClipAddSubsectorSegs(r_sub);
2173 unguard;
2174 }
2175
2176 //==========================================================================
2177 //
2178 // VAdvancedRenderLevel::UpdateSubsector
2179 //
2180 //==========================================================================
2181
UpdateSubsector(int num,float * bbox)2182 void VAdvancedRenderLevel::UpdateSubsector(int num, float *bbox)
2183 {
2184 guard(VAdvancedRenderLevel::UpdateSubsector);
2185 r_sub = &Level->Subsectors[num];
2186
2187 if (!r_sub->sector->linecount)
2188 {
2189 // Skip sectors containing original polyobjs
2190 return;
2191 }
2192
2193 bbox[2] = r_sub->sector->floor.minz;
2194 if (IsSky(&r_sub->sector->ceiling))
2195 {
2196 bbox[5] = skyheight;
2197 }
2198 else
2199 {
2200 bbox[5] = r_sub->sector->ceiling.maxz;
2201 }
2202
2203 UpdateSubRegion(r_sub->regions, false);
2204 unguard;
2205 }
2206
2207 //==========================================================================
2208 //
2209 // VRenderLevel::UpdateBSPNode
2210 //
2211 //==========================================================================
2212
UpdateBSPNode(int bspnum,float * bbox)2213 void VRenderLevel::UpdateBSPNode(int bspnum, float* bbox)
2214 {
2215 guard(VRenderLevel::UpdateBSPNode);
2216 if (ViewClip.ClipIsFull())
2217 {
2218 return;
2219 }
2220
2221 if (!ViewClip.ClipIsBBoxVisible(bbox))
2222 {
2223 return;
2224 }
2225
2226 // Found a subsector?
2227 if (bspnum & NF_SUBSECTOR)
2228 {
2229 if (bspnum == -1)
2230 {
2231 UpdateSubsector(0, bbox);
2232 }
2233 else
2234 {
2235 UpdateSubsector(bspnum & (~NF_SUBSECTOR), bbox);
2236 }
2237 return;
2238 }
2239
2240 node_t* bsp = &Level->Nodes[bspnum];
2241
2242 if (bsp->VisFrame != r_visframecount)
2243 {
2244 return;
2245 }
2246
2247 // Decide which side the view point is on.
2248 int side = bsp->PointOnSide(vieworg);
2249
2250 UpdateBSPNode(bsp->children[side], bsp->bbox[side]);
2251 UpdateBSPNode(bsp->children[side ^ 1], bsp->bbox[side ^ 1]);
2252 bbox[2] = MIN(bsp->bbox[0][2], bsp->bbox[1][2]);
2253 bbox[5] = MAX(bsp->bbox[0][5], bsp->bbox[1][5]);
2254 unguard;
2255 }
2256
2257 //==========================================================================
2258 //
2259 // VAdvancedRenderLevel::UpdateBSPNode
2260 //
2261 //==========================================================================
2262
UpdateBSPNode(int bspnum,float * bbox)2263 void VAdvancedRenderLevel::UpdateBSPNode(int bspnum, float* bbox)
2264 {
2265 guard(VAdvancedRenderLevel::UpdateBSPNode);
2266 // Found a subsector?
2267 if (bspnum & NF_SUBSECTOR)
2268 {
2269 if (bspnum == -1)
2270 {
2271 UpdateSubsector(0, bbox);
2272 }
2273 else
2274 {
2275 UpdateSubsector(bspnum & (~NF_SUBSECTOR), bbox);
2276 }
2277 return;
2278 }
2279
2280 node_t* bsp = &Level->Nodes[bspnum];
2281
2282 // Decide which side the view point is on.
2283 int side = bsp->PointOnSide(vieworg);
2284
2285 UpdateBSPNode(bsp->children[side], bsp->bbox[side]);
2286 UpdateBSPNode(bsp->children[side ^ 1], bsp->bbox[side ^ 1]);
2287 bbox[2] = MIN(bsp->bbox[0][2], bsp->bbox[1][2]);
2288 bbox[5] = MAX(bsp->bbox[0][5], bsp->bbox[1][5]);
2289 unguard;
2290 }
2291
2292 //==========================================================================
2293 //
2294 // VRenderLevelShared::CopyPlaneIfValid
2295 //
2296 //==========================================================================
2297
CopyPlaneIfValid(sec_plane_t * dest,const sec_plane_t * source,const sec_plane_t * opp)2298 bool VRenderLevelShared::CopyPlaneIfValid(sec_plane_t* dest,
2299 const sec_plane_t* source, const sec_plane_t* opp)
2300 {
2301 guard(VRenderLevelShared::CopyPlaneIfValid);
2302 bool copy = false;
2303
2304 // If the planes do not have matching slopes, then always copy them
2305 // because clipping would require creating new sectors.
2306 if (source->normal != dest->normal)
2307 {
2308 copy = true;
2309 }
2310 else if (opp->normal != -dest->normal)
2311 {
2312 if (source->dist > dest->dist)
2313 {
2314 copy = true;
2315 }
2316 }
2317 else if (source->dist > dest->dist && source->dist < -opp->dist)
2318 {
2319 copy = true;
2320 }
2321
2322 if (copy)
2323 {
2324 *(TPlane*)dest = *(TPlane*)source;
2325 }
2326
2327 return copy;
2328 unguard;
2329 }
2330
2331 //==========================================================================
2332 //
2333 // VRenderLevelShared::UpdateFakeFlats
2334 //
2335 // killough 3/7/98: Hack floor/ceiling heights for deep water etc.
2336 //
2337 // If player's view height is underneath fake floor, lower the
2338 // drawn ceiling to be just under the floor height, and replace
2339 // the drawn floor and ceiling textures, and light level, with
2340 // the control sector's.
2341 //
2342 // Similar for ceiling, only reflected.
2343 //
2344 // killough 4/11/98, 4/13/98: fix bugs, add 'back' parameter
2345 //
2346 //==========================================================================
2347
UpdateFakeFlats(sector_t * sec)2348 void VRenderLevelShared::UpdateFakeFlats(sector_t* sec)
2349 {
2350 guard(VRenderLevelShared::UpdateFakeFlats);
2351 const sector_t *s = sec->heightsec;
2352 sector_t *heightsec = r_viewleaf->sector->heightsec;
2353 bool underwater = /*r_fakingunderwater ||*/
2354 //(heightsec && vieworg.z <= heightsec->floor.GetPointZ(vieworg));
2355 (s && vieworg.z <= s->floor.GetPointZ(vieworg));
2356 bool doorunderwater = false;
2357 int diffTex = !!(s->SectorFlags & sector_t::SF_ClipFakePlanes);
2358
2359 // Replace sector being drawn with a copy to be hacked
2360 fakefloor_t* ff = sec->fakefloors;
2361 ff->floorplane = sec->floor;
2362 ff->ceilplane = sec->ceiling;
2363 ff->params = sec->params;
2364
2365 // Replace floor and ceiling height with control sector's heights.
2366 if (diffTex)
2367 {
2368 if (CopyPlaneIfValid(&ff->floorplane, &s->floor, &sec->ceiling))
2369 {
2370 ff->floorplane.pic = s->floor.pic;
2371 }
2372 else if (s->SectorFlags & sector_t::SF_FakeFloorOnly)
2373 {
2374 if (underwater)
2375 {
2376 // tempsec->ColourMap = s->ColourMap;
2377 ff->params.Fade = s->params.Fade;
2378 if (!(s->SectorFlags & sector_t::SF_NoFakeLight))
2379 {
2380 ff->params.lightlevel = s->params.lightlevel;
2381 ff->params.LightColour = s->params.LightColour;
2382
2383 /* if (floorlightlevel != NULL)
2384 {
2385 *floorlightlevel = GetFloorLight (s);
2386 }
2387
2388 if (ceilinglightlevel != NULL)
2389 {
2390 *ceilinglightlevel = GetFloorLight (s);
2391 }*/
2392 }
2393 return;
2394 }
2395 return;
2396 }
2397 }
2398 else
2399 {
2400 ff->floorplane.normal = s->floor.normal;
2401 ff->floorplane.dist = s->floor.dist;
2402 }
2403
2404 if (!(s->SectorFlags & sector_t::SF_FakeFloorOnly))
2405 {
2406 if (diffTex)
2407 {
2408 if (CopyPlaneIfValid(&ff->ceilplane, &s->ceiling, &sec->floor))
2409 {
2410 ff->ceilplane.pic = s->ceiling.pic;
2411 }
2412 }
2413 else
2414 {
2415 ff->ceilplane.normal = s->ceiling.normal;
2416 ff->ceilplane.dist = s->ceiling.dist;
2417 }
2418 }
2419
2420 // float refflorz = s->floor.GetPointZ(viewx, viewy);
2421 float refceilz = s->ceiling.GetPointZ(vieworg);
2422 // float orgflorz = sec->floor.GetPointZ(viewx, viewy);
2423 float orgceilz = sec->ceiling.GetPointZ(vieworg);
2424
2425 #if 0//1
2426 // [RH] Allow viewing underwater areas through doors/windows that
2427 // are underwater but not in a water sector themselves.
2428 // Only works if you cannot see the top surface of any deep water
2429 // sectors at the same time.
2430 if (back && !r_fakingunderwater && curline->frontsector->heightsec == NULL)
2431 {
2432 if (rw_frontcz1 <= s->floorplane.ZatPoint (curline->v1->x, curline->v1->y) &&
2433 rw_frontcz2 <= s->floorplane.ZatPoint (curline->v2->x, curline->v2->y))
2434 {
2435 // Check that the window is actually visible
2436 for (int z = WallSX1; z < WallSX2; ++z)
2437 {
2438 if (floorclip[z] > ceilingclip[z])
2439 {
2440 doorunderwater = true;
2441 r_fakingunderwater = true;
2442 break;
2443 }
2444 }
2445 }
2446 }
2447 #endif
2448
2449 if (underwater || doorunderwater)
2450 {
2451 ff->floorplane.normal = sec->floor.normal;
2452 ff->floorplane.dist = sec->floor.dist;
2453 ff->ceilplane.normal = -s->floor.normal;
2454 ff->ceilplane.dist = -s->floor.dist/* + 1*/;
2455 // ff->ColourMap = s->ColourMap;
2456 ff->params.Fade = s->params.Fade;
2457 }
2458
2459 // killough 11/98: prevent sudden light changes from non-water sectors:
2460 if ((underwater/* && !back*/) || doorunderwater)
2461 {
2462 // head-below-floor hack
2463 ff->floorplane.pic = diffTex ? sec->floor.pic : s->floor.pic;
2464 ff->floorplane.xoffs = s->floor.xoffs;
2465 ff->floorplane.yoffs = s->floor.yoffs;
2466 ff->floorplane.XScale = s->floor.XScale;
2467 ff->floorplane.YScale = s->floor.YScale;
2468 ff->floorplane.Angle = s->floor.Angle;
2469 ff->floorplane.BaseAngle = s->floor.BaseAngle;
2470 ff->floorplane.BaseYOffs = s->floor.BaseYOffs;
2471
2472 ff->ceilplane.normal = -s->floor.normal;
2473 ff->ceilplane.dist = -s->floor.dist/* + 1*/;
2474 if (s->ceiling.pic == skyflatnum)
2475 {
2476 ff->floorplane.normal = -ff->ceilplane.normal;
2477 ff->floorplane.dist = -ff->ceilplane.dist/* + 1*/;
2478 ff->ceilplane.pic = ff->floorplane.pic;
2479 ff->ceilplane.xoffs = ff->floorplane.xoffs;
2480 ff->ceilplane.yoffs = ff->floorplane.yoffs;
2481 ff->ceilplane.XScale = ff->floorplane.XScale;
2482 ff->ceilplane.YScale = ff->floorplane.YScale;
2483 ff->ceilplane.Angle = ff->floorplane.Angle;
2484 ff->ceilplane.BaseAngle = ff->floorplane.BaseAngle;
2485 ff->ceilplane.BaseYOffs = ff->floorplane.BaseYOffs;
2486 }
2487 else
2488 {
2489 ff->ceilplane.pic = diffTex ? s->floor.pic : s->ceiling.pic;
2490 ff->ceilplane.xoffs = s->ceiling.xoffs;
2491 ff->ceilplane.yoffs = s->ceiling.yoffs;
2492 ff->ceilplane.XScale = s->ceiling.XScale;
2493 ff->ceilplane.YScale = s->ceiling.YScale;
2494 ff->ceilplane.Angle = s->ceiling.Angle;
2495 ff->ceilplane.BaseAngle = s->ceiling.BaseAngle;
2496 ff->ceilplane.BaseYOffs = s->ceiling.BaseYOffs;
2497 }
2498
2499 if (!(s->SectorFlags & sector_t::SF_NoFakeLight))
2500 {
2501 ff->params.lightlevel = s->params.lightlevel;
2502 ff->params.LightColour = s->params.LightColour;
2503
2504 /* if (floorlightlevel != NULL)
2505 {
2506 *floorlightlevel = GetFloorLight (s);
2507 }
2508
2509 if (ceilinglightlevel != NULL)
2510 {
2511 *ceilinglightlevel = GetFloorLight (s);
2512 }*/
2513 }
2514 }
2515 else if (heightsec && orgceilz > refceilz &&
2516 !(s->SectorFlags & sector_t::SF_FakeFloorOnly) &&
2517 vieworg.z >= heightsec->ceiling.GetPointZ(vieworg))
2518 {
2519 // Above-ceiling hack
2520 ff->ceilplane.normal = s->ceiling.normal;
2521 ff->ceilplane.dist = s->ceiling.dist;
2522 ff->floorplane.normal = -s->ceiling.normal;
2523 ff->floorplane.dist = -s->ceiling.dist/* + 1*/;
2524 ff->params.Fade = s->params.Fade;
2525 // ff->params.ColourMap = s->params.ColourMap;
2526
2527 ff->ceilplane.pic = diffTex ? sec->ceiling.pic : s->ceiling.pic;
2528 ff->floorplane.pic = s->ceiling.pic;
2529 ff->floorplane.xoffs = ff->ceilplane.xoffs = s->ceiling.xoffs;
2530 ff->floorplane.yoffs = ff->ceilplane.yoffs = s->ceiling.yoffs;
2531 ff->floorplane.XScale = ff->ceilplane.XScale = s->ceiling.XScale;
2532 ff->floorplane.YScale = ff->ceilplane.YScale = s->ceiling.YScale;
2533 ff->floorplane.Angle = ff->ceilplane.Angle = s->ceiling.Angle;
2534 ff->floorplane.BaseAngle = ff->ceilplane.BaseAngle = s->ceiling.BaseAngle;
2535 ff->floorplane.BaseYOffs = ff->ceilplane.BaseYOffs = s->ceiling.BaseYOffs;
2536
2537 if (s->floor.pic != skyflatnum)
2538 {
2539 ff->ceilplane.normal = sec->ceiling.normal;
2540 ff->ceilplane.dist = sec->ceiling.dist;
2541 ff->floorplane.pic = s->floor.pic;
2542 ff->floorplane.xoffs = s->floor.xoffs;
2543 ff->floorplane.yoffs = s->floor.yoffs;
2544 ff->floorplane.XScale = s->floor.XScale;
2545 ff->floorplane.YScale = s->floor.YScale;
2546 ff->floorplane.Angle = s->floor.Angle;
2547 }
2548
2549 if (!(s->SectorFlags & sector_t::SF_NoFakeLight))
2550 {
2551 ff->params.lightlevel = s->params.lightlevel;
2552 ff->params.LightColour = s->params.LightColour;
2553
2554 /* if (floorlightlevel != NULL)
2555 {
2556 *floorlightlevel = GetFloorLight (s);
2557 }
2558
2559 if (ceilinglightlevel != NULL)
2560 {
2561 *ceilinglightlevel = GetCeilingLight (s);
2562 }*/
2563 }
2564 }
2565 unguard;
2566 }
2567
2568 //==========================================================================
2569 //
2570 // VRenderLevel::UpdateWorld
2571 //
2572 //==========================================================================
2573
UpdateWorld(const refdef_t * rd,const VViewClipper * Range)2574 void VRenderLevel::UpdateWorld(const refdef_t* rd, const VViewClipper* Range)
2575 {
2576 guard(VRenderLevel::UpdateWorld);
2577 float dummy_bbox[6] = {-99999, -99999, -99999, 99999, 99999, 99999};
2578
2579 ViewClip.ClearClipNodes(vieworg, Level);
2580 ViewClip.ClipInitFrustrumRange(viewangles, viewforward, viewright, viewup,
2581 rd->fovx, rd->fovy);
2582 if (Range)
2583 {
2584 // Range contains a valid range, so we must clip away holes in it.
2585 ViewClip.ClipToRanges(*Range);
2586 }
2587
2588 // Update fake sectors.
2589 for (int i = 0; i < Level->NumSectors; i++)
2590 {
2591 if (Level->Sectors[i].heightsec &&
2592 !(Level->Sectors[i].heightsec->SectorFlags & sector_t::SF_IgnoreHeightSec))
2593 {
2594 UpdateFakeFlats(&Level->Sectors[i]);
2595 }
2596 }
2597
2598 UpdateBSPNode(Level->NumNodes - 1, dummy_bbox); // head node is the last node output
2599 unguard;
2600 }
2601
2602 //==========================================================================
2603 //
2604 // VAdvancedRenderLevel::UpdateWorld
2605 //
2606 //==========================================================================
2607
UpdateWorld()2608 void VAdvancedRenderLevel::UpdateWorld()
2609 {
2610 guard(VAdvancedRenderLevel::UpdateWorld);
2611 float dummy_bbox[6] = {-99999, -99999, -99999, 99999, 99999, 99999};
2612
2613 // Update fake sectors.
2614 for (int i = 0; i < Level->NumSectors; i++)
2615 {
2616 if (Level->Sectors[i].heightsec &&
2617 !(Level->Sectors[i].heightsec->SectorFlags & sector_t::SF_IgnoreHeightSec))
2618 {
2619 UpdateFakeFlats(&Level->Sectors[i]);
2620 }
2621 }
2622
2623 UpdateBSPNode(Level->NumNodes - 1, dummy_bbox); // head node is the last node output
2624 unguard;
2625 }
2626
2627 //==========================================================================
2628 //
2629 // VRenderLevelShared::SetupFakeFloors
2630 //
2631 //==========================================================================
2632
SetupFakeFloors(sector_t * Sec)2633 void VRenderLevelShared::SetupFakeFloors(sector_t* Sec)
2634 {
2635 guard(VRenderLevelShared::SetupFakeFloors);
2636 sector_t* HeightSec = Sec->heightsec;
2637
2638 if (HeightSec->SectorFlags & sector_t::SF_IgnoreHeightSec)
2639 {
2640 return;
2641 }
2642
2643 Sec->fakefloors = new fakefloor_t;
2644 memset(Sec->fakefloors, 0, sizeof(fakefloor_t));
2645 Sec->fakefloors->floorplane = Sec->floor;
2646 Sec->fakefloors->ceilplane = Sec->ceiling;
2647 Sec->fakefloors->params = Sec->params;
2648
2649 Sec->topregion->params = &Sec->fakefloors->params;
2650 unguard;
2651 }
2652
2653 //==========================================================================
2654 //
2655 // VRenderLevelShared::FreeSurfaces
2656 //
2657 //==========================================================================
2658
FreeSurfaces(surface_t * InSurf)2659 void VRenderLevelShared::FreeSurfaces(surface_t* InSurf)
2660 {
2661 guard(VRenderLevelShared::FreeSurfaces);
2662 surface_t* next;
2663 for (surface_t* s = InSurf; s; s = next)
2664 {
2665 if (s->CacheSurf)
2666 {
2667 FreeSurfCache(s->CacheSurf);
2668 }
2669 if (s->lightmap)
2670 {
2671 Z_Free(s->lightmap);
2672 }
2673 if (s->lightmap_rgb)
2674 {
2675 Z_Free(s->lightmap_rgb);
2676 }
2677 next = s->next;
2678 Z_Free(s);
2679 }
2680 unguard;
2681 }
2682
2683 //==========================================================================
2684 //
2685 // VRenderLevelShared::FreeSegParts
2686 //
2687 //==========================================================================
2688
FreeSegParts(segpart_t * ASP)2689 void VRenderLevelShared::FreeSegParts(segpart_t* ASP)
2690 {
2691 guard(VRenderLevelShared::FreeSegParts);
2692 for (segpart_t* sp = ASP; sp; sp = sp->next)
2693 {
2694 FreeWSurfs(sp->surfs);
2695 }
2696 unguard;
2697 }
2698