r_main.c 41.6 KB
Newer Older
Alam Ed Arias committed
1 2 3 4
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
James R. committed
5
// Copyright (C) 1999-2020 by Sonic Team Junior.
Alam Ed Arias committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file  r_main.c
/// \brief Rendering main loop and setup functions,
///        utility functions (BSP, geometry, trigonometry).
///        See tables.c, too.

#include "doomdef.h"
#include "g_game.h"
#include "g_input.h"
#include "r_local.h"
#include "r_splats.h" // faB(21jan): testing
#include "r_sky.h"
Jaime Ita Passos committed
22
#include "hu_stuff.h"
Alam Ed Arias committed
23 24 25 26 27 28 29 30 31
#include "st_stuff.h"
#include "p_local.h"
#include "keys.h"
#include "i_video.h"
#include "m_menu.h"
#include "am_map.h"
#include "d_main.h"
#include "v_video.h"
#include "p_spec.h" // skyboxmo
Jaime Ita Passos committed
32
#include "p_setup.h"
Alam Ed Arias committed
33 34
#include "z_zone.h"
#include "m_random.h" // quake camera shake
35
#include "r_portal.h"
36
#include "r_main.h"
James R. committed
37
#include "i_system.h" // I_GetPreciseTime
Alam Ed Arias committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif

//profile stuff ---------------------------------------------------------
//#define TIMING
#ifdef TIMING
#include "p5prof.h"
INT64 mycount;
INT64 mytotal = 0;
//unsigned long  nombre = 100000;
#endif
//profile stuff ---------------------------------------------------------

// Fineangles in the SCREENWIDTH wide window.
#define FIELDOFVIEW 2048

// increment every time a check is made
size_t validcount = 1;

INT32 centerx, centery;

fixed_t centerxfrac, centeryfrac;
fixed_t projection;
fixed_t projectiony; // aspect ratio
colette committed
64
fixed_t fovtan; // field of view
Alam Ed Arias committed
65 66 67 68 69 70 71 72 73 74 75

// just for profiling purposes
size_t framecount;

size_t loopcount;

fixed_t viewx, viewy, viewz;
angle_t viewangle, aimingangle;
fixed_t viewcos, viewsin;
sector_t *viewsector;
player_t *viewplayer;
James R. committed
76
mobj_t *r_viewmobj;
Alam Ed Arias committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

//
// precalculated math tables
//
angle_t clipangle;
angle_t doubleclipangle;

// The viewangletox[viewangle + FINEANGLES/4] lookup
// maps the visible view angles to screen X coordinates,
// flattening the arc to a flat projection plane.
// There will be many angles mapped to the same X.
INT32 viewangletox[FINEANGLES/2];

// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
angle_t xtoviewangle[MAXVIDWIDTH+1];

lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];

// Hack to support extra boom colormaps.
100
extracolormap_t *extra_colormaps = NULL;
Alam Ed Arias committed
101

102
// Render stats
James R. committed
103 104 105 106
precise_t ps_prevframetime = 0;
precise_t ps_rendercalltime = 0;
precise_t ps_uitime = 0;
precise_t ps_swaptime = 0;
107

James R. committed
108
precise_t ps_bsptime = 0;
109

James R. committed
110 111 112 113
precise_t ps_sw_spritecliptime = 0;
precise_t ps_sw_portaltime = 0;
precise_t ps_sw_planetime = 0;
precise_t ps_sw_maskedtime = 0;
114

Hannu Hanhi committed
115 116 117 118
int ps_numbspcalls = 0;
int ps_numsprites = 0;
int ps_numdrawnodes = 0;
int ps_numpolyobjects = 0;
119

Alam Ed Arias committed
120 121 122 123 124
static CV_PossibleValue_t drawdist_cons_t[] = {
	{256, "256"},	{512, "512"},	{768, "768"},
	{1024, "1024"},	{1536, "1536"},	{2048, "2048"},
	{3072, "3072"},	{4096, "4096"},	{6144, "6144"},
	{8192, "8192"},	{0, "Infinite"},	{0, NULL}};
toaster committed
125 126 127 128 129 130 131 132

//static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}};

static CV_PossibleValue_t drawdist_precip_cons_t[] = {
	{256, "256"},	{512, "512"},	{768, "768"},
	{1024, "1024"},	{1536, "1536"},	{2048, "2048"},
	{0, "None"},	{0, NULL}};

colette committed
133
static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
Alam Ed Arias committed
134
static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}};
Alam Ed Arias committed
135
static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card
Alam Ed Arias committed
136 137
static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}};

colette committed
138
static void Fov_OnChange(void);
Alam Ed Arias committed
139 140
static void ChaseCam_OnChange(void);
static void ChaseCam2_OnChange(void);
Alam Ed Arias committed
141 142
static void FlipCam_OnChange(void);
static void FlipCam2_OnChange(void);
Alam Ed Arias committed
143
void SendWeaponPref(void);
Alam Ed Arias committed
144
void SendWeaponPref2(void);
Alam Ed Arias committed
145

146 147 148 149 150 151 152 153
consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_chasecam = CVAR_INIT ("chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange);
consvar_t cv_chasecam2 = CVAR_INIT ("chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange);
consvar_t cv_flipcam = CVAR_INIT ("flipcam", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam_OnChange);
consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam2_OnChange);

consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL);
154
consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL);
155 156 157 158 159 160 161 162 163 164
consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL,  CV_YesNo, R_SetViewSize);
consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL);

consvar_t cv_translucency = CVAR_INIT ("translucency", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_drawdist = CVAR_INIT ("drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL);
//consvar_t cv_precipdensity = CVAR_INIT ("precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL);
consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange);
Alam Ed Arias committed
165 166

// Okay, whoever said homremoval causes a performance hit should be shot.
167
consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL);
Alam Ed Arias committed
168

169
consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL);
Alam Ed Arias committed
170

171
consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL);
172

Alam Ed Arias committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
void SplitScreen_OnChange(void)
{
	if (!cv_debug && netgame)
	{
		if (splitscreen)
		{
			CONS_Alert(CONS_NOTICE, M_GetText("Splitscreen not supported in netplay, sorry!\n"));
			splitscreen = false;
		}
		return;
	}

	// recompute screen size
	R_ExecuteSetViewSize();

	if (!demoplayback && !botingame)
	{
		if (splitscreen)
			CL_AddSplitscreenPlayer();
		else
			CL_RemoveSplitscreenPlayer();

		if (server && !netgame)
			multiplayer = splitscreen;
	}
	else
	{
		INT32 i;
		secondarydisplayplayer = consoleplayer;
		for (i = 0; i < MAXPLAYERS; i++)
			if (playeringame[i] && i != consoleplayer)
			{
				secondarydisplayplayer = i;
				break;
			}
	}
}
colette committed
210 211 212 213 214 215 216 217
static void Fov_OnChange(void)
{
	// Shouldn't be needed with render parity?
	//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
	//	CV_Set(&cv_fov, cv_fov.defaultvalue);

	R_SetViewSize();
}
Alam Ed Arias committed
218 219 220

