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