1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: r_main.cpp 4355 2010-12-24 01:29:15Z firebrand_kh $
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 //**	Rendering main loop and setup functions, utility functions (BSP,
27 //**  geometry, trigonometry). See tables.c, too.
28 //**
29 //**************************************************************************
30 
31 // HEADER FILES ------------------------------------------------------------
32 
33 #include "gamedefs.h"
34 #include "r_local.h"
35 
36 // MACROS ------------------------------------------------------------------
37 
38 // TYPES -------------------------------------------------------------------
39 
40 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
41 
42 void R_FreeSkyboxData();
43 
44 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
45 
46 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
47 
48 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
49 
50 // PUBLIC DATA DEFINITIONS -------------------------------------------------
51 
52 int						screenblocks = 0;
53 
54 TVec					vieworg;
55 TVec					viewforward;
56 TVec					viewright;
57 TVec					viewup;
58 TAVec					viewangles;
59 
60 TClipPlane				view_clipplanes[5];
61 
62 int						r_visframecount;
63 
64 VCvarI					r_fog("r_fog", "0");
65 VCvarI					r_fog_test("r_fog_test", "0");
66 VCvarF					r_fog_r("r_fog_r", "0.5");
67 VCvarF					r_fog_g("r_fog_g", "0.5");
68 VCvarF					r_fog_b("r_fog_b", "0.5");
69 VCvarF					r_fog_start("r_fog_start", "1.0");
70 VCvarF					r_fog_end("r_fog_end", "2048.0");
71 VCvarF					r_fog_density("r_fog_density", "0.5");
72 
73 VCvarI					aspect_ratio("r_aspect_ratio", "1", CVAR_Archive);
74 VCvarI					r_interpolate_frames("r_interpolate_frames", "1", CVAR_Archive);
75 VCvarI					r_vsync("r_vsync", "1", CVAR_Archive);
76 VCvarI					r_fade_light("r_fade_light", "0", CVAR_Archive);
77 VCvarF					r_fade_factor("r_fade_factor", "4.0", CVAR_Archive);
78 VCvarF					r_sky_bright_factor("r_sky_bright_factor", "1.0", CVAR_Archive);
79 
80 VDrawer					*Drawer;
81 
82 refdef_t				refdef;
83 
84 float					PixelAspect;
85 
86 bool					MirrorFlip;
87 bool					MirrorClip;
88 
89 // PRIVATE DATA DEFINITIONS ------------------------------------------------
90 
91 static FDrawerDesc		*DrawerList[DRAWER_MAX];
92 
93 VCvarI					screen_size("screen_size", "10", CVAR_Archive);
94 bool					set_resolutioon_needed = true;
95 
96 // Angles in the SCREENWIDTH wide window.
97 VCvarF					fov("fov", "90");
98 
99 TVec					clip_base[4];
100 
101 //
102 //	Translation tables
103 //
104 VTextureTranslation*	PlayerTranslations[MAXPLAYERS + 1];
105 static TArray<VTextureTranslation*>	CachedTranslations;
106 
107 // if true, load all graphics at start
108 VCvarI					precache("precache", "1", CVAR_Archive);
109 
110 static VCvarI			_driver("_driver", "0", CVAR_Rom);
111 
112 static VCvarI			r_level_renderer("r_level_renderer", "0", CVAR_Archive);
113 
114 // CODE --------------------------------------------------------------------
115 
116 //==========================================================================
117 //
118 //  FDrawerDesc::FDrawerDesc
119 //
120 //==========================================================================
121 
FDrawerDesc(int Type,const char * AName,const char * ADescription,const char * ACmdLineArg,VDrawer * (* ACreator)())122 FDrawerDesc::FDrawerDesc(int Type, const char* AName, const char* ADescription,
123 	const char* ACmdLineArg, VDrawer* (*ACreator)())
124 : Name(AName)
125 , Description(ADescription)
126 , CmdLineArg(ACmdLineArg)
127 , Creator(ACreator)
128 {
129 	guard(FDrawerDesc::FDrawerDesc);
130 	DrawerList[Type] = this;
131 	unguard
132 }
133 
134 //==========================================================================
135 //
136 //  R_Init
137 //
138 //==========================================================================
139 
R_Init()140 void R_Init()
141 {
142 	guard(R_Init);
143 	R_InitSkyBoxes();
144 	R_InitModels();
145 
146 	for (int i = 0; i < 256; i++)
147 	{
148 		light_remap[i] = byte(i * i / 255);
149 	}
150 	unguard;
151 }
152 
153 //==========================================================================
154 //
155 //  R_Start
156 //
157 //==========================================================================
158 
R_Start(VLevel * ALevel)159 void R_Start(VLevel* ALevel)
160 {
161 	guard(R_Start);
162 	switch (r_level_renderer)
163 	{
164 	case 1:
165 		ALevel->RenderData = new VRenderLevel(ALevel);
166 		break;
167 
168 	case 2:
169 		ALevel->RenderData = new VAdvancedRenderLevel(ALevel);
170 		break;
171 
172 	default:
173 		if (Drawer->SupportsAdvancedRendering())
174 		{
175 			ALevel->RenderData = new VAdvancedRenderLevel(ALevel);
176 		}
177 		else
178 		{
179 			ALevel->RenderData = new VRenderLevel(ALevel);
180 		}
181 		break;
182 	}
183 	unguard;
184 }
185 
186 //==========================================================================
187 //
188 //	VRenderLevelShared::VRenderLevelShared
189 //
190 //==========================================================================
191 
VRenderLevelShared(VLevel * ALevel)192 VRenderLevelShared::VRenderLevelShared(VLevel* ALevel)
193 : Level(ALevel)
194 , ViewEnt(NULL)
195 , MirrorLevel(0)
196 , PortalLevel(0)
197 , VisSize(0)
198 , BspVis(NULL)
199 , r_viewleaf(NULL)
200 , r_oldviewleaf(NULL)
201 , old_fov(90.0)
202 , prev_aspect_ratio(0)
203 , ExtraLight(0)
204 , FixedLight(0)
205 , Particles(0)
206 , ActiveParticles(0)
207 , FreeParticles(0)
208 , CurrentSky1Texture(-1)
209 , CurrentSky2Texture(-1)
210 , CurrentDoubleSky(false)
211 , CurrentLightning(false)
212 , trans_sprites(MainTransSprites)
213 , free_wsurfs(NULL)
214 , AllocatedWSurfBlocks(NULL)
215 , AllocatedSubRegions(NULL)
216 , AllocatedDrawSegs(NULL)
217 , AllocatedSegParts(NULL)
218 , cacheframecount(0)
219 {
220 	guard(VRenderLevelShared::VRenderLevelShared);
221 	memset(MainTransSprites, 0, sizeof(MainTransSprites));
222 
223 	memset(light_block, 0, sizeof(light_block));
224 	memset(block_changed, 0, sizeof(block_changed));
225 	memset(light_chain, 0, sizeof(light_chain));
226 	memset(add_block, 0, sizeof(add_block));
227 	memset(add_changed, 0, sizeof(add_changed));
228 	memset(add_chain, 0, sizeof(add_chain));
229 	SimpleSurfsHead = NULL;
230 	SimpleSurfsTail = NULL;
231 	SkyPortalsHead = NULL;
232 	SkyPortalsTail = NULL;
233 	HorizonPortalsHead = NULL;
234 	HorizonPortalsTail = NULL;
235 	PortalDepth = 0;
236 
237 	VisSize = (Level->NumSubsectors + 7) >> 3;
238 	BspVis = new vuint8[VisSize];
239 
240 	InitParticles();
241 	ClearParticles();
242 
243 	screenblocks = 0;
244 
245 	// preload graphics
246 	if (precache)
247 	{
248 		PrecacheLevel();
249 	}
250 	unguard;
251 }
252 
253 //==========================================================================
254 //
255 //	VRenderLevel::VRenderLevel
256 //
257 //==========================================================================
258 
VRenderLevel(VLevel * ALevel)259 VRenderLevel::VRenderLevel(VLevel* ALevel)
260 : VRenderLevelShared(ALevel)
261 , c_subdivides(0)
262 , c_seg_div(0)
263 , freeblocks(NULL)
264 {
265 	guard(VRenderLevel::VRenderLevel);
266 	NeedsInfiniteFarClip = false;
267 
268 	memset(cacheblocks, 0, sizeof(cacheblocks));
269 	memset(blockbuf, 0, sizeof(blockbuf));
270 
271 	FlushCaches();
272 
273 	memset(DLights, 0, sizeof(DLights));
274 	unguard;
275 }
276 
277 //==========================================================================
278 //
279 //	VAdvancedRenderLevel::VAdvancedRenderLevel
280 //
281 //==========================================================================
282 
VAdvancedRenderLevel(VLevel * ALevel)283 VAdvancedRenderLevel::VAdvancedRenderLevel(VLevel* ALevel)
284 : VRenderLevelShared(ALevel)
285 , LightVis(NULL)
286 {
287 	guard(VAdvancedRenderLevel::VAdvancedRenderLevel);
288 	NeedsInfiniteFarClip = true;
289 
290 	memset(DLights, 0, sizeof(DLights));
291 
292 	LightVis = new vuint8[VisSize];
293 	LightBspVis = new vuint8[VisSize];
294 	unguard;
295 }
296 
297 //==========================================================================
298 //
299 //	VRenderLevelShared::~VRenderLevelShared
300 //
301 //==========================================================================
302 
~VRenderLevelShared()303 VRenderLevelShared::~VRenderLevelShared()
304 {
305 	guard(VRenderLevelShared::~VRenderLevelShared);
306 	//	Free fake floor data.
307 	for (int i = 0; i < Level->NumSectors; i++)
308 	{
309 		if (Level->Sectors[i].fakefloors)
310 		{
311 			delete Level->Sectors[i].fakefloors;
312 			Level->Sectors[i].fakefloors = NULL;
313 		}
314 	}
315 
316 	for (int i = 0; i < Level->NumSubsectors; i++)
317 	{
318 		for (subregion_t* r = Level->Subsectors[i].regions; r; r = r->next)
319 		{
320 			FreeSurfaces(r->floor->surfs);
321 			delete r->floor;
322 			r->floor = NULL;
323 			FreeSurfaces(r->ceil->surfs);
324 			delete r->ceil;
325 			r->ceil = NULL;
326 		}
327 	}
328 
329 	//	Free seg parts.
330 	for (int i = 0; i < Level->NumSegs; i++)
331 	{
332 		for (drawseg_t* ds = Level->Segs[i].drawsegs; ds; ds = ds->next)
333 		{
334 			FreeSegParts(ds->top);
335 			FreeSegParts(ds->mid);
336 			FreeSegParts(ds->bot);
337 			FreeSegParts(ds->topsky);
338 			FreeSegParts(ds->extra);
339 			if (ds->HorizonTop)
340 			{
341 				Z_Free(ds->HorizonTop);
342 			}
343 			if (ds->HorizonBot)
344 			{
345 				Z_Free(ds->HorizonBot);
346 			}
347 		}
348 	}
349 	//	Free allocated wall surface blocks.
350 	for (void* Block = AllocatedWSurfBlocks; Block;)
351 	{
352 		void* Next = *(void**)Block;
353 		Z_Free(Block);
354 		Block = Next;
355 	}
356 	AllocatedWSurfBlocks = NULL;
357 
358 	//	Free big blocks.
359 	delete[] AllocatedSubRegions;
360 	AllocatedSubRegions = NULL;
361 	delete[] AllocatedDrawSegs;
362 	AllocatedDrawSegs = NULL;
363 	delete[] AllocatedSegParts;
364 	AllocatedSegParts = NULL;
365 
366 	delete[] Particles;
367 	Particles = NULL;
368 	delete[] BspVis;
369 	BspVis = NULL;
370 
371 	for (int i = 0; i < SideSkies.Num(); i++)
372 	{
373 		delete SideSkies[i];
374 		SideSkies[i] = NULL;
375 	}
376 	unguard;
377 }
378 
379 //==========================================================================
380 //
381 //	VAdvancedRenderLevel::~VAdvancedRenderLevel
382 //
383 //==========================================================================
384 
~VAdvancedRenderLevel()385 VAdvancedRenderLevel::~VAdvancedRenderLevel()
386 {
387 	guard(VAdvancedRenderLevel::~VAdvancedRenderLevel);
388 	delete[] LightVis;
389 	LightVis = NULL;
390 	delete[] LightBspVis;
391 	LightBspVis = NULL;
392 	unguard;
393 }
394 
395 //==========================================================================
396 //
397 // 	R_SetViewSize
398 //
399 // 	Do not really change anything here, because it might be in the middle
400 // of a refresh. The change will take effect next refresh.
401 //
402 //==========================================================================
403 
R_SetViewSize(int blocks)404 void R_SetViewSize(int blocks)
405 {
406 	guard(R_SetViewSize);
407 	if (blocks > 2)
408 	{
409 		screen_size = blocks;
410 	}
411 	set_resolutioon_needed = true;
412 	unguard;
413 }
414 
415 //==========================================================================
416 //
417 //  COMMAND SizeDown
418 //
419 //==========================================================================
420 
COMMAND(SizeDown)421 COMMAND(SizeDown)
422 {
423 	R_SetViewSize(screenblocks - 1);
424 	GAudio->PlaySound(GSoundManager->GetSoundID("menu/change"),
425 		TVec(0, 0, 0), TVec(0, 0, 0), 0, 0, 1, 0, false);
426 }
427 
428 //==========================================================================
429 //
430 //  COMMAND SizeUp
431 //
432 //==========================================================================
433 
COMMAND(SizeUp)434 COMMAND(SizeUp)
435 {
436 	R_SetViewSize(screenblocks + 1);
437 	GAudio->PlaySound(GSoundManager->GetSoundID("menu/change"),
438 		TVec(0, 0, 0), TVec(0, 0, 0), 0, 0, 1, 0, false);
439 }
440 
441 //==========================================================================
442 //
443 //	VRenderLevelShared::ExecuteSetViewSize
444 //
445 //==========================================================================
446 
ExecuteSetViewSize()447 void VRenderLevelShared::ExecuteSetViewSize()
448 {
449 	guard(VRenderLevelShared::ExecuteSetViewSize);
450 	set_resolutioon_needed = false;
451 	if (screen_size < 3)
452 	{
453 		screen_size = 3;
454 	}
455 	if (screen_size > 11)
456 	{
457 		screen_size = 11;
458 	}
459 	screenblocks = screen_size;
460 
461 	if (fov < 5.0)
462 	{
463 		fov = 5.0;
464 	}
465 	if (fov > 175.0)
466 	{
467 		fov = 175.0;
468 	}
469 	old_fov = fov;
470 
471 	if (screenblocks > 10)
472 	{
473 		refdef.width = ScreenWidth;
474 		refdef.height = ScreenHeight;
475 		refdef.y = 0;
476 	}
477 	else if (GGameInfo->NetMode == NM_TitleMap)
478 	{
479 		//	No status bar for titlemap.
480 		refdef.width = screenblocks * ScreenWidth / 10;
481 		refdef.height = (screenblocks * ScreenHeight / 10);
482 		refdef.y = (ScreenHeight - refdef.height) >> 1;
483 	}
484 	else
485 	{
486 		refdef.width = screenblocks * ScreenWidth / 10;
487 		refdef.height = (screenblocks * (ScreenHeight - SB_REALHEIGHT) / 10);
488 		refdef.y = (ScreenHeight - SB_REALHEIGHT - refdef.height) >> 1;
489 	}
490 	refdef.x = (ScreenWidth - refdef.width) >> 1;
491 
492 	if (aspect_ratio == 0)
493 	{
494 		// Original aspect ratio
495 		PixelAspect = ((float)ScreenHeight * 320.0) / ((float)ScreenWidth * 200.0);
496 	}
497 	else if (aspect_ratio == 1)
498 	{
499 		// 4:3 aspect ratio
500 		PixelAspect = ((float)ScreenHeight * 4.0) / ((float)ScreenWidth * 3.0);
501 	}
502 	else if (aspect_ratio == 2)
503 	{
504 		// 16:9 aspect ratio
505 		PixelAspect = ((float)ScreenHeight * 16.0) / ((float)ScreenWidth * 9.0);
506 	}
507 	else
508 	{
509 		// 16:10 aspect ratio
510 		PixelAspect = ((float)ScreenHeight * 16.0) / ((float)ScreenWidth * 10.0);
511 	}
512 	prev_aspect_ratio = aspect_ratio;
513 
514 	refdef.fovx = tan(DEG2RAD(fov) / 2);
515 	refdef.fovy = refdef.fovx * refdef.height / refdef.width / PixelAspect;
516 
517 	// left side clip
518 	clip_base[0] = Normalise(TVec(1, 1.0 / refdef.fovx, 0));
519 
520 	// right side clip
521 	clip_base[1] = Normalise(TVec(1, -1.0 / refdef.fovx, 0));
522 
523 	// top side clip
524 	clip_base[2] = Normalise(TVec(1, 0, -1.0 / refdef.fovy));
525 
526 	// bottom side clip
527 	clip_base[3] = Normalise(TVec(1, 0, 1.0 / refdef.fovy));
528 
529 	refdef.drawworld = true;
530 	unguard;
531 }
532 
533 //==========================================================================
534 //
535 //	R_DrawViewBorder
536 //
537 //==========================================================================
538 
R_DrawViewBorder()539 void R_DrawViewBorder()
540 {
541 	guard(R_DrawViewBorder);
542 	if (GGameInfo->NetMode == NM_TitleMap)
543 	{
544 		GClGame->eventDrawViewBorder(320 - screenblocks * 32,
545 			(480 - screenblocks * 480 / 10) / 2,
546 			screenblocks * 64, screenblocks * 480 / 10);
547 	}
548 	else
549 	{
550 		GClGame->eventDrawViewBorder(320 - screenblocks * 32,
551 			(480 - sb_height - screenblocks * (480 - sb_height) / 10) / 2,
552 			screenblocks * 64, screenblocks * (480 - sb_height) / 10);
553 	}
554 	unguard;
555 }
556 
557 //==========================================================================
558 //
559 //	VRenderLevelShared::TransformFrustum
560 //
561 //==========================================================================
562 
TransformFrustum()563 void VRenderLevelShared::TransformFrustum()
564 {
565 	guard(VRenderLevelShared::TransformFrustum);
566 	for (int i = 0; i < 4; i++)
567 	{
568 		TVec &v = clip_base[i];
569 		TVec v2;
570 
571 		v2.x = v.y * viewright.x + v.z * viewup.x + v.x * viewforward.x;
572 		v2.y = v.y * viewright.y + v.z * viewup.y + v.x * viewforward.y;
573 		v2.z = v.y * viewright.z + v.z * viewup.z + v.x * viewforward.z;
574 
575 		view_clipplanes[i].Set(v2, DotProduct(vieworg, v2));
576 
577 		view_clipplanes[i].next = i == 3 ? NULL : &view_clipplanes[i + 1];
578 		view_clipplanes[i].clipflag = 1 << i;
579 	}
580 	unguard;
581 }
582 
583 //==========================================================================
584 //
585 //	VRenderLevelShared::SetupFrame
586 //
587 //==========================================================================
588 
589 VCvarI			r_chasecam("r_chasecam", "0", CVAR_Archive);
590 VCvarF			r_chase_dist("r_chase_dist", "32.0", CVAR_Archive);
591 VCvarF			r_chase_up("r_chase_up", "128.0", CVAR_Archive);
592 VCvarF			r_chase_right("r_chase_right", "0", CVAR_Archive);
593 VCvarI			r_chase_front("r_chase_front", "0", CVAR_Archive);
594 
SetupFrame()595 void VRenderLevelShared::SetupFrame()
596 {
597 	guard(VRenderLevelShared::SetupFrame);
598 	// change the view size if needed
599 	if (screen_size != screenblocks || !screenblocks ||
600 		set_resolutioon_needed || old_fov != fov ||
601 		aspect_ratio != prev_aspect_ratio)
602 	{
603 		ExecuteSetViewSize();
604 	}
605 
606 	ViewEnt = cl->Camera;
607 	viewangles = cl->ViewAngles;
608 	if (r_chasecam && r_chase_front)
609 	{
610 		//	This is used to see how weapon looks in player's hands
611 		viewangles.yaw = AngleMod(viewangles.yaw + 180);
612 		viewangles.pitch = -viewangles.pitch;
613 	}
614 	AngleVectors(viewangles, viewforward, viewright, viewup);
615 
616 	if (r_chasecam && cl->MO == cl->Camera)
617 	{
618 		vieworg = cl->MO->Origin + TVec(0.0, 0.0, 32.0)
619 			- r_chase_dist * viewforward + r_chase_up * viewup
620 			+ r_chase_right * viewright;
621 	}
622 	else
623 	{
624 		vieworg = cl->ViewOrg;
625 	}
626 
627 	ExtraLight = ViewEnt->Player ? ViewEnt->Player->ExtraLight * 8 : 0;
628 	if (cl->Camera == cl->MO)
629 	{
630 		ColourMap = CM_Default;
631 		if (cl->FixedColourmap == INVERSECOLOURMAP)
632 		{
633 			ColourMap = CM_Inverse;
634 			FixedLight = 255;
635 		}
636 		else if (cl->FixedColourmap == GOLDCOLOURMAP)
637 		{
638 			ColourMap = CM_Gold;
639 			FixedLight = 255;
640 		}
641 		else if (cl->FixedColourmap == REDCOLOURMAP)
642 		{
643 			ColourMap = CM_Red;
644 			FixedLight = 255;
645 		}
646 		else if (cl->FixedColourmap == GREENCOLOURMAP)
647 		{
648 			ColourMap = CM_Green;
649 			FixedLight = 255;
650 		}
651 		else if (cl->FixedColourmap >= NUMCOLOURMAPS)
652 		{
653 			FixedLight = 255;
654 		}
655 		else if (cl->FixedColourmap)
656 		{
657 			FixedLight = 255 - (cl->FixedColourmap << 3);
658 		}
659 		else
660 		{
661 			FixedLight = 0;
662 		}
663 	}
664 	else
665 	{
666 		FixedLight = 0;
667 		ColourMap = 0;
668 	}
669 	//	Inverse colourmap flash effect.
670 	if (cl->ExtraLight == 255)
671 	{
672 		ExtraLight = 0;
673 		ColourMap = CM_Inverse;
674 		FixedLight = 255;
675 	}
676 
677 	Drawer->SetupView(this, &refdef);
678 	cacheframecount++;
679 	PortalDepth = 0;
680 	unguard;
681 }
682 
683 //==========================================================================
684 //
685 //	VRenderLevelShared::SetupCameraFrame
686 //
687 //==========================================================================
688 
SetupCameraFrame(VEntity * Camera,VTexture * Tex,int FOV,refdef_t * rd)689 void VRenderLevelShared::SetupCameraFrame(VEntity* Camera, VTexture* Tex,
690 	int FOV, refdef_t* rd)
691 {
692 	guard(VRenderLevelShared::SetupCameraFrame);
693 	rd->width = Tex->GetWidth();
694 	rd->height = Tex->GetHeight();
695 	rd->y = 0;
696 	rd->x = 0;
697 
698 	if (aspect_ratio == 0)
699 	{
700 		PixelAspect = ((float)rd->height * 320.0) / ((float)rd->width * 200.0);
701 	}
702 	else if (aspect_ratio == 1)
703 	{
704 		PixelAspect = ((float)rd->height * 4.0) / ((float)rd->width * 3.0);
705 	}
706 	else if (aspect_ratio == 2)
707 	{
708 		PixelAspect = ((float)rd->height * 16.0) / ((float)rd->width * 9.0);
709 	}
710 	else if (aspect_ratio > 2)
711 	{
712 		PixelAspect = ((float)rd->height * 16.0) / ((float)rd->width * 10.0);
713 	}
714 
715 	rd->fovx = tan(DEG2RAD(FOV) / 2);
716 	rd->fovy = rd->fovx * rd->height / rd->width / PixelAspect;
717 
718 	// left side clip
719 	clip_base[0] = Normalise(TVec(1, 1.0 / rd->fovx, 0));
720 
721 	// right side clip
722 	clip_base[1] = Normalise(TVec(1, -1.0 / rd->fovx, 0));
723 
724 	// top side clip
725 	clip_base[2] = Normalise(TVec(1, 0, -1.0 / rd->fovy));
726 
727 	// bottom side clip
728 	clip_base[3] = Normalise(TVec(1, 0, 1.0 / rd->fovy));
729 
730 	rd->drawworld = true;
731 
732 	ViewEnt = Camera;
733 	viewangles = Camera->Angles;
734 	AngleVectors(viewangles, viewforward, viewright, viewup);
735 
736 	vieworg = Camera->Origin;
737 
738 	ExtraLight = 0;
739 	FixedLight = 0;
740 	ColourMap = 0;
741 
742 	Drawer->SetupView(this, rd);
743 	cacheframecount++;
744 	PortalDepth = 0;
745 	set_resolutioon_needed = true;
746 	unguard;
747 }
748 
749 //==========================================================================
750 //
751 //	VRenderLevelShared::MarkLeaves
752 //
753 //==========================================================================
754 
MarkLeaves()755 void VRenderLevelShared::MarkLeaves()
756 {
757 	guard(VRenderLevelShared::MarkLeaves);
758 	byte	*vis;
759 	node_t	*node;
760 	int		i;
761 
762 	if (r_oldviewleaf == r_viewleaf)
763 		return;
764 
765 	r_visframecount++;
766 	r_oldviewleaf = r_viewleaf;
767 
768 	vis = Level->LeafPVS(r_viewleaf);
769 
770 	for (i = 0; i < Level->NumSubsectors; i++)
771 	{
772 		if (vis[i >> 3] & (1 << (i & 7)))
773 		{
774 			subsector_t *sub = &Level->Subsectors[i];
775 			sub->VisFrame = r_visframecount;
776 			node = sub->parent;
777 			while (node)
778 			{
779 				if (node->VisFrame == r_visframecount)
780 					break;
781 				node->VisFrame = r_visframecount;
782 				node = node->parent;
783 			}
784 		}
785 	}
786 	unguard;
787 }
788 
789 //==========================================================================
790 //
791 //  VRenderLevel::RenderScene
792 //
793 //==========================================================================
794 
RenderScene(const refdef_t * RD,const VViewClipper * Range)795 void VRenderLevel::RenderScene(const refdef_t* RD, const VViewClipper* Range)
796 {
797 	guard(VRenderLevel::RenderScene);
798 	r_viewleaf = Level->PointInSubsector(vieworg);
799 
800 	TransformFrustum();
801 
802 	Drawer->SetupViewOrg();
803 
804 	MarkLeaves();
805 
806 	UpdateWorld(RD, Range);
807 
808 	RenderWorld(RD, Range);
809 
810 	RenderMobjs(RPASS_Normal);
811 
812 	DrawParticles();
813 
814 	DrawTranslucentPolys();
815 	unguard;
816 }
817 
818 //==========================================================================
819 //
820 //  VAdvancedRenderLevel::RenderScene
821 //
822 //==========================================================================
823 
RenderScene(const refdef_t * RD,const VViewClipper * Range)824 void VAdvancedRenderLevel::RenderScene(const refdef_t* RD, const VViewClipper* Range)
825 {
826 	guard(VAdvancedRenderLevel::RenderScene);
827 	if (!Drawer->SupportsAdvancedRendering())
828 	{
829 		Host_Error("Advanced rendering not supported by graphics card");
830 	}
831 
832 	r_viewleaf = Level->PointInSubsector(vieworg);
833 
834 	TransformFrustum();
835 
836 	Drawer->SetupViewOrg();
837 
838 	MarkLeaves();
839 
840 	UpdateWorld();
841 
842 	RenderWorld(RD, Range);
843 	RenderMobjsAmbient();
844 
845 	Drawer->BeginShadowVolumesPass();
846 	if (!FixedLight && r_dynamic)
847 	{
848 		dlight_t* l = DLights;
849 		for (int i = 0; i < MAX_DLIGHTS; i++, l++)
850 		{
851 			if (l->die < Level->Time || !l->radius)
852 			{
853 				continue;
854 			}
855 			RenderLightShadows(RD, Range, l->origin, l->radius, l->colour);
856 		}
857 	}
858 	if (!FixedLight && r_static_lights)
859 	{
860 		for (int i = 0; i < Lights.Num(); i++)
861 		{
862 			if (!Lights[i].radius)
863 			{
864 				continue;
865 			}
866 			RenderLightShadows(RD, Range, Lights[i].origin, Lights[i].radius, Lights[i].colour);
867 		}
868 	}
869 
870 	Drawer->DrawWorldTexturesPass();
871 	RenderMobjsTextures();
872 
873 	Drawer->DrawWorldFogPass();
874 	RenderMobjsFog();
875 	Drawer->EndFogPass();
876 
877 	RenderMobjs(RPASS_NonShadow);
878 
879 	DrawParticles();
880 
881 	DrawTranslucentPolys();
882 	unguard;
883 }
884 
885 //==========================================================================
886 //
887 //  R_RenderPlayerView
888 //
889 //==========================================================================
890 
R_RenderPlayerView()891 void R_RenderPlayerView()
892 {
893 	guard(R_RenderPlayerView);
894 	GClLevel->RenderData->RenderPlayerView();
895 	unguard;
896 }
897 
898 //==========================================================================
899 //
900 //  VRenderLevelShared::RenderPlayerView
901 //
902 //==========================================================================
903 
RenderPlayerView()904 void VRenderLevelShared::RenderPlayerView()
905 {
906 	guard(VRenderLevelShared::RenderPlayerView);
907 	if (!Level->LevelInfo)
908 	{
909 		return;
910 	}
911 
912 	GTextureManager.Time = Level->Time;
913 
914 	BuildPlayerTranslations();
915 
916 	AnimateSky(host_frametime);
917 
918 	UpdateParticles(host_frametime);
919 
920 	PushDlights();
921 
922 	//	Update camera textures that were visible in last frame.
923 	for (int i = 0; i < Level->CameraTextures.Num(); i++)
924 	{
925 		UpdateCameraTexture(Level->CameraTextures[i].Camera,
926 			Level->CameraTextures[i].TexNum, Level->CameraTextures[i].FOV);
927 	}
928 
929 	SetupFrame();
930 
931 	RenderScene(&refdef, NULL);
932 
933 	// draw the psprites on top of everything
934 	if (fov <= 90.0 && cl->MO == cl->Camera &&
935 		GGameInfo->NetMode != NM_TitleMap)
936 	{
937 		DrawPlayerSprites();
938 	}
939 
940 	Drawer->EndView();
941 
942 	// Draw croshair
943 	if (cl->MO == cl->Camera && GGameInfo->NetMode != NM_TitleMap)
944 	{
945 		DrawCroshair();
946 	}
947 	unguard;
948 }
949 
950 //==========================================================================
951 //
952 //	VRenderLevelShared::UpdateCameraTexture
953 //
954 //==========================================================================
955 
UpdateCameraTexture(VEntity * Camera,int TexNum,int FOV)956 void VRenderLevelShared::UpdateCameraTexture(VEntity* Camera, int TexNum,
957 	int FOV)
958 {
959 	guard(VRenderLevelShared::UpdateCameraTexture);
960 	if (!Camera)
961 	{
962 		return;
963 	}
964 
965 	if (!GTextureManager[TexNum]->bIsCameraTexture)
966 	{
967 		return;
968 	}
969 	VCameraTexture* Tex = (VCameraTexture*)GTextureManager[TexNum];
970 	if (!Tex->bNeedsUpdate)
971 	{
972 		return;
973 	}
974 
975 	refdef_t		CameraRefDef;
976 	CameraRefDef.DrawCamera = true;
977 
978 	SetupCameraFrame(Camera, Tex, FOV, &CameraRefDef);
979 
980 	RenderScene(&CameraRefDef, NULL);
981 
982 	Drawer->EndView();
983 
984 	Tex->CopyImage();
985 	unguard;
986 }
987 
988 //==========================================================================
989 //
990 //	VRenderLevelShared::GetFade
991 //
992 //==========================================================================
993 
GetFade(sec_region_t * Reg)994 vuint32 VRenderLevelShared::GetFade(sec_region_t* Reg)
995 {
996 	guard(VRenderLevelShared::GetFade);
997 	if (r_fog_test)
998 	{
999 		return 0xff000000 | (int(255 * r_fog_r) << 16) |
1000 			(int(255 * r_fog_g) << 8) | int(255 * r_fog_b);
1001 	}
1002 	if (Reg->params->Fade)
1003 	{
1004 		return Reg->params->Fade;
1005 	}
1006 	if (Level->LevelInfo->OutsideFog && Reg->ceiling->pic == skyflatnum)
1007 	{
1008 		return Level->LevelInfo->OutsideFog;
1009 	}
1010 	if (Level->LevelInfo->Fade)
1011 	{
1012 		return Level->LevelInfo->Fade;
1013 	}
1014 	if (Level->LevelInfo->FadeTable == NAME_fogmap)
1015 	{
1016 		return 0xff7f7f7f;
1017 	}
1018 	if (r_fade_light)
1019 	{
1020 		// Simulate light fading using dark fog
1021 		return FADE_LIGHT;
1022 	}
1023 	else
1024 	{
1025 		return 0;
1026 	}
1027 	unguard;
1028 }
1029 
1030 //==========================================================================
1031 //
1032 //	R_DrawPic
1033 //
1034 //==========================================================================
1035 
R_DrawPic(int x,int y,int handle,float Alpha)1036 void R_DrawPic(int x, int y, int handle, float Alpha)
1037 {
1038 	guard(R_DrawPic);
1039 	if (handle < 0)
1040 	{
1041 		return;
1042 	}
1043 
1044 	VTexture* Tex = GTextureManager(handle);
1045 	x -= Tex->GetScaledSOffset();
1046 	y -= Tex->GetScaledTOffset();
1047 	Drawer->DrawPic(fScaleX * x, fScaleY * y,
1048 		fScaleX * (x + Tex->GetScaledWidth()), fScaleY * (y + Tex->GetScaledHeight()),
1049 		0, 0, Tex->GetWidth(), Tex->GetHeight(), Tex, NULL, Alpha);
1050 	unguard;
1051 }
1052 
1053 //==========================================================================
1054 //
1055 // 	VRenderLevelShared::PrecacheLevel
1056 //
1057 // 	Preloads all relevant graphics for the level.
1058 //
1059 //==========================================================================
1060 
PrecacheLevel()1061 void VRenderLevelShared::PrecacheLevel()
1062 {
1063 	guard(VRenderLevelShared::PrecacheLevel);
1064 	int			i;
1065 
1066 	if (cls.demoplayback)
1067 		return;
1068 
1069 #ifdef __GNUC__
1070 	char texturepresent[GTextureManager.GetNumTextures()];
1071 #else
1072 	char* texturepresent = (char*)Z_Malloc(GTextureManager.GetNumTextures());
1073 #endif
1074 	memset(texturepresent, 0, GTextureManager.GetNumTextures());
1075 
1076 	for (i = 0; i < Level->NumSectors; i++)
1077 	{
1078 		texturepresent[Level->Sectors[i].floor.pic] = true;
1079 		texturepresent[Level->Sectors[i].ceiling.pic] = true;
1080 	}
1081 
1082 	for (i = 0; i < Level->NumSides; i++)
1083 	{
1084 		texturepresent[Level->Sides[i].TopTexture] = true;
1085 		texturepresent[Level->Sides[i].MidTexture] = true;
1086 		texturepresent[Level->Sides[i].BottomTexture] = true;
1087 	}
1088 
1089 	// Precache textures.
1090 	for (i = 1; i < GTextureManager.GetNumTextures(); i++)
1091 	{
1092 		if (texturepresent[i])
1093 		{
1094 			Drawer->PrecacheTexture(GTextureManager[i]);
1095 		}
1096 	}
1097 
1098 #ifndef __GNUC__
1099 	Z_Free(texturepresent);
1100 #endif
1101 	unguard;
1102 }
1103 
1104 //==========================================================================
1105 //
1106 //	VRenderLevelShared::GetTranslation
1107 //
1108 //==========================================================================
1109 
GetTranslation(int TransNum)1110 VTextureTranslation* VRenderLevelShared::GetTranslation(int TransNum)
1111 {
1112 	guard(VRenderLevelShared::GetTranslation);
1113 	return R_GetCachedTranslation(TransNum, Level);
1114 	unguard;
1115 }
1116 
1117 //==========================================================================
1118 //
1119 //	VRenderLevelShared::BuildPlayerTranslations
1120 //
1121 //==========================================================================
1122 
BuildPlayerTranslations()1123 void VRenderLevelShared::BuildPlayerTranslations()
1124 {
1125 	guard(VRenderLevelShared::BuildPlayerTranslations);
1126 	for (TThinkerIterator<VPlayerReplicationInfo> It(Level); It; ++It)
1127 	{
1128 		if (It->PlayerNum < 0 || It->PlayerNum >= MAXPLAYERS)
1129 		{
1130 			//	Should not happen.
1131 			continue;
1132 		}
1133 		if (!It->TranslStart || !It->TranslEnd)
1134 		{
1135 			continue;
1136 		}
1137 
1138 		VTextureTranslation* Tr = PlayerTranslations[It->PlayerNum];
1139 		if (Tr && Tr->TranslStart == It->TranslStart &&
1140 			Tr->TranslEnd == It->TranslEnd && Tr->Colour == It->Colour)
1141 		{
1142 			continue;
1143 		}
1144 
1145 		if (!Tr)
1146 		{
1147 			Tr = new VTextureTranslation;
1148 			PlayerTranslations[It->PlayerNum] = Tr;
1149 		}
1150 		//	Don't waste time clearing if it's the same range.
1151 		if (Tr->TranslStart != It->TranslStart ||
1152 			Tr->TranslEnd != It->TranslEnd)
1153 		{
1154 			Tr->Clear();
1155 		}
1156 		Tr->BuildPlayerTrans(It->TranslStart, It->TranslEnd, It->Colour);
1157 	}
1158 	unguard;
1159 }
1160 
1161 //==========================================================================
1162 //
1163 //	R_SetMenuPlayerTrans
1164 //
1165 //==========================================================================
1166 
R_SetMenuPlayerTrans(int Start,int End,int Col)1167 int R_SetMenuPlayerTrans(int Start, int End, int Col)
1168 {
1169 	guard(R_SetMenuPlayerTrans);
1170 	if (!Start || !End)
1171 	{
1172 		return 0;
1173 	}
1174 
1175 	VTextureTranslation* Tr = PlayerTranslations[MAXPLAYERS];
1176 	if (Tr && Tr->TranslStart == Start && Tr->TranslEnd == End &&
1177 		Tr->Colour == Col)
1178 	{
1179 		return (TRANSL_Player << TRANSL_TYPE_SHIFT) + MAXPLAYERS;
1180 	}
1181 
1182 	if (!Tr)
1183 	{
1184 		Tr = new VTextureTranslation;
1185 		PlayerTranslations[MAXPLAYERS] = Tr;
1186 	}
1187 	if (Tr->TranslStart != Start || Tr->TranslEnd == End)
1188 	{
1189 		Tr->Clear();
1190 	}
1191 	Tr->BuildPlayerTrans(Start, End, Col);
1192 	return (TRANSL_Player << TRANSL_TYPE_SHIFT) + MAXPLAYERS;
1193 	unguard;
1194 }
1195 
1196 //==========================================================================
1197 //
1198 //	R_GetCachedTranslation
1199 //
1200 //==========================================================================
1201 
R_GetCachedTranslation(int TransNum,VLevel * Level)1202 VTextureTranslation* R_GetCachedTranslation(int TransNum, VLevel* Level)
1203 {
1204 	guard(R_GetCachedTranslation);
1205 	int Type = TransNum >> TRANSL_TYPE_SHIFT;
1206 	int Index = TransNum & ((1 << TRANSL_TYPE_SHIFT) - 1);
1207 	VTextureTranslation* Tr;
1208 	switch (Type)
1209 	{
1210 	case TRANSL_Standard:
1211 		if (Index == 7)
1212 		{
1213 			Tr = &IceTranslation;
1214 		}
1215 		else
1216 		{
1217 			if (Index < 0 || Index >= NumTranslationTables)
1218 			{
1219 				return NULL;
1220 			}
1221 			Tr = TranslationTables[Index];
1222 		}
1223 		break;
1224 
1225 	case TRANSL_Player:
1226 		if (Index < 0 || Index >= MAXPLAYERS + 1)
1227 		{
1228 			return NULL;
1229 		}
1230 		Tr = PlayerTranslations[Index];
1231 		break;
1232 
1233 	case TRANSL_Level:
1234 		if (!Level || Index < 0 || Index >= Level->Translations.Num())
1235 		{
1236 			return NULL;
1237 		}
1238 		Tr = Level->Translations[Index];
1239 		break;
1240 
1241 	case TRANSL_BodyQueue:
1242 		if (!Level || Index < 0 || Index >= Level->BodyQueueTrans.Num())
1243 		{
1244 			return NULL;
1245 		}
1246 		Tr = Level->BodyQueueTrans[Index];
1247 		break;
1248 
1249 	case TRANSL_Decorate:
1250 		if (Index < 0 || Index >= DecorateTranslations.Num())
1251 		{
1252 			return NULL;
1253 		}
1254 		Tr = DecorateTranslations[Index];
1255 		break;
1256 
1257 	case TRANSL_Blood:
1258 		if (Index < 0 || Index >= BloodTranslations.Num())
1259 		{
1260 			return NULL;
1261 		}
1262 		Tr = BloodTranslations[Index];
1263 		break;
1264 
1265 	default:
1266 		return NULL;
1267 	}
1268 
1269 	if (!Tr)
1270 	{
1271 		return NULL;
1272 	}
1273 
1274 	for (int i = 0; i < CachedTranslations.Num(); i++)
1275 	{
1276 		VTextureTranslation* Check = CachedTranslations[i];
1277 		if (Check->Crc != Tr->Crc)
1278 		{
1279 			continue;
1280 		}
1281 		if (memcmp(Check->Palette, Tr->Palette, sizeof(Tr->Palette)))
1282 		{
1283 			continue;
1284 		}
1285 		return Check;
1286 	}
1287 
1288 	VTextureTranslation* Copy = new VTextureTranslation;
1289 	*Copy = *Tr;
1290 	CachedTranslations.Append(Copy);
1291 	return Copy;
1292 	unguard;
1293 }
1294 
1295 //==========================================================================
1296 //
1297 //	COMMAND TimeRefresh
1298 //
1299 //	For program optimization
1300 //
1301 //==========================================================================
1302 
COMMAND(TimeRefresh)1303 COMMAND(TimeRefresh)
1304 {
1305 	guard(COMMAND TimeRefresh);
1306 	int			i;
1307 	double		start, stop, time, RenderTime, UpdateTime;
1308 	float		startangle;
1309 
1310 	if (!cl)
1311 	{
1312 		return;
1313 	}
1314 
1315 	startangle = cl->ViewAngles.yaw;
1316 
1317 	RenderTime = 0;
1318 	UpdateTime = 0;
1319 	start = Sys_Time();
1320 	for (i = 0; i < 128; i++)
1321 	{
1322 		cl->ViewAngles.yaw = (float)(i) * 360.0 / 128.0;
1323 
1324 		Drawer->StartUpdate();
1325 
1326 		RenderTime -= Sys_Time();
1327 		R_RenderPlayerView();
1328 		RenderTime += Sys_Time();
1329 
1330 		UpdateTime -= Sys_Time();
1331 		Drawer->Update();
1332 		UpdateTime += Sys_Time();
1333 	}
1334 	stop = Sys_Time();
1335 	time = stop - start;
1336 	GCon->Logf("%f seconds (%f fps)", time, 128 / time);
1337 	GCon->Logf("Render time %f, update time %f", RenderTime, UpdateTime);
1338 
1339 	cl->ViewAngles.yaw = startangle;
1340 	unguard;
1341 }
1342 
1343 //==========================================================================
1344 //
1345 //	V_Init
1346 //
1347 //==========================================================================
1348 
V_Init()1349 void V_Init()
1350 {
1351 	guard(V_Init);
1352 	int DIdx = -1;
1353 	for (int i = 0; i < DRAWER_MAX; i++)
1354 	{
1355 		if (!DrawerList[i])
1356 			continue;
1357 		//	Pick first available as default.
1358 		if (DIdx == -1)
1359 			DIdx = i;
1360 		//	Check for user driver selection.
1361 		if (DrawerList[i]->CmdLineArg && GArgs.CheckParm(DrawerList[i]->CmdLineArg))
1362 			DIdx = i;
1363 	}
1364 	if (DIdx == -1)
1365 		Sys_Error("No drawers are available");
1366 	_driver = DIdx;
1367 	GCon->Logf(NAME_Init, "Selected %s", DrawerList[DIdx]->Description);
1368 	//	Create drawer.
1369 	Drawer = DrawerList[DIdx]->Creator();
1370 	Drawer->Init();
1371 	unguard;
1372 }
1373 
1374 //==========================================================================
1375 //
1376 //	V_Shutdown
1377 //
1378 //==========================================================================
1379 
V_Shutdown()1380 void V_Shutdown()
1381 {
1382 	guard(V_Shutdown);
1383 	if (Drawer)
1384 	{
1385 		Drawer->Shutdown();
1386 		delete Drawer;
1387 		Drawer = NULL;
1388 	}
1389 	R_FreeModels();
1390 	for (int i = 0; i < MAXPLAYERS + 1; i++)
1391 	{
1392 		if (PlayerTranslations[i])
1393 		{
1394 			delete PlayerTranslations[i];
1395 			PlayerTranslations[i] = NULL;
1396 		}
1397 	}
1398 	for (int i = 0; i < CachedTranslations.Num(); i++)
1399 	{
1400 		delete CachedTranslations[i];
1401 		CachedTranslations[i] = NULL;
1402 	}
1403 	CachedTranslations.Clear();
1404 	R_FreeSkyboxData();
1405 	unguard;
1406 }
1407