static void ChaseCam_OnChange(void)
{
221 222
	if (!cv_chasecam.value || !cv_useranalog[0].value)
		CV_SetValue(&cv_analog[0], 0);
Alam Ed Arias committed
223
	else
224
		CV_SetValue(&cv_analog[0], 1);
Alam Ed Arias committed
225 226 227 228 229 230
}

static void ChaseCam2_OnChange(void)
{
	if (botingame)
		return;
231 232
	if (!cv_chasecam2.value || !cv_useranalog[1].value)
		CV_SetValue(&cv_analog[1], 0);
Alam Ed Arias committed
233
	else
234
		CV_SetValue(&cv_analog[1], 1);
Alam Ed Arias committed
235 236
}

Alam Ed Arias committed
237 238 239 240 241 242 243 244 245 246
static void FlipCam_OnChange(void)
{
	SendWeaponPref();
}

static void FlipCam2_OnChange(void)
{
	SendWeaponPref2();
}

Alam Ed Arias committed
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
//
// R_PointOnSide
// Traverse BSP (sub) tree,
// check point against partition plane.
// Returns side 0 (front) or 1 (back).
//
// killough 5/2/98: reformatted
//
INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node)
{
	if (!node->dx)
		return x <= node->x ? node->dy > 0 : node->dy < 0;

	if (!node->dy)
		return y <= node->y ? node->dx < 0 : node->dx > 0;

	x -= node->x;
	y -= node->y;

	// Try to quickly decide by looking at sign bits.
	if ((node->dy ^ node->dx ^ x ^ y) < 0)
		return (node->dy ^ x) < 0;  // (left is negative)
	return FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x);
}

// killough 5/2/98: reformatted
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line)
{
275 276 277 278
	fixed_t lx = line->v1->x;
	fixed_t ly = line->v1->y;
	fixed_t ldx = line->v2->x - lx;
	fixed_t ldy = line->v2->y - ly;
Alam Ed Arias committed
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

	if (!ldx)
		return x <= lx ? ldy > 0 : ldy < 0;

	if (!ldy)
		return y <= ly ? ldx < 0 : ldx > 0;

	x -= lx;
	y -= ly;

	// Try to quickly decide by looking at sign bits.
	if ((ldy ^ ldx ^ x ^ y) < 0)
		return (ldy ^ x) < 0;          // (left is negative)
	return FixedMul(y, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, x);
}

//
// R_PointToAngle
// To get a global angle from cartesian coordinates,
//  the coordinates are flipped until they are in
//  the first octant of the coordinate system, then
//  the y (<=x) is scaled and divided by x to get a
//  tangent (slope) value which is looked up in the
//  tantoangle[] table. The +1 size of tantoangle[]
//  is to handle the case when x==y without additional
//  checking.
//
// killough 5/2/98: reformatted, cleaned up

angle_t R_PointToAngle(fixed_t x, fixed_t y)
{
	return (y -= viewy, (x -= viewx) || y) ?
	x >= 0 ?
	y >= 0 ?
		(x > y) ? tantoangle[SlopeDiv(y,x)] :                          // octant 0
314
		ANGLE_90-tantoangle[SlopeDiv(x,y)] :                           // octant 1
Alam Ed Arias committed
315 316
		x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] :                   // octant 8
		ANGLE_270+tantoangle[SlopeDiv(x,y)] :                          // octant 7
317
		y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] :  // octant 3
Alam Ed Arias committed
318
		ANGLE_90 + tantoangle[SlopeDiv(x,y)] :                         // octant 2
319 320
		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] :    // octant 4
		ANGLE_270-tantoangle[SlopeDiv(x,y)] :                          // octant 5
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
		0;
}

// This version uses 64-bit variables to avoid overflows with large values.
// Currently used only by OpenGL rendering.
angle_t R_PointToAngle64(INT64 x, INT64 y)
{
	return (y -= viewy, (x -= viewx) || y) ?
	x >= 0 ?
	y >= 0 ?
		(x > y) ? tantoangle[SlopeDivEx(y,x)] :                            // octant 0
		ANGLE_90-tantoangle[SlopeDivEx(x,y)] :                               // octant 1
		x > (y = -y) ? 0-tantoangle[SlopeDivEx(y,x)] :                    // octant 8
		ANGLE_270+tantoangle[SlopeDivEx(x,y)] :                              // octant 7
		y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDivEx(y,x)] :  // octant 3
		ANGLE_90 + tantoangle[SlopeDivEx(x,y)] :                             // octant 2
		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDivEx(y,x)] :    // octant 4
		ANGLE_270-tantoangle[SlopeDivEx(x,y)] :                              // octant 5
Alam Ed Arias committed
339 340 341 342 343 344 345 346 347
		0;
}

angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
{
	return (y -= pviewy, (x -= pviewx) || y) ?
	x >= 0 ?
	y >= 0 ?
		(x > y) ? tantoangle[SlopeDiv(y,x)] :                          // octant 0
348
		ANGLE_90-tantoangle[SlopeDiv(x,y)] :                           // octant 1
Alam Ed Arias committed
349 350
		x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] :                   // octant 8
		ANGLE_270+tantoangle[SlopeDiv(x,y)] :                          // octant 7
351
		y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] :  // octant 3
Alam Ed Arias committed
352
		ANGLE_90 + tantoangle[SlopeDiv(x,y)] :                         // octant 2
353 354
		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] :    // octant 4
		ANGLE_270-tantoangle[SlopeDiv(x,y)] :                          // octant 5
Alam Ed Arias committed
355 356 357 358 359
		0;
}

fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1)
{
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
	angle_t angle;
	fixed_t dx, dy, dist;

	dx = abs(px1 - px2);
	dy = abs(py1 - py2);

	if (dy > dx)
	{
		fixed_t temp;

		temp = dx;
		dx = dy;
		dy = temp;
	}
	if (!dy)
		return dx;

	angle = (tantoangle[FixedDiv(dy, dx)>>DBITS] + ANGLE_90) >> ANGLETOFINESHIFT;

	// use as cosine
	dist = FixedDiv(dx, FINESINE(angle));

	return dist;
Alam Ed Arias committed
383 384 385 386 387 388 389 390
}

// Little extra utility. Works in the same way as R_PointToAngle2
fixed_t R_PointToDist(fixed_t x, fixed_t y)
{
	return R_PointToDist2(viewx, viewy, x, y);
}

Jaime Ita Passos committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
{
	INT64 dx = x1-x2;
	INT64 dy = y1-y2;
	if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX)
	{
		x1 = (int)(dx / 2 + x2);
		y1 = (int)(dy / 2 + y2);
	}
	return (y1 -= y2, (x1 -= x2) || y1) ?
	x1 >= 0 ?
	y1 >= 0 ?
		(x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] :                            // octant 0
		ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] :                               // octant 1
		x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] :                    // octant 8
		ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] :                              // octant 7
		y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] :  // octant 3
		ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] :                             // octant 2
		(x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] :    // octant 4
		ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] :                              // octant 5
		0;
}

Alam Ed Arias committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)
//  at the given angle.
// rw_distance must be calculated first.
//
// killough 5/2/98: reformatted, cleaned up
//
// note: THIS IS USED ONLY FOR WALLS!
fixed_t R_ScaleFromGlobalAngle(angle_t visangle)
{
	angle_t anglea = ANGLE_90 + (visangle-viewangle);
	angle_t angleb = ANGLE_90 + (visangle-rw_normalangle);
	fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT));
	// proff 11/06/98: Changed for high-res
	fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT));

	if (den > num>>16)
	{
		num = FixedDiv(num, den);
		if (num > 64*FRACUNIT)
			return 64*FRACUNIT;
		if (num < 256)
			return 256;
		return num;
	}
	return 64*FRACUNIT;
}

Alam Ed Arias committed
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
//
// R_DoCulling
// Checks viewz and top/bottom heights of an item against culling planes
// Returns true if the item is to be culled, i.e it shouldn't be drawn!
// if ML_NOCLIMB is set, the camera view is required to be in the same area for culling to occur
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph)
{
	fixed_t cullplane;

	if (!cullheight)
		return false;

	cullplane = cullheight->frontsector->floorheight;
	if (cullheight->flags & ML_NOCLIMB) // Group culling
	{
		if (!viewcullheight)
			return false;

		// Make sure this is part of the same group
		if (viewcullheight->frontsector == cullheight->frontsector)
		{
			// OK, we can cull
			if (vz > cullplane && toph < cullplane) // Cull if below plane
				return true;

			if (bottomh > cullplane && vz <= cullplane) // Cull if above plane
				return true;
		}
	}
	else // Quick culling
	{
		if (vz > cullplane && toph < cullplane) // Cull if below plane
			return true;

		if (bottomh > cullplane && vz <= cullplane) // Cull if above plane
			return true;
	}

	return false;
}

Alam Ed Arias committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
//
// R_InitTextureMapping
//
static void R_InitTextureMapping(void)
{
	INT32 i;
	INT32 x;
	INT32 t;
	fixed_t focallength;

	// Use tangent table to generate viewangletox:
	//  viewangletox will give the next greatest x
	//  after the view angle.
	//
	// Calc focallength
	//  so FIELDOFVIEW angles covers SCREENWIDTH.
colette committed
500 501
	focallength = FixedDiv(projection,
		FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2));
Alam Ed Arias committed
502

503 504
	focallengthf = FIXED_TO_FLOAT(focallength);

Alam Ed Arias committed
505 506
	for (i = 0; i < FINEANGLES/2; i++)
	{
colette committed
507
		if (FINETANGENT(i) > fovtan*2)
Alam Ed Arias committed
508
			t = -1;
colette committed
509
		else if (FINETANGENT(i) < -fovtan*2)
Alam Ed Arias committed
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
			t = viewwidth+1;
		else
		{
			t = FixedMul(FINETANGENT(i), focallength);
			t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS;

			if (t < -1)
				t = -1;
			else if (t > viewwidth+1)
				t = viewwidth+1;
		}
		viewangletox[i] = t;
	}

	// Scan viewangletox[] to generate xtoviewangle[]:
	//  xtoviewangle will give the smallest view angle
	//  that maps to x.
	for (x = 0; x <= viewwidth;x++)
	{
		i = 0;
		while (viewangletox[i] > x)
			i++;
		xtoviewangle[x] = (i<<ANGLETOFINESHIFT) - ANGLE_90;
	}

	// Take out the fencepost cases from viewangletox.
	for (i = 0; i < FINEANGLES/2; i++)
	{
		if (viewangletox[i] == -1)
			viewangletox[i] = 0;
		else if (viewangletox[i] == viewwidth+1)
			viewangletox[i]  = viewwidth;
	}

	clipangle = xtoviewangle[0];
	doubleclipangle = clipangle*2;
}



//
// R_InitLightTables
// Only inits the zlight table,
//  because the scalelight table changes with view size.
//
#define DISTMAP 2

static inline void R_InitLightTables(void)
{
	INT32 i;
	INT32 j;
	INT32 level;
	INT32 startmapl;
	INT32 scale;

	// Calculate the light levels to use
	//  for each level / distance combination.
	for (i = 0; i < LIGHTLEVELS; i++)
	{
		startmapl = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
		for (j = 0; j < MAXLIGHTZ; j++)
		{
			//added : 02-02-98 : use BASEVIDWIDTH, vid.width is not set already,
			// and it seems it needs to be calculated only once.
			scale = FixedDiv((BASEVIDWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT);
			scale >>= LIGHTSCALESHIFT;
			level = startmapl - scale/DISTMAP;

			if (level < 0)
				level = 0;

			if (level >= NUMCOLORMAPS)
				level = NUMCOLORMAPS-1;

			zlight[i][j] = colormaps + level*256;
		}
	}
}

colette committed
589 590 591
//#define WOUGHMP_WOUGHMP // I got a fish-eye lens - I'll make a rap video with a couple of friends
// it's kinda laggy sometimes

colette committed
592 593
static struct {
	angle_t rollangle; // pre-shifted by fineshift
colette committed
594 595 596
#ifdef WOUGHMP_WOUGHMP
	fixed_t fisheye;
#endif
colette committed
597 598 599

	fixed_t zoomneeded;
	INT32 *scrmap;
600
	INT32 scrmapsize;
601

602
	INT32 x1; // clip rendering horizontally for efficiency
603 604
	INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];

colette committed
605
	boolean use;
colette committed
606 607 608 609 610
} viewmorph = {
	0,
#ifdef WOUGHMP_WOUGHMP
	0,
#endif
611

colette committed
612 613 614
	FRACUNIT,
	NULL,
	0,
615

616
	0,
617 618
	{}, {},

colette committed
619 620
	false
};
colette committed
621 622 623 624

void R_CheckViewMorph(void)
{
	float zoomfactor, rollcos, rollsin;
colette committed
625
	float x1, y1, x2, y2;
colette committed
626
	fixed_t temp;
627
	INT32 end, vx, vy, pos, usedpos;
colette committed
628
	INT32 usedx, usedy, halfwidth = vid.width/2, halfheight = vid.height/2;
colette committed
629 630 631
#ifdef WOUGHMP_WOUGHMP
	float fisheyemap[MAXVIDWIDTH/2 + 1];
#endif
colette committed
632 633

	angle_t rollangle = players[displayplayer].viewrollangle;
colette committed
634 635 636
#ifdef WOUGHMP_WOUGHMP
	fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value
#endif
colette committed
637 638

	rollangle >>= ANGLETOFINESHIFT;
639
	rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
colette committed
640

colette committed
641 642 643 644 645 646 647 648 649
#ifdef WOUGHMP_WOUGHMP
	fisheye &= ~0x7FF; // Same
#endif

	if (rollangle == viewmorph.rollangle &&
#ifdef WOUGHMP_WOUGHMP
		fisheye == viewmorph.fisheye &&
#endif
		viewmorph.scrmapsize == vid.width*vid.height)
colette committed
650 651 652
		return; // No change

	viewmorph.rollangle = rollangle;
colette committed
653 654 655
#ifdef WOUGHMP_WOUGHMP
	viewmorph.fisheye = fisheye;
#endif
colette committed
656

colette committed
657 658 659 660 661
	if (viewmorph.rollangle == 0
#ifdef WOUGHMP_WOUGHMP
		 && viewmorph.fisheye == 0
#endif
	 )
colette committed
662 663
	{
		viewmorph.use = false;
664
		viewmorph.x1 = 0;
colette committed
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
		if (viewmorph.zoomneeded != FRACUNIT)
			R_SetViewSize();
		viewmorph.zoomneeded = FRACUNIT;

		return;
	}

	if (viewmorph.scrmapsize != vid.width*vid.height)
	{
		if (viewmorph.scrmap)
			free(viewmorph.scrmap);
		viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32));
		viewmorph.scrmapsize = vid.width*vid.height;
	}

	temp = FINECOSINE(rollangle);
	rollcos = FIXED_TO_FLOAT(temp);
	temp = FINESINE(rollangle);
	rollsin = FIXED_TO_FLOAT(temp);

	// Calculate maximum zoom needed
	x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width;
	y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height;

colette committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
#ifdef WOUGHMP_WOUGHMP
	if (fisheye)
	{
		float f = FIXED_TO_FLOAT(fisheye);
		for (vx = 0; vx <= halfwidth; vx++)
			fisheyemap[vx] = 1.0f / cos(atan(vx * f / halfwidth));

		f = cos(atan(f));
		if (f < 1.0f)
		{
			x1 /= f;
			y1 /= f;
		}
	}
#endif

colette committed
705 706 707 708
	temp = max(x1, y1)*FRACUNIT;
	if (temp < FRACUNIT)
		temp = FRACUNIT;
	else
709
		temp |= 0x3FFF; // Limit how many times the viewport needs to be recalculated
colette committed
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731

	//CONS_Printf("Setting zoom to %f\n", FIXED_TO_FLOAT(temp));

	if (temp != viewmorph.zoomneeded)
	{
		viewmorph.zoomneeded = temp;
		R_SetViewSize();
	}

	zoomfactor = FIXED_TO_FLOAT(viewmorph.zoomneeded);

	end = vid.width * vid.height - 1;

	pos = 0;

	// Pre-multiply rollcos and rollsin to use for positional stuff
	rollcos /= zoomfactor;
	rollsin /= zoomfactor;

	x1 = -(halfwidth * rollcos - halfheight * rollsin);
	y1 = -(halfheight * rollcos + halfwidth * rollsin);

732 733 734 735 736 737 738 739
#ifdef WOUGHMP_WOUGHMP
	if (fisheye)
		viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)) * fisheyemap[halfwidth]);
	else
#endif
	viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)));
	//CONS_Printf("saving %d cols\n", viewmorph.x1);

740 741 742 743 744 745 746 747 748 749 750 751
	// Set ceilingclip and floorclip
	for (vx = 0; vx < vid.width; vx++)
	{
		viewmorph.ceilingclip[vx] = vid.height;
		viewmorph.floorclip[vx] = -1;
	}
	x2 = x1;
	y2 = y1;
	for (vx = 0; vx < vid.width; vx++)
	{
		INT16 xa, ya, xb, yb;
		xa = x2+halfwidth;
752
		ya = y2+halfheight-1;
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
		xb = vid.width-1-xa;
		yb = vid.height-1-ya;

		viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
		viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
		viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
		viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
		x2 += rollcos;
		y2 += rollsin;
	}
	x2 = x1;
	y2 = y1;
	for (vy = 0; vy < vid.height; vy++)
	{
		INT16 xa, ya, xb, yb;
		xa = x2+halfwidth;
		ya = y2+halfheight;
		xb = vid.width-1-xa;
		yb = vid.height-1-ya;

		viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
		viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
		viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
		viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
		x2 -= rollsin;
		y2 += rollcos;
	}

colette committed
781 782
	//CONS_Printf("Top left corner is %f %f\n", x1, y1);

colette committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
#ifdef WOUGHMP_WOUGHMP
	if (fisheye)
	{
		for (vy = 0; vy < halfheight; vy++)
		{
			x2 = x1;
			y2 = y1;
			x1 -= rollsin;
			y1 += rollcos;

			for (vx = 0; vx < vid.width; vx++)
			{
				usedx = halfwidth + x2*fisheyemap[(int) floorf(fabsf(y2*zoomfactor))];
				usedy = halfheight + y2*fisheyemap[(int) floorf(fabsf(x2*zoomfactor))];

				usedpos = usedx + usedy*vid.width;

				viewmorph.scrmap[pos] = usedpos;
				viewmorph.scrmap[end-pos] = end-usedpos;

				x2 += rollcos;
				y2 += rollsin;
				pos++;
			}
		}
	}
	else
810
	{
colette committed
811
#endif
812 813 814
	x1 += halfwidth;
	y1 += halfheight;

colette committed
815 816 817 818 819 820 821 822 823
	for (vy = 0; vy < halfheight; vy++)
	{
		x2 = x1;
		y2 = y1;
		x1 -= rollsin;
		y1 += rollcos;

		for (vx = 0; vx < vid.width; vx++)
		{
824 825
			usedx = x2;
			usedy = y2;
colette committed
826 827 828 829 830 831 832 833 834 835 836

			usedpos = usedx + usedy*vid.width;

			viewmorph.scrmap[pos] = usedpos;
			viewmorph.scrmap[end-pos] = end-usedpos;

			x2 += rollcos;
			y2 += rollsin;
			pos++;
		}
	}
837 838 839
#ifdef WOUGHMP_WOUGHMP
	}
#endif
colette committed
840 841 842 843 844 845 846 847 848 849 850 851 852

	viewmorph.use = true;
}

void R_ApplyViewMorph(void)
{
	UINT8 *tmpscr = screens[4];
	UINT8 *srcscr = screens[0];
	INT32 p, end = vid.width * vid.height;

	if (!viewmorph.use)
		return;

853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
	if (cv_debug & DBG_VIEWMORPH)
	{
		UINT8 border = 32;
		UINT8 grid = 160;
		INT32 ws = vid.width / 4;
		INT32 hs = vid.width * (vid.height / 4);

		memcpy(tmpscr, srcscr, vid.width*vid.height);
		for (p = 0; p < vid.width; p++)
		{
			tmpscr[viewmorph.scrmap[p]] = border;
			tmpscr[viewmorph.scrmap[p + hs]] = grid;
			tmpscr[viewmorph.scrmap[p + hs*2]] = grid;
			tmpscr[viewmorph.scrmap[p + hs*3]] = grid;
			tmpscr[viewmorph.scrmap[end - 1 - p]] = border;
		}
		for (p = vid.width; p < end; p += vid.width)
		{
			tmpscr[viewmorph.scrmap[p]] = border;
			tmpscr[viewmorph.scrmap[p + ws]] = grid;
			tmpscr[viewmorph.scrmap[p + ws*2]] = grid;
			tmpscr[viewmorph.scrmap[p + ws*3]] = grid;
			tmpscr[viewmorph.scrmap[end - 1 - p]] = border;
		}
	}
	else
		for (p = 0; p < end; p++)
			tmpscr[p] = srcscr[viewmorph.scrmap[p]];
colette committed
881 882 883 884 885

	VID_BlitLinearScreen(tmpscr, screens[0],
			vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
}

Alam Ed Arias committed
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909

//
// R_SetViewSize
// Do not really change anything here,
// because it might be in the middle of a refresh.
// The change will take effect next refresh.
//
boolean setsizeneeded;

void R_SetViewSize(void)
{
	setsizeneeded = true;
}

//
// R_ExecuteSetViewSize
//
void R_ExecuteSetViewSize(void)
{
	fixed_t dy;
	INT32 i;
	INT32 j;
	INT32 level;
	INT32 startmapl;
colette committed
910
	angle_t fov;
Alam Ed Arias committed
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932

	setsizeneeded = false;

	if (rendermode == render_none)
		return;

	// status bar overlay
	st_overlay = cv_showhud.value;

	scaledviewwidth = vid.width;
	viewheight = vid.height;

	if (splitscreen)
		viewheight >>= 1;

	viewwidth = scaledviewwidth;

	centerx = viewwidth/2;
	centery = viewheight/2;
	centerxfrac = centerx<<FRACBITS;
	centeryfrac = centery<<FRACBITS;

colette committed
933
	fov = FixedAngle(cv_fov.value/2) + ANGLE_90;
colette committed
934
	fovtan = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded);
colette committed
935 936 937 938
	if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
		fovtan = 17*fovtan/10;

	projection = projectiony = FixedDiv(centerxfrac, fovtan);
Alam Ed Arias committed
939 940 941 942 943 944 945 946 947

	R_InitViewBuffer(scaledviewwidth, viewheight);

	R_InitTextureMapping();

	// thing clipping
	for (i = 0; i < viewwidth; i++)
		screenheightarray[i] = (INT16)viewheight;

Jaime Ita Passos committed
948
	// setup sky scaling
Alam Ed Arias committed
949 950 951 952 953 954
	R_SetSkyScale();

	// planes
	if (rendermode == render_soft)
	{
		// this is only used for planes rendering in software mode
Jaime Ita Passos committed
955
		j = viewheight*16;
Alam Ed Arias committed
956 957
		for (i = 0; i < j; i++)
		{
Jaime Ita Passos committed
958
			dy = ((i - viewheight*8)<<FRACBITS) + FRACUNIT/2;
colette committed
959
			dy = FixedMul(abs(dy), fovtan);
Jaime Ita Passos committed
960
			yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
Alam Ed Arias committed
961
		}
962 963 964 965 966 967 968 969 970 971

		if (ds_su)
			Z_Free(ds_su);
		if (ds_sv)
			Z_Free(ds_sv);
		if (ds_sz)
			Z_Free(ds_sz);

		ds_su = ds_sv = ds_sz = NULL;
		ds_sup = ds_svp = ds_szp = NULL;
Alam Ed Arias committed
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
	}

	memset(scalelight, 0xFF, sizeof(scalelight));

	// Calculate the light levels to use for each level/scale combination.
	for (i = 0; i< LIGHTLEVELS; i++)
	{
		startmapl = ((LIGHTLEVELS - 1 - i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
		for (j = 0; j < MAXLIGHTSCALE; j++)
		{
			level = startmapl - j*vid.width/(viewwidth)/DISTMAP;

			if (level < 0)
				level = 0;

			if (level >= NUMCOLORMAPS)
				level = NUMCOLORMAPS - 1;

			scalelight[i][j] = colormaps + level*256;
		}
	}

	// continue to do the software setviewsize as long as we use the reference software view
#ifdef HWRENDER
	if (rendermode != render_soft)
		HWR_SetViewSize();
#endif

	am_recalc = true;
}

//
// R_Init
//

void R_Init(void)
{
	// screensize independent
	//I_OutputMsg("\nR_InitData");
	R_InitData();

	//I_OutputMsg("\nR_InitViewBorder");
	R_InitViewBorder();
	R_SetViewSize(); // setsizeneeded is set true

	//I_OutputMsg("\nR_InitPlanes");
	R_InitPlanes();

	// this is now done by SCR_Recalc() at the first mode set
	//I_OutputMsg("\nR_InitLightTables");
	R_InitLightTables();

Jaime Ita Passos committed
1024 1025
	//I_OutputMsg("\nR_InitTranslucencyTables\n");
	R_InitTranslucencyTables();
Alam Ed Arias committed
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045

	R_InitDrawNodes();

	framecount = 0;
}

//
// R_PointInSubsector
//
subsector_t *R_PointInSubsector(fixed_t x, fixed_t y)
{
	size_t nodenum = numnodes-1;

	while (!(nodenum & NF_SUBSECTOR))
		nodenum = nodes[nodenum].children[R_PointOnSide(x, y, nodes+nodenum)];

	return &subsectors[nodenum & ~NF_SUBSECTOR];
}

//
1046
// R_PointInSubsectorOrNull, same as above but returns 0 if not in subsector
Alam Ed Arias committed
1047
//
1048
subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y)
Alam Ed Arias committed
1049 1050 1051 1052 1053
{
	node_t *node;
	INT32 side, i;
	size_t nodenum;
	subsector_t *ret;
1054
	seg_t *seg;
Alam Ed Arias committed
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069

	// single subsector is a special case
	if (numnodes == 0)
		return subsectors;

	nodenum = numnodes - 1;

	while (!(nodenum & NF_SUBSECTOR))
	{
		node = &nodes[nodenum];
		side = R_PointOnSide(x, y, node);
		nodenum = node->children[side];
	}

	ret = &subsectors[nodenum & ~NF_SUBSECTOR];
1070 1071 1072 1073 1074 1075 1076
	for (i = 0, seg = &segs[ret->firstline]; i < ret->numlines; i++, seg++)
	{
		if (seg->glseg)
			continue;

		//if (R_PointOnSegSide(x, y, seg)) -- breaks in ogl because polyvertex_t cast over vertex pointers
		if (P_PointOnLineSide(x, y, seg->linedef) != seg->side)
Alam Ed Arias committed
1077
			return 0;
1078
	}
Alam Ed Arias committed
1079 1080 1081 1082 1083 1084 1085 1086

	return ret;
}

//
// R_SetupFrame
//

Jaime Ita Passos committed
1087 1088 1089
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
1090
static void R_SetupFreelook(player_t *player, boolean skybox)
Alam Ed Arias committed
1091 1092
{
	INT32 dy = 0;
1093

1094 1095 1096 1097 1098
#ifndef HWRENDER
	(void)player;
	(void)skybox;
#endif

1099 1100 1101 1102
	// clip it in the case we are looking a hardware 90 degrees full aiming
	// (lmps, network and use F12...)
	if (rendermode == render_soft
#ifdef HWRENDER
1103 1104 1105
		|| (rendermode == render_opengl
			&& (cv_glshearing.value == 1
			|| (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))))
1106 1107
#endif
		)
Jaime Ita Passos committed
1108 1109
	{
		G_SoftwareClipAimingPitch((INT32 *)&aimingangle);
1110 1111 1112 1113 1114
	}

	if (rendermode == render_soft)
	{
		dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH;
Jaime Ita Passos committed
1115 1116
		yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)];
	}
1117

Jaime Ita Passos committed
1118 1119 1120 1121
	centery = (viewheight/2) + dy;
	centeryfrac = centery<<FRACBITS;
}

1122
void R_SetupFrame(player_t *player)
Jaime Ita Passos committed
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
{
	camera_t *thiscam;
	boolean chasecam = false;

	if (splitscreen && player == &players[secondarydisplayplayer]
		&& player != &players[consoleplayer])
	{
		thiscam = &camera2;
		chasecam = (cv_chasecam2.value != 0);
	}
	else
	{
		thiscam = &camera;
		chasecam = (cv_chasecam.value != 0);
	}

1139
	if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode)
Jaime Ita Passos committed
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
		chasecam = true; // force chasecam on
	else if (player->spectator) // no spectator chasecam
		chasecam = false; // force chasecam off

	if (chasecam && !thiscam->chase)
	{
		P_ResetCamera(player, thiscam);
		thiscam->chase = true;
	}
	else if (!chasecam)
		thiscam->chase = false;

	if (player->awayviewtics)
	{
		// cut-away view stuff
James R. committed
1155 1156 1157
		r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
		I_Assert(r_viewmobj != NULL);
		viewz = r_viewmobj->z + 20*FRACUNIT;
Jaime Ita Passos committed
1158
		aimingangle = player->awayviewaiming;
James R. committed
1159
		viewangle = r_viewmobj->angle;
Jaime Ita Passos committed
1160 1161 1162 1163
	}
	else if (!player->spectator && chasecam)
	// use outside cam view
	{
James R. committed
1164
		r_viewmobj = NULL;
Jaime Ita Passos committed
1165 1166 1167 1168 1169 1170 1171 1172 1173
		viewz = thiscam->z + (thiscam->height>>1);
		aimingangle = thiscam->aiming;
		viewangle = thiscam->angle;
	}
	else
	// use the player's eyes view
	{
		viewz = player->viewz;

James R. committed
1174 1175
		r_viewmobj = player->mo;
		I_Assert(r_viewmobj != NULL);
Jaime Ita Passos committed
1176 1177

		aimingangle = player->aiming;
James R. committed
1178
		viewangle = r_viewmobj->angle;
Jaime Ita Passos committed
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211

		if (!demoplayback && player->playerstate != PST_DEAD)
		{
			if (player == &players[consoleplayer])
			{
				viewangle = localangle; // WARNING: camera uses this
				aimingangle = localaiming;
			}
			else if (player == &players[secondarydisplayplayer])
			{
				viewangle = localangle2;
				aimingangle = localaiming2;
			}
		}
	}
	viewz += quake.z;

	viewplayer = player;

	if (chasecam && !player->awayviewtics && !player->spectator)
	{
		viewx = thiscam->x;
		viewy = thiscam->y;
		viewx += quake.x;
		viewy += quake.y;

		if (thiscam->subsector)
			viewsector = thiscam->subsector->sector;
		else
			viewsector = R_PointInSubsector(viewx, viewy)->sector;
	}
	else
	{
James R. committed
1212 1213
		viewx = r_viewmobj->x;
		viewy = r_viewmobj->y;
Jaime Ita Passos committed
1214 1215 1216
		viewx += quake.x;
		viewy += quake.y;

James R. committed
1217 1218
		if (r_viewmobj->subsector)
			viewsector = r_viewmobj->subsector->sector;
Jaime Ita Passos committed
1219 1220 1221 1222 1223 1224 1225
		else
			viewsector = R_PointInSubsector(viewx, viewy)->sector;
	}

	viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
	viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);

1226
	R_SetupFreelook(player, false);
Jaime Ita Passos committed
1227 1228 1229 1230
}

void R_SkyboxFrame(player_t *player)
{
Alam Ed Arias committed
1231 1232 1233 1234 1235 1236 1237 1238 1239
	camera_t *thiscam;

	if (splitscreen && player == &players[secondarydisplayplayer]
	&& player != &players[consoleplayer])
		thiscam = &camera2;
	else
		thiscam = &camera;

	// cut-away view stuff
James R. committed
1240
	r_viewmobj = skyboxmo[0];
Alam Ed Arias committed
1241
#ifdef PARANOIA
James R. committed
1242
	if (!r_viewmobj)
Alam Ed Arias committed
1243 1244
	{
		const size_t playeri = (size_t)(player - players);
James R. committed
1245
		I_Error("R_SkyboxFrame: r_viewmobj null (player %s)", sizeu1(playeri));
Alam Ed Arias committed
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
	}
#endif
	if (player->awayviewtics)
	{
		aimingangle = player->awayviewaiming;
		viewangle = player->awayviewmobj->angle;
	}
	else if (thiscam->chase)
	{
		aimingangle = thiscam->aiming;
		viewangle = thiscam->angle;
	}
	else
	{
		aimingangle = player->aiming;
		viewangle = player->mo->angle;
		if (!demoplayback && player->playerstate != PST_DEAD)
		{
			if (player == &players[consoleplayer])
			{
				viewangle = localangle; // WARNING: camera uses this
				aimingangle = localaiming;
			}
			else if (player == &players[secondarydisplayplayer])
			{
				viewangle = localangle2;
				aimingangle = localaiming2;
			}
		}
	}
James R. committed
1276
	viewangle += r_viewmobj->angle;
Alam Ed Arias committed
1277 1278 1279

	viewplayer = player;

James R. committed
1280 1281 1282
	viewx = r_viewmobj->x;
	viewy = r_viewmobj->y;
	viewz = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
Alam Ed Arias committed
1283 1284 1285 1286

	if (mapheaderinfo[gamemap-1])
	{
		mapheader_t *mh = mapheaderinfo[gamemap-1];
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
		vector3_t campos = {0,0,0}; // Position of player's actual view point

		if (player->awayviewtics) {
			campos.x = player->awayviewmobj->x;
			campos.y = player->awayviewmobj->y;
			campos.z = player->awayviewmobj->z + 20*FRACUNIT;
		} else if (thiscam->chase) {
			campos.x = thiscam->x;
			campos.y = thiscam->y;
			campos.z = thiscam->z + (thiscam->height>>1);
		} else {
			campos.x = player->mo->x;
			campos.y = player->mo->y;
			campos.z = player->viewz;
		}

		// Earthquake effects should be scaled in the skybox
		// (if an axis isn't used, the skybox won't shake in that direction)
		campos.x += quake.x;
		campos.y += quake.y;
		campos.z += quake.z;

		if (skyboxmo[1]) // Is there a viewpoint?
1310
		{
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
			fixed_t x = 0, y = 0;
			if (mh->skybox_scalex > 0)
				x = (campos.x - skyboxmo[1]->x) / mh->skybox_scalex;
			else if (mh->skybox_scalex < 0)
				x = (campos.x - skyboxmo[1]->x) * -mh->skybox_scalex;

			if (mh->skybox_scaley > 0)
				y = (campos.y - skyboxmo[1]->y) / mh->skybox_scaley;
			else if (mh->skybox_scaley < 0)
				y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley;

James R. committed
1322
			if (r_viewmobj->angle == 0)
1323
			{
1324 1325
				viewx += x;
				viewy += y;
1326
			}
James R. committed
1327
			else if (r_viewmobj->angle == ANGLE_90)
Alam Ed Arias committed
1328
			{
1329 1330
				viewx -= y;
				viewy += x;
Alam Ed Arias committed
1331
			}
James R. committed
1332
			else if (r_viewmobj->angle == ANGLE_180)
1333 1334 1335 1336
			{
				viewx -= x;
				viewy -= y;
			}
James R. committed
1337
			else if (r_viewmobj->angle == ANGLE_270)
Alam Ed Arias committed
1338
			{
1339 1340 1341 1342
				viewx += y;
				viewy -= x;
			}
			else
Alam Ed Arias committed
1343
			{
James R. committed
1344
				angle_t ang = r_viewmobj->angle>>ANGLETOFINESHIFT;
1345 1346
				viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y,  FINESINE(ang));
				viewy += FixedMul(x,  FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
Alam Ed Arias committed
1347 1348
			}
		}
1349 1350 1351 1352
		if (mh->skybox_scalez > 0)
			viewz += campos.z / mh->skybox_scalez;
		else if (mh->skybox_scalez < 0)
			viewz += campos.z * -mh->skybox_scalez;
Alam Ed Arias committed
1353 1354
	}

James R. committed
1355 1356
	if (r_viewmobj->subsector)
		viewsector = r_viewmobj->subsector->sector;
Alam Ed Arias committed
1357 1358 1359 1360 1361 1362
	else
		viewsector = R_PointInSubsector(viewx, viewy)->sector;

	viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
	viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);

1363
	R_SetupFreelook(player, true);
Alam Ed Arias committed
1364 1365
}

1366
boolean R_ViewpointHasChasecam(player_t *player)
1367 1368
{
	boolean chasecam = false;
1369

1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
	if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer])
		chasecam = (cv_chasecam2.value != 0);
	else
		chasecam = (cv_chasecam.value != 0);

	if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode)
		chasecam = true; // force chasecam on
	else if (player->spectator) // no spectator chasecam
		chasecam = false; // force chasecam off

1380 1381 1382
	return chasecam;
}

1383
boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox)
1384 1385 1386
{
	boolean chasecam = R_ViewpointHasChasecam(player);

1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397
	// cut-away view stuff
	if (player->awayviewtics || skybox)
		return chasecam;
	// use outside cam view
	else if (!player->spectator && chasecam)
		return true;

	// use the player's eyes view
	return false;
}

1398
static void R_PortalFrame(portal_t *portal)
Alam Ed Arias committed
1399
{
Alam Ed Arias committed
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
	viewx = portal->viewx;
	viewy = portal->viewy;
	viewz = portal->viewz;

	viewangle = portal->viewangle;
	viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
	viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);

	portalclipstart = portal->start;
	portalclipend = portal->end;
Alam Ed Arias committed
1410

1411
	if (portal->clipline != -1)
Alam Ed Arias committed
1412
	{
1413
		portalclipline = &lines[portal->clipline];
1414
		portalcullsector = portalclipline->frontsector;
1415
		viewsector = portalclipline->frontsector;
Alam Ed Arias committed
1416 1417
	}
	else
Alam Ed Arias committed
1418
	{
1419
		portalclipline = NULL;
1420
		portalcullsector = NULL;
1421
		viewsector = R_PointInSubsector(viewx, viewy)->sector;
Alam Ed Arias committed
1422
	}
Alam Ed Arias committed
1423 1424
}

1425
static void Mask_Pre (maskcount_t* m)
Alam Ed Arias committed
1426
{
1427 1428 1429 1430 1431 1432 1433
	m->drawsegs[0] = ds_p - drawsegs;
	m->vissprites[0] = visspritecount;
	m->viewx = viewx;
	m->viewy = viewy;
	m->viewz = viewz;
	m->viewsector = viewsector;
}
Alam Ed Arias committed
1434

1435 1436 1437 1438
static void Mask_Post (maskcount_t* m)
{
	m->drawsegs[1] = ds_p - drawsegs;
	m->vissprites[1] = visspritecount;
Alam Ed Arias committed
1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
}

// ================
// R_RenderView
// ================

//                     FAB NOTE FOR WIN32 PORT !! I'm not finished already,
// but I suspect network may have problems with the video buffer being locked
// for all duration of rendering, and being released only once at the end..
// I mean, there is a win16lock() or something that lasts all the rendering,
// so maybe we should release screen lock before each netupdate below..?

void R_RenderPlayerView(player_t *player)
{
1453 1454
	UINT8			nummasks	= 1;
	maskcount_t*	masks		= malloc(sizeof(maskcount_t));
Alam Ed Arias committed
1455 1456 1457 1458

	if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
	{
		if (cv_homremoval.value == 1)
1459
			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
Alam Ed Arias committed
1460
		else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
1461
			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15));
Alam Ed Arias committed
1462 1463
	}

1464
	R_SetupFrame(player);
Alam Ed Arias committed
1465 1466 1467 1468 1469
	framecount++;
	validcount++;

	// Clear buffers.
	R_ClearPlanes();
1470 1471 1472 1473 1474
	if (viewmorph.use)
	{
		portalclipstart = viewmorph.x1;
		portalclipend = viewwidth-viewmorph.x1-1;
		R_PortalClearClipSegs(portalclipstart, portalclipend);
1475 1476
		memcpy(ceilingclip, viewmorph.ceilingclip, sizeof(INT16)*vid.width);
		memcpy(floorclip, viewmorph.floorclip, sizeof(INT16)*vid.width);
1477 1478 1479 1480
	}
	else
	{
		portalclipstart = 0;
1481
		portalclipend = viewwidth;
1482 1483
		R_ClearClipSegs();
	}
Alam Ed Arias committed
1484 1485
	R_ClearDrawSegs();
	R_ClearSprites();
1486
	Portal_InitList();
Alam Ed Arias committed
1487 1488 1489 1490 1491 1492

	// check for new console commands.
	NetUpdate();

	// The head node is the last node output.

1493 1494
	Mask_Pre(&masks[nummasks - 1]);
	curdrawsegs = ds_p;
Alam Ed Arias committed
1495 1496 1497 1498 1499
//profile stuff ---------------------------------------------------------
#ifdef TIMING
	mytotal = 0;
	ProfZeroTimer();
#endif
Hannu Hanhi committed
1500
	ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0;
James R. committed
1501
	ps_bsptime = I_GetPreciseTime();
Alam Ed Arias committed
1502
	R_RenderBSPNode((INT32)numnodes - 1);
James R. committed
1503
	ps_bsptime = I_GetPreciseTime() - ps_bsptime;
Hannu Hanhi committed
1504
	ps_numsprites = visspritecount;
Alam Ed Arias committed
1505 1506 1507 1508 1509 1510 1511
#ifdef TIMING
	RDMSR(0x10, &mycount);
	mytotal += mycount; // 64bit add

	CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal);
#endif
//profile stuff ---------------------------------------------------------
1512
	Mask_Post(&masks[nummasks - 1]);
Alam Ed Arias committed
1513

James R. committed
1514
	ps_sw_spritecliptime = I_GetPreciseTime();
1515
	R_ClipSprites(drawsegs, NULL);
James R. committed
1516
	ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime;
1517

Alam Ed Arias committed
1518

1519
	// Add skybox portals caused by sky visplanes.
1520
	if (cv_skybox.value && skyboxmo[0])
1521 1522
		Portal_AddSkyboxPortals();

1523
	// Portal rendering. Hijacks the BSP traversal.
James R. committed
1524
	ps_sw_portaltime = I_GetPreciseTime();
1525
	if (portal_base)
Alam Ed Arias committed
1526
	{
1527 1528
		portal_t *portal;

1529 1530 1531
		for(portal = portal_base; portal; portal = portal_base)
		{
			portalrender = portal->pass; // Recursiveness depth.
Alam Ed Arias committed
1532

1533
			R_ClearFFloorClips();
Alam Ed Arias committed
1534

1535 1536
			// Apply the viewpoint stored for the portal.
			R_PortalFrame(portal);
Alam Ed Arias committed
1537

1538 1539 1540 1541
			// Hack in the clipsegs to delimit the starting
			// clipping for sprites and possibly other similar
			// future items.
			R_PortalClearClipSegs(portal->start, portal->end);
Alam Ed Arias committed
1542

1543 1544 1545
			// Hack in the top/bottom clip values for the window
			// that were previously stored.
			Portal_ClipApply(portal);
Alam Ed Arias committed
1546

1547
			validcount++;
Alam Ed Arias committed
1548

1549 1550
			masks = realloc(masks, (++nummasks)*sizeof(maskcount_t));

1551
			Mask_Pre(&masks[nummasks - 1]);
1552 1553
			curdrawsegs = ds_p;

1554 1555
			// Render the BSP from the new viewpoint, and clip
			// any sprites with the new clipsegs and window.
1556
			R_RenderBSPNode((INT32)numnodes - 1);
1557
			Mask_Post(&masks[nummasks - 1]);
Nev3r committed
1558 1559

			R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Alam Ed Arias committed
1560

1561 1562
			Portal_Remove(portal);
		}
Alam Ed Arias committed
1563
	}
James R. committed
1564
	ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime;
Alam Ed Arias committed
1565

James R. committed
1566
	ps_sw_planetime = I_GetPreciseTime();
Alam Ed Arias committed
1567
	R_DrawPlanes();
James R. committed
1568
	ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime;
1569

Alam Ed Arias committed
1570 1571
	// draw mid texture and sprite
	// And now 3D floors/sides!
James R. committed
1572
	ps_sw_maskedtime = I_GetPreciseTime();
1573
	R_DrawMasked(masks, nummasks);
James R. committed
1574
	ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime;
1575

1576
	free(masks);
Alam Ed Arias committed
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
}

// =========================================================================
//                    ENGINE COMMANDS & VARS
// =========================================================================

void R_RegisterEngineStuff(void)
{
	CV_RegisterVar(&cv_gravity);
	CV_RegisterVar(&cv_tailspickup);
	CV_RegisterVar(&cv_allowmlook);
	CV_RegisterVar(&cv_homremoval);
	CV_RegisterVar(&cv_flipcam);
Inuyasha committed
1590
	CV_RegisterVar(&cv_flipcam2);
Alam Ed Arias committed
1591 1592 1593 1594 1595

	// Enough for dedicated server
	if (dedicated)
		return;

Alam Ed Arias committed
1596
	CV_RegisterVar(&cv_translucency);
Alam Ed Arias committed
1597 1598 1599
	CV_RegisterVar(&cv_drawdist);
	CV_RegisterVar(&cv_drawdist_nights);
	CV_RegisterVar(&cv_drawdist_precip);
colette committed
1600
	CV_RegisterVar(&cv_fov);
Alam Ed Arias committed
1601 1602 1603

	CV_RegisterVar(&cv_chasecam);
	CV_RegisterVar(&cv_chasecam2);
1604

Alam Ed Arias committed
1605 1606
	CV_RegisterVar(&cv_shadow);
	CV_RegisterVar(&cv_skybox);
1607
	CV_RegisterVar(&cv_ffloorclip);
Alam Ed Arias committed
1608 1609 1610 1611 1612 1613 1614

	CV_RegisterVar(&cv_cam_dist);
	CV_RegisterVar(&cv_cam_still);
	CV_RegisterVar(&cv_cam_height);
	CV_RegisterVar(&cv_cam_speed);
	CV_RegisterVar(&cv_cam_rotate);
	CV_RegisterVar(&cv_cam_rotspeed);
1615
	CV_RegisterVar(&cv_cam_turnmultiplier);
1616
	CV_RegisterVar(&cv_cam_orbit);
1617
	CV_RegisterVar(&cv_cam_adjust);
Alam Ed Arias committed
1618 1619 1620 1621 1622 1623 1624

	CV_RegisterVar(&cv_cam2_dist);
	CV_RegisterVar(&cv_cam2_still);
	CV_RegisterVar(&cv_cam2_height);
	CV_RegisterVar(&cv_cam2_speed);
	CV_RegisterVar(&cv_cam2_rotate);
	CV_RegisterVar(&cv_cam2_rotspeed);
1625
	CV_RegisterVar(&cv_cam2_turnmultiplier);
1626
	CV_RegisterVar(&cv_cam2_orbit);
1627
	CV_RegisterVar(&cv_cam2_adjust);
Alam Ed Arias committed
1628

1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
	CV_RegisterVar(&cv_cam_savedist[0][0]);
	CV_RegisterVar(&cv_cam_savedist[0][1]);
	CV_RegisterVar(&cv_cam_savedist[1][0]);
	CV_RegisterVar(&cv_cam_savedist[1][1]);

	CV_RegisterVar(&cv_cam_saveheight[0][0]);
	CV_RegisterVar(&cv_cam_saveheight[0][1]);
	CV_RegisterVar(&cv_cam_saveheight[1][0]);
	CV_RegisterVar(&cv_cam_saveheight[1][1]);

Alam Ed Arias committed
1639
	CV_RegisterVar(&cv_showhud);
Alam Ed Arias committed
1640
	CV_RegisterVar(&cv_translucenthud);
Alam Ed Arias committed
1641

Alam Ed Arias committed
1642 1643
	CV_RegisterVar(&cv_maxportals);

Sal committed
1644
	CV_RegisterVar(&cv_movebob);
Alam Ed Arias committed
1645
}