2001-02-19 21:15:25 +00:00
|
|
|
/*
|
|
|
|
r_main.c
|
|
|
|
|
2001-05-15 04:50:53 +00:00
|
|
|
(description)
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
2001-05-15 04:50:53 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
2003-01-15 16:53:34 +00:00
|
|
|
#ifdef HAVE_STDLIB_H
|
|
|
|
# include <stdlib.h>
|
|
|
|
#endif
|
2001-05-15 04:50:53 +00:00
|
|
|
|
|
|
|
#include <math.h>
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-03-27 20:33:07 +00:00
|
|
|
#include "QF/cmd.h"
|
2001-05-31 03:41:35 +00:00
|
|
|
#include "QF/cvar.h"
|
2001-05-15 04:50:53 +00:00
|
|
|
#include "QF/mathlib.h"
|
2001-05-20 20:38:51 +00:00
|
|
|
#include "QF/render.h"
|
2001-04-15 21:11:41 +00:00
|
|
|
#include "QF/screen.h"
|
2001-05-15 04:50:53 +00:00
|
|
|
#include "QF/sound.h"
|
2001-05-10 06:01:11 +00:00
|
|
|
#include "QF/sys.h"
|
|
|
|
|
2021-07-24 05:19:52 +00:00
|
|
|
#include "QF/scene/entity.h"
|
|
|
|
|
2004-07-11 00:37:48 +00:00
|
|
|
#include "compat.h"
|
2012-04-10 04:27:53 +00:00
|
|
|
#include "mod_internal.h"
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "r_internal.h"
|
2012-02-17 07:13:56 +00:00
|
|
|
#include "vid_internal.h"
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2002-06-10 22:52:13 +00:00
|
|
|
#ifdef PIC
|
|
|
|
# undef USE_INTEL_ASM //XXX asm pic hack
|
|
|
|
#endif
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void *colormap;
|
2012-02-18 05:34:14 +00:00
|
|
|
static vec3_t viewlightvec;
|
|
|
|
static alight_t r_viewlighting = { 128, 192, viewlightvec };
|
2001-02-26 06:48:02 +00:00
|
|
|
int r_numallocatededges;
|
|
|
|
qboolean r_drawpolys;
|
|
|
|
qboolean r_drawculledpolys;
|
|
|
|
qboolean r_worldpolysbacktofront;
|
|
|
|
qboolean r_recursiveaffinetriangles = true;
|
|
|
|
int r_pixbytes = 1;
|
|
|
|
float r_aliasuvscale = 1.0;
|
|
|
|
int r_outofsurfaces;
|
|
|
|
int r_outofedges;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
qboolean r_dowarp, r_dowarpold, r_viewchanged;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int c_surf;
|
2012-02-18 05:34:14 +00:00
|
|
|
int r_maxsurfsseen, r_maxedgesseen;
|
|
|
|
static int r_cnumsurfs;
|
|
|
|
static qboolean r_surfsonstack;
|
2001-02-26 06:48:02 +00:00
|
|
|
int r_clipflags;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
byte *r_warpbuffer;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2012-02-18 05:34:14 +00:00
|
|
|
static byte *r_stack_start;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// screen size info
|
2001-02-26 06:48:02 +00:00
|
|
|
float xcenter, ycenter;
|
|
|
|
float xscale, yscale;
|
|
|
|
float xscaleinv, yscaleinv;
|
|
|
|
float xscaleshrink, yscaleshrink;
|
|
|
|
float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int screenwidth;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
float pixelAspect;
|
2012-02-18 05:34:14 +00:00
|
|
|
static float screenAspect;
|
|
|
|
static float verticalFieldOfView;
|
|
|
|
static float xOrigin, yOrigin;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2011-11-14 02:18:22 +00:00
|
|
|
plane_t screenedge[4];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
// refresh flags
|
2001-02-26 06:48:02 +00:00
|
|
|
int r_polycount;
|
|
|
|
int r_drawnpolycount;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
int *pfrustum_indexes[4];
|
|
|
|
int r_frustum_indexes[4 * 6];
|
|
|
|
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
vec3_t vup, base_vup;
|
|
|
|
vec3_t vfwd, base_vfwd;
|
|
|
|
vec3_t vright, base_vright;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
float r_aliastransition, r_resfudge;
|
|
|
|
|
2012-02-21 05:10:20 +00:00
|
|
|
static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
|
|
|
|
static float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
|
|
|
void
|
2012-02-22 13:12:29 +00:00
|
|
|
sw_R_Init (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int dummy;
|
|
|
|
|
2022-03-04 16:48:10 +00:00
|
|
|
r_ent_queue = EntQueue_New (mod_num_types);
|
|
|
|
|
2001-05-15 04:50:53 +00:00
|
|
|
// get stack position so we can guess if we are going to overflow
|
2001-02-26 06:48:02 +00:00
|
|
|
r_stack_start = (byte *) & dummy;
|
|
|
|
|
2012-04-10 04:27:53 +00:00
|
|
|
R_Init_Cvars ();
|
|
|
|
R_Particles_Init_Cvars ();
|
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
Draw_Init ();
|
2012-02-01 12:52:47 +00:00
|
|
|
SCR_Init ();
|
2002-06-07 15:09:20 +00:00
|
|
|
R_SetFPCW ();
|
2002-06-10 22:52:13 +00:00
|
|
|
#ifdef USE_INTEL_ASM
|
2002-06-03 07:23:41 +00:00
|
|
|
R_InitVars ();
|
2002-06-10 22:52:13 +00:00
|
|
|
#endif
|
2002-06-03 07:23:41 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
R_InitTurb ();
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f, "Tests the current "
|
|
|
|
"refresh rate for the current location");
|
2001-05-15 04:50:53 +00:00
|
|
|
Cmd_AddCommand ("loadsky", R_LoadSky_f, "Load a skybox");
|
2001-02-26 06:48:02 +00:00
|
|
|
|
|
|
|
Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES);
|
|
|
|
Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
view_clipplanes[0].leftedge = true;
|
|
|
|
view_clipplanes[1].rightedge = true;
|
|
|
|
view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
|
2001-02-26 06:48:02 +00:00
|
|
|
view_clipplanes[3].leftedge = false;
|
2001-02-19 21:15:25 +00:00
|
|
|
view_clipplanes[0].rightedge = view_clipplanes[2].rightedge =
|
2001-02-26 06:48:02 +00:00
|
|
|
view_clipplanes[3].rightedge = false;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
r_refdef.xOrigin = XCENTERING;
|
|
|
|
r_refdef.yOrigin = YCENTERING;
|
|
|
|
|
|
|
|
// TODO: collect 386-specific code in one place
|
2001-05-15 04:50:53 +00:00
|
|
|
#ifdef USE_INTEL_ASM
|
2001-02-26 06:48:02 +00:00
|
|
|
Sys_MakeCodeWriteable ((long) R_EdgeCodeStart,
|
|
|
|
(long) R_EdgeCodeEnd - (long) R_EdgeCodeStart);
|
|
|
|
#endif // USE_INTEL_ASM
|
2001-02-19 21:15:25 +00:00
|
|
|
D_Init ();
|
2012-04-10 04:27:53 +00:00
|
|
|
|
|
|
|
Skin_Init ();
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2001-05-21 23:09:46 +00:00
|
|
|
R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush = &worldmodel->brush;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-05-18 17:50:19 +00:00
|
|
|
memset (&r_worldentity, 0, sizeof (r_worldentity));
|
2021-03-09 14:52:40 +00:00
|
|
|
r_worldentity.renderer.model = worldmodel;
|
2001-05-18 17:50:19 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// clear out efrags in case the level hasn't been reloaded
|
2021-07-27 03:32:40 +00:00
|
|
|
for (unsigned i = 0; i < brush->modleafs; i++)
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->leafs[i].efrags = NULL;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
if (brush->skytexture)
|
|
|
|
R_InitSky (brush->skytexture);
|
2004-11-06 02:21:00 +00:00
|
|
|
|
2012-01-29 07:09:35 +00:00
|
|
|
// Force a vis update
|
2001-02-19 21:15:25 +00:00
|
|
|
r_viewleaf = NULL;
|
2012-01-29 07:09:35 +00:00
|
|
|
R_MarkLeaves ();
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
R_ClearParticles ();
|
|
|
|
|
|
|
|
r_cnumsurfs = r_maxsurfs->int_val;
|
|
|
|
|
|
|
|
if (r_cnumsurfs <= MINSURFACES)
|
|
|
|
r_cnumsurfs = MINSURFACES;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_cnumsurfs > NUMSTACKSURFACES) {
|
2021-07-28 06:01:45 +00:00
|
|
|
surfaces = Hunk_AllocName (0, r_cnumsurfs * sizeof (surf_t),
|
|
|
|
"surfaces");
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
surface_p = surfaces;
|
|
|
|
surf_max = &surfaces[r_cnumsurfs];
|
|
|
|
r_surfsonstack = false;
|
2001-02-26 06:48:02 +00:00
|
|
|
// surface 0 doesn't really exist; it's just a dummy because index 0
|
|
|
|
// is used to indicate no edge attached to surface
|
2001-02-19 21:15:25 +00:00
|
|
|
surfaces--;
|
|
|
|
R_SurfacePatch ();
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2001-02-19 21:15:25 +00:00
|
|
|
r_surfsonstack = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
r_maxedgesseen = 0;
|
|
|
|
r_maxsurfsseen = 0;
|
|
|
|
|
|
|
|
r_numallocatededges = r_maxedges->int_val;
|
|
|
|
|
|
|
|
if (r_numallocatededges < MINEDGES)
|
|
|
|
r_numallocatededges = MINEDGES;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_numallocatededges <= NUMSTACKEDGES) {
|
2001-02-19 21:15:25 +00:00
|
|
|
auxedges = NULL;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
2021-07-28 06:01:45 +00:00
|
|
|
auxedges = Hunk_AllocName (0, r_numallocatededges * sizeof (edge_t),
|
2001-02-19 21:15:25 +00:00
|
|
|
"edges");
|
|
|
|
}
|
|
|
|
|
|
|
|
r_dowarpold = false;
|
|
|
|
r_viewchanged = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-05-15 04:50:53 +00:00
|
|
|
R_ViewChanged
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-05-15 04:50:53 +00:00
|
|
|
Called every time the vid structure or r_refdef changes.
|
|
|
|
Guaranteed to be called before the first refresh
|
2001-02-19 21:15:25 +00:00
|
|
|
*/
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
2021-04-01 10:17:19 +00:00
|
|
|
R_ViewChanged (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i;
|
|
|
|
float res_scale;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
r_viewchanged = true;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI);
|
|
|
|
r_refdef.fvrectx = (float) r_refdef.vrect.x;
|
|
|
|
r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5;
|
|
|
|
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1;
|
|
|
|
r_refdef.fvrecty = (float) r_refdef.vrect.y;
|
|
|
|
r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5;
|
2001-02-19 21:15:25 +00:00
|
|
|
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.vrectright_adj_shift20 =
|
|
|
|
(r_refdef.vrectright << 20) + (1 << 19) - 1;
|
|
|
|
r_refdef.fvrectright = (float) r_refdef.vrectright;
|
|
|
|
r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5;
|
|
|
|
r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99;
|
2001-02-19 21:15:25 +00:00
|
|
|
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.fvrectbottom = (float) r_refdef.vrectbottom;
|
|
|
|
r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * r_aliasuvscale);
|
|
|
|
r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * r_aliasuvscale);
|
|
|
|
r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * r_aliasuvscale);
|
2001-08-25 02:47:11 +00:00
|
|
|
r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height *
|
|
|
|
r_aliasuvscale);
|
2001-02-19 21:15:25 +00:00
|
|
|
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.aliasvrect.width;
|
2001-02-19 21:15:25 +00:00
|
|
|
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
|
2001-02-26 06:48:02 +00:00
|
|
|
r_refdef.aliasvrect.height;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2021-04-01 10:17:19 +00:00
|
|
|
pixelAspect = 1;//FIXME vid.aspect;
|
2001-02-19 21:15:25 +00:00
|
|
|
xOrigin = r_refdef.xOrigin;
|
|
|
|
yOrigin = r_refdef.yOrigin;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2009-12-21 10:10:45 +00:00
|
|
|
screenAspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height;
|
2001-08-25 02:47:11 +00:00
|
|
|
// 320*200 1.0 pixelAspect = 1.6 screenAspect
|
|
|
|
// 320*240 1.0 pixelAspect = 1.3333 screenAspect
|
|
|
|
// proper 320*200 pixelAspect = 0.8333333
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
|
|
|
|
|
2001-05-16 17:08:56 +00:00
|
|
|
// values for perspective projection
|
|
|
|
// if math were exact, the values would range from 0.5 to to range+0.5
|
|
|
|
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
|
|
|
|
// the polygon rasterization will never render in the first row or column
|
|
|
|
// but will definately render in the [range] row and column, so adjust the
|
|
|
|
// buffer origin to get an exact edge to edge fill
|
2001-02-26 06:48:02 +00:00
|
|
|
xcenter = ((float) r_refdef.vrect.width * XCENTERING) +
|
|
|
|
r_refdef.vrect.x - 0.5;
|
2001-02-19 21:15:25 +00:00
|
|
|
aliasxcenter = xcenter * r_aliasuvscale;
|
2001-02-26 06:48:02 +00:00
|
|
|
ycenter = ((float) r_refdef.vrect.height * YCENTERING) +
|
|
|
|
r_refdef.vrect.y - 0.5;
|
2001-02-19 21:15:25 +00:00
|
|
|
aliasycenter = ycenter * r_aliasuvscale;
|
|
|
|
|
|
|
|
xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
|
|
|
|
aliasxscale = xscale * r_aliasuvscale;
|
|
|
|
xscaleinv = 1.0 / xscale;
|
|
|
|
yscale = xscale * pixelAspect;
|
|
|
|
aliasyscale = yscale * r_aliasuvscale;
|
|
|
|
yscaleinv = 1.0 / yscale;
|
2001-02-26 06:48:02 +00:00
|
|
|
xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView;
|
|
|
|
yscaleshrink = xscaleshrink * pixelAspect;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// left side clip
|
2001-08-25 02:47:11 +00:00
|
|
|
screenedge[0].normal[0] = -1.0 / (xOrigin *
|
|
|
|
r_refdef.horizontalFieldOfView);
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[0].normal[1] = 0;
|
|
|
|
screenedge[0].normal[2] = 1;
|
|
|
|
screenedge[0].type = PLANE_ANYZ;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// right side clip
|
2001-08-28 20:51:51 +00:00
|
|
|
screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) *
|
|
|
|
r_refdef.horizontalFieldOfView);
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[1].normal[1] = 0;
|
|
|
|
screenedge[1].normal[2] = 1;
|
|
|
|
screenedge[1].type = PLANE_ANYZ;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// top side clip
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[2].normal[0] = 0;
|
2001-02-26 06:48:02 +00:00
|
|
|
screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView);
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[2].normal[2] = 1;
|
|
|
|
screenedge[2].type = PLANE_ANYZ;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// bottom side clip
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[3].normal[0] = 0;
|
2001-02-26 06:48:02 +00:00
|
|
|
screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView);
|
|
|
|
screenedge[3].normal[2] = 1;
|
2001-02-19 21:15:25 +00:00
|
|
|
screenedge[3].type = PLANE_ANYZ;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
2001-02-19 21:15:25 +00:00
|
|
|
VectorNormalize (screenedge[i].normal);
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) /
|
2001-08-25 02:47:11 +00:00
|
|
|
(320.0 * 152.0)) * (2.0 /
|
|
|
|
r_refdef.horizontalFieldOfView);
|
2001-02-19 21:15:25 +00:00
|
|
|
r_aliastransition = r_aliastransbase->value * res_scale;
|
|
|
|
r_resfudge = r_aliastransadj->value * res_scale;
|
|
|
|
|
|
|
|
// TODO: collect 386-specific code in one place
|
2001-05-15 04:50:53 +00:00
|
|
|
#ifdef USE_INTEL_ASM
|
2001-11-21 19:13:53 +00:00
|
|
|
Sys_MakeCodeWriteable ((long) R_Surf8Start,
|
|
|
|
(long) R_Surf8End - (long) R_Surf8Start);
|
|
|
|
colormap = vid.colormap8;
|
|
|
|
R_SurfPatch ();
|
2001-02-26 06:48:02 +00:00
|
|
|
#endif // USE_INTEL_ASM
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
D_ViewChanged ();
|
|
|
|
}
|
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
static inline void
|
|
|
|
draw_sprite_entity (entity_t *ent)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2022-03-11 06:07:38 +00:00
|
|
|
R_DrawSprite (ent);
|
2022-03-02 06:00:32 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
static inline void
|
2022-03-11 06:07:38 +00:00
|
|
|
setup_lighting (entity_t *ent, alight_t *lighting)
|
2022-03-02 06:00:32 +00:00
|
|
|
{
|
|
|
|
float minlight = 0;
|
|
|
|
int j;
|
2001-08-28 20:51:51 +00:00
|
|
|
// FIXME: remove and do real lighting
|
2001-02-26 06:48:02 +00:00
|
|
|
vec3_t dist;
|
|
|
|
float add;
|
2022-03-02 06:00:32 +00:00
|
|
|
float lightvec[3] = { -1, 0, 0 };
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-11 06:07:38 +00:00
|
|
|
minlight = max (ent->renderer.model->min_light, ent->renderer.min_light);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
// 128 instead of 255 due to clamping below
|
|
|
|
j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin),
|
|
|
|
minlight * 128);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
lighting->ambientlight = j;
|
|
|
|
lighting->shadelight = j;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
lighting->plightvec = lightvec;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) {
|
|
|
|
if (r_dlights[lnum].die >= vr_data.realtime) {
|
|
|
|
VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist);
|
|
|
|
add = r_dlights[lnum].radius - VectorLength (dist);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
if (add > 0)
|
|
|
|
lighting->ambientlight += add;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-02 06:00:32 +00:00
|
|
|
|
|
|
|
// clamp lighting so it doesn't overbright as much
|
|
|
|
if (lighting->ambientlight > 128)
|
|
|
|
lighting->ambientlight = 128;
|
|
|
|
if (lighting->ambientlight + lighting->shadelight > 192)
|
|
|
|
lighting->shadelight = 192 - lighting->ambientlight;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
draw_alias_entity (entity_t *ent)
|
|
|
|
{
|
|
|
|
// see if the bounding box lets us trivially reject, also
|
|
|
|
// sets trivial accept status
|
2022-03-11 06:07:38 +00:00
|
|
|
ent->visibility.trivial_accept = 0; //FIXME
|
|
|
|
if (R_AliasCheckBBox (ent)) {
|
2022-03-02 06:00:32 +00:00
|
|
|
alight_t lighting;
|
2022-03-11 06:07:38 +00:00
|
|
|
setup_lighting (ent, &lighting);
|
|
|
|
R_AliasDrawModel (ent, &lighting);
|
2022-03-02 06:00:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
draw_iqm_entity (entity_t *ent)
|
|
|
|
{
|
|
|
|
// see if the bounding box lets us trivially reject, also
|
|
|
|
// sets trivial accept status
|
2022-03-11 06:07:38 +00:00
|
|
|
ent->visibility.trivial_accept = 0; //FIXME
|
2022-03-02 06:00:32 +00:00
|
|
|
|
|
|
|
alight_t lighting;
|
2022-03-11 06:07:38 +00:00
|
|
|
setup_lighting (ent, &lighting);
|
|
|
|
R_IQMDrawModel (ent, &lighting);
|
2022-03-02 06:00:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
R_DrawEntitiesOnList (void)
|
|
|
|
{
|
|
|
|
if (!r_drawentities->int_val)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#define RE_LOOP(type_name) \
|
|
|
|
do { \
|
2022-03-04 16:48:10 +00:00
|
|
|
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
|
|
|
|
i++) { \
|
|
|
|
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
|
2022-03-02 06:00:32 +00:00
|
|
|
VectorCopy (Transform_GetWorldPosition (ent->transform), \
|
|
|
|
r_entorigin); \
|
|
|
|
draw_##type_name##_entity (ent); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
RE_LOOP (alias);
|
|
|
|
RE_LOOP (iqm);
|
|
|
|
RE_LOOP (sprite);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-02-26 06:48:02 +00:00
|
|
|
R_DrawViewModel (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-08-28 20:51:51 +00:00
|
|
|
// FIXME: remove and do real lighting
|
2001-02-26 06:48:02 +00:00
|
|
|
float lightvec[3] = { -1, 0, 0 };
|
|
|
|
int j;
|
2003-04-17 00:01:48 +00:00
|
|
|
unsigned int lnum;
|
2001-02-26 06:48:02 +00:00
|
|
|
vec3_t dist;
|
|
|
|
float add;
|
2004-07-11 00:37:48 +00:00
|
|
|
float minlight;
|
2001-02-26 06:48:02 +00:00
|
|
|
dlight_t *dl;
|
2022-03-11 06:07:38 +00:00
|
|
|
entity_t *viewent;
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
if (vr_data.inhibit_viewmodel
|
2001-05-20 20:38:51 +00:00
|
|
|
|| !r_drawviewmodel->int_val
|
2001-05-15 04:50:53 +00:00
|
|
|
|| !r_drawentities->int_val)
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
|
2022-03-11 06:07:38 +00:00
|
|
|
viewent = vr_data.view_model;
|
|
|
|
if (!viewent->renderer.model)
|
2001-02-19 21:15:25 +00:00
|
|
|
return;
|
|
|
|
|
2022-03-11 06:07:38 +00:00
|
|
|
VectorCopy (Transform_GetWorldPosition (viewent->transform), r_entorigin);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
VectorCopy (vup, viewlightvec);
|
2007-03-10 12:00:59 +00:00
|
|
|
VectorNegate (viewlightvec, viewlightvec);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-11 06:07:38 +00:00
|
|
|
minlight = max (viewent->renderer.min_light,
|
|
|
|
viewent->renderer.model->min_light);
|
2004-07-11 00:37:48 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
j = max (R_LightPoint (&r_worldentity.renderer.model->brush,
|
2021-03-19 11:18:45 +00:00
|
|
|
r_entorigin), minlight * 128);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
r_viewlighting.ambientlight = j;
|
|
|
|
r_viewlighting.shadelight = j;
|
|
|
|
|
2012-05-21 23:23:22 +00:00
|
|
|
// add dynamic lights
|
2001-10-09 20:35:17 +00:00
|
|
|
for (lnum = 0; lnum < r_maxdlights; lnum++) {
|
2001-05-20 05:42:52 +00:00
|
|
|
dl = &r_dlights[lnum];
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!dl->radius)
|
|
|
|
continue;
|
|
|
|
if (!dl->radius)
|
|
|
|
continue;
|
2012-02-14 08:28:09 +00:00
|
|
|
if (dl->die < vr_data.realtime)
|
2001-02-19 21:15:25 +00:00
|
|
|
continue;
|
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
VectorSubtract (r_entorigin, dl->origin, dist);
|
2002-08-20 02:22:40 +00:00
|
|
|
add = dl->radius - VectorLength (dist);
|
2001-02-19 21:15:25 +00:00
|
|
|
if (add > 0)
|
|
|
|
r_viewlighting.ambientlight += add;
|
|
|
|
}
|
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// clamp lighting so it doesn't overbright as much
|
2001-02-19 21:15:25 +00:00
|
|
|
if (r_viewlighting.ambientlight > 128)
|
|
|
|
r_viewlighting.ambientlight = 128;
|
|
|
|
if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
|
|
|
|
r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
|
|
|
|
|
|
|
|
r_viewlighting.plightvec = lightvec;
|
|
|
|
|
2022-03-11 06:07:38 +00:00
|
|
|
R_AliasDrawModel (viewent, &r_viewlighting);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static int
|
2022-03-11 07:39:08 +00:00
|
|
|
R_BmodelCheckBBox (entity_t *ent, model_t *clmodel, float *minmaxs)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i, *pindex, clipflags;
|
|
|
|
vec3_t acceptpt, rejectpt;
|
|
|
|
double d;
|
2021-03-09 14:52:40 +00:00
|
|
|
mat4f_t mat;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
clipflags = 0;
|
|
|
|
|
2022-03-11 07:39:08 +00:00
|
|
|
Transform_GetWorldMatrix (ent->transform, mat);
|
2021-03-09 14:52:40 +00:00
|
|
|
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
|
2001-02-26 06:48:02 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
2021-03-19 11:18:45 +00:00
|
|
|
d = DotProduct (mat[3], view_clipplanes[i].normal);
|
2001-02-19 21:15:25 +00:00
|
|
|
d -= view_clipplanes[i].dist;
|
|
|
|
|
|
|
|
if (d <= -clmodel->radius)
|
|
|
|
return BMODEL_FULLY_CLIPPED;
|
|
|
|
|
|
|
|
if (d <= clmodel->radius)
|
2001-02-26 06:48:02 +00:00
|
|
|
clipflags |= (1 << i);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
// generate accept and reject points
|
2001-08-28 20:51:51 +00:00
|
|
|
// FIXME: do with fast look-ups or integer tests based on the
|
|
|
|
// sign bit of the floating point values
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
pindex = pfrustum_indexes[i];
|
|
|
|
|
|
|
|
rejectpt[0] = minmaxs[pindex[0]];
|
|
|
|
rejectpt[1] = minmaxs[pindex[1]];
|
|
|
|
rejectpt[2] = minmaxs[pindex[2]];
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
|
|
|
d -= view_clipplanes[i].dist;
|
|
|
|
|
|
|
|
if (d <= 0)
|
|
|
|
return BMODEL_FULLY_CLIPPED;
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
acceptpt[0] = minmaxs[pindex[3 + 0]];
|
|
|
|
acceptpt[1] = minmaxs[pindex[3 + 1]];
|
|
|
|
acceptpt[2] = minmaxs[pindex[3 + 2]];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
|
|
|
d -= view_clipplanes[i].dist;
|
|
|
|
|
|
|
|
if (d <= 0)
|
2001-02-26 06:48:02 +00:00
|
|
|
clipflags |= (1 << i);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return clipflags;
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2022-03-11 04:10:20 +00:00
|
|
|
R_DrawBrushEntitiesOnList (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2010-12-03 05:54:39 +00:00
|
|
|
int j, clipflags;
|
2003-04-17 00:01:48 +00:00
|
|
|
unsigned int k;
|
2021-03-19 11:18:45 +00:00
|
|
|
vec3_t origin;
|
2001-02-26 06:48:02 +00:00
|
|
|
model_t *clmodel;
|
|
|
|
float minmaxs[6];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
if (!r_drawentities->int_val)
|
|
|
|
return;
|
|
|
|
|
|
|
|
insubmodel = true;
|
|
|
|
|
2022-03-04 16:48:10 +00:00
|
|
|
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
|
|
|
|
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-04 16:48:10 +00:00
|
|
|
VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
|
|
|
|
clmodel = ent->renderer.model;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
// see if the bounding box lets us trivially reject, also
|
|
|
|
// sets trivial accept status
|
|
|
|
for (j = 0; j < 3; j++) {
|
|
|
|
minmaxs[j] = origin[j] + clmodel->mins[j];
|
|
|
|
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
|
|
|
|
}
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-11 07:39:08 +00:00
|
|
|
clipflags = R_BmodelCheckBBox (ent, clmodel, minmaxs);
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
if (clipflags != BMODEL_FULLY_CLIPPED) {
|
|
|
|
mod_brush_t *brush = &clmodel->brush;
|
|
|
|
VectorCopy (origin, r_entorigin);
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
VectorSubtract (r_refdef.frame.position, r_entorigin, modelorg);
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
r_pcurrentvertbase = brush->vertexes;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
// FIXME: stop transforming twice
|
2022-03-11 07:39:08 +00:00
|
|
|
R_RotateBmodel (ent->transform);
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
// calculate dynamic lighting for bmodel if it's not an
|
|
|
|
// instanced model
|
|
|
|
if (brush->firstmodelsurface != 0) {
|
|
|
|
vec3_t lightorigin;
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2022-03-02 06:00:32 +00:00
|
|
|
for (k = 0; k < r_maxdlights; k++) {
|
|
|
|
if ((r_dlights[k].die < vr_data.realtime) ||
|
|
|
|
(!r_dlights[k].radius)) {
|
|
|
|
continue;
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2022-03-02 06:00:32 +00:00
|
|
|
|
|
|
|
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
|
|
|
|
R_RecursiveMarkLights (brush, lightorigin,
|
|
|
|
&r_dlights[k], k,
|
|
|
|
brush->nodes
|
|
|
|
+ brush->hulls[0].firstclipnode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if the driver wants polygons, deliver those.
|
|
|
|
// Z-buffering is on at this point, so no clipping to the
|
|
|
|
// world tree is needed, just frustum clipping
|
|
|
|
if (r_drawpolys | r_drawculledpolys) {
|
2022-03-11 07:39:08 +00:00
|
|
|
R_ZDrawSubmodelPolys (ent, clmodel);
|
2022-03-02 06:00:32 +00:00
|
|
|
} else {
|
2022-03-04 16:48:10 +00:00
|
|
|
if (ent->visibility.topnode) {
|
|
|
|
mnode_t *topnode = ent->visibility.topnode;
|
2022-03-02 06:00:32 +00:00
|
|
|
|
|
|
|
if (topnode->contents >= 0) {
|
|
|
|
// not a leaf; has to be clipped to the world
|
|
|
|
// BSP
|
|
|
|
r_clipflags = clipflags;
|
2022-03-11 07:39:08 +00:00
|
|
|
R_DrawSolidClippedSubmodelPolygons (ent, clmodel, topnode);
|
2001-05-15 04:50:53 +00:00
|
|
|
} else {
|
2022-03-02 06:00:32 +00:00
|
|
|
// falls entirely in one leaf, so we just put
|
|
|
|
// all the edges in the edge list and let 1/z
|
|
|
|
// sorting handle drawing order
|
2022-03-11 07:39:08 +00:00
|
|
|
R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode);
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-05-15 04:50:53 +00:00
|
|
|
}
|
2022-03-02 06:00:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// put back world rotation and frustum clipping
|
|
|
|
// FIXME: R_RotateBmodel should just work off base_vxx
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
VectorCopy (base_vfwd, vfwd);
|
2022-03-02 06:00:32 +00:00
|
|
|
VectorCopy (base_vup, vup);
|
|
|
|
VectorCopy (base_vright, vright);
|
|
|
|
VectorCopy (base_modelorg, modelorg);
|
|
|
|
R_TransformFrustum ();
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
insubmodel = false;
|
|
|
|
}
|
|
|
|
|
2012-02-21 05:10:20 +00:00
|
|
|
static void
|
|
|
|
R_PrintDSpeeds (void)
|
|
|
|
{
|
|
|
|
float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time,
|
|
|
|
|
|
|
|
dv_time;
|
|
|
|
|
|
|
|
r_time2 = Sys_DoubleTime ();
|
|
|
|
|
|
|
|
dp_time = (dp_time2 - dp_time1) * 1000;
|
|
|
|
rw_time = (rw_time2 - rw_time1) * 1000;
|
|
|
|
db_time = (db_time2 - db_time1) * 1000;
|
|
|
|
se_time = (se_time2 - se_time1) * 1000;
|
|
|
|
de_time = (de_time2 - de_time1) * 1000;
|
|
|
|
dv_time = (dv_time2 - dv_time1) * 1000;
|
|
|
|
ms = (r_time2 - r_time1) * 1000;
|
|
|
|
|
|
|
|
Sys_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
|
|
|
|
(int) ms, dp_time, (int) rw_time, db_time, (int) se_time,
|
|
|
|
de_time, dv_time);
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-02-26 06:48:02 +00:00
|
|
|
R_EdgeDrawing (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
edge_t ledges[NUMSTACKEDGES +
|
|
|
|
((CACHE_SIZE - 1) / sizeof (edge_t)) + 1];
|
|
|
|
surf_t lsurfs[NUMSTACKSURFACES +
|
|
|
|
((CACHE_SIZE - 1) / sizeof (surf_t)) + 1];
|
|
|
|
|
|
|
|
if (auxedges) {
|
2001-02-19 21:15:25 +00:00
|
|
|
r_edges = auxedges;
|
2001-02-26 06:48:02 +00:00
|
|
|
} else {
|
|
|
|
r_edges = (edge_t *)
|
2007-04-11 22:03:36 +00:00
|
|
|
(((intptr_t) &ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_surfsonstack) {
|
|
|
|
surfaces = (surf_t *)
|
2007-04-11 22:03:36 +00:00
|
|
|
(((intptr_t) &lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
|
2001-02-19 21:15:25 +00:00
|
|
|
surf_max = &surfaces[r_cnumsurfs];
|
2001-02-26 06:48:02 +00:00
|
|
|
// surface 0 doesn't really exist; it's just a dummy because index 0
|
|
|
|
// is used to indicate no edge attached to surface
|
2001-02-19 21:15:25 +00:00
|
|
|
surfaces--;
|
|
|
|
R_SurfacePatch ();
|
|
|
|
}
|
|
|
|
|
|
|
|
R_BeginEdgeFrame ();
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
rw_time1 = Sys_DoubleTime ();
|
|
|
|
}
|
|
|
|
|
|
|
|
R_RenderWorld ();
|
|
|
|
|
|
|
|
if (r_drawculledpolys)
|
|
|
|
R_ScanEdges ();
|
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// only the world can be drawn back to front with no z reads or compares,
|
|
|
|
// just z writes, so have the driver turn z compares on now
|
2001-02-19 21:15:25 +00:00
|
|
|
D_TurnZOn ();
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
rw_time2 = Sys_DoubleTime ();
|
|
|
|
db_time1 = rw_time2;
|
|
|
|
}
|
|
|
|
|
2022-03-11 04:10:20 +00:00
|
|
|
R_DrawBrushEntitiesOnList ();
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
db_time2 = Sys_DoubleTime ();
|
|
|
|
se_time1 = db_time2;
|
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (!r_dspeeds->int_val) {
|
2001-05-15 21:13:07 +00:00
|
|
|
S_ExtraUpdate (); // don't let sound get messed up if going slow
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
if (!(r_drawpolys | r_drawculledpolys))
|
|
|
|
R_ScanEdges ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-05-15 04:50:53 +00:00
|
|
|
R_RenderView
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-05-15 04:50:53 +00:00
|
|
|
r_refdef must be set before the first call
|
2001-02-19 21:15:25 +00:00
|
|
|
*/
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-02-26 06:48:02 +00:00
|
|
|
R_RenderView_ (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
byte warpbuffer[WARP_WIDTH * WARP_HEIGHT];
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2004-04-16 03:24:10 +00:00
|
|
|
if (r_norefresh->int_val)
|
|
|
|
return;
|
2021-12-02 09:30:57 +00:00
|
|
|
if (!r_worldentity.renderer.model) {
|
|
|
|
return;
|
|
|
|
}
|
2004-04-16 03:24:10 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
r_warpbuffer = warpbuffer;
|
|
|
|
|
|
|
|
if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val)
|
|
|
|
r_time1 = Sys_DoubleTime ();
|
|
|
|
|
|
|
|
R_SetupFrame ();
|
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
R_MarkLeaves (); // done here so we know if we're in water
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-08-07 17:29:21 +00:00
|
|
|
R_PushDlights (vec3_origin);
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
// make FDIV fast. This reduces timing precision after we've been running for a
|
|
|
|
// while, so we don't do it globally. This also sets chop mode, and we do it
|
|
|
|
// here so that setup stuff like the refresh area calculations match what's
|
|
|
|
// done in screen.c
|
2002-06-07 15:09:20 +00:00
|
|
|
R_LowFPPrecision ();
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (!r_dspeeds->int_val) {
|
2001-05-15 21:13:07 +00:00
|
|
|
S_ExtraUpdate (); // don't let sound get messed up if going slow
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
R_EdgeDrawing ();
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (!r_dspeeds->int_val) {
|
2001-05-15 21:13:07 +00:00
|
|
|
S_ExtraUpdate (); // don't let sound get messed up if going slow
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
2001-02-26 06:48:02 +00:00
|
|
|
|
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
se_time2 = Sys_DoubleTime ();
|
|
|
|
de_time1 = se_time2;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_DrawEntitiesOnList ();
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
de_time2 = Sys_DoubleTime ();
|
|
|
|
dv_time1 = de_time2;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_DrawViewModel ();
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
if (r_dspeeds->int_val) {
|
2001-02-19 21:15:25 +00:00
|
|
|
dv_time2 = Sys_DoubleTime ();
|
|
|
|
dp_time1 = Sys_DoubleTime ();
|
|
|
|
}
|
|
|
|
|
|
|
|
R_DrawParticles ();
|
|
|
|
|
|
|
|
if (r_dspeeds->int_val)
|
|
|
|
dp_time2 = Sys_DoubleTime ();
|
|
|
|
|
|
|
|
if (r_dowarp)
|
2022-03-09 11:19:14 +00:00
|
|
|
D_WarpScreen ();
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
if (r_timegraph->int_val)
|
|
|
|
R_TimeGraph ();
|
|
|
|
|
2001-05-16 17:08:56 +00:00
|
|
|
if (r_zgraph->int_val)
|
|
|
|
R_ZGraph ();
|
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
if (r_aliasstats->int_val)
|
|
|
|
R_PrintAliasStats ();
|
2001-02-26 06:48:02 +00:00
|
|
|
|
2001-02-19 21:15:25 +00:00
|
|
|
if (r_speeds->int_val)
|
|
|
|
R_PrintTimes ();
|
|
|
|
|
|
|
|
if (r_dspeeds->int_val)
|
|
|
|
R_PrintDSpeeds ();
|
|
|
|
|
|
|
|
if (r_reportsurfout->int_val && r_outofsurfaces)
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("Short %d surfaces\n", r_outofsurfaces);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
|
|
|
if (r_reportedgeout->int_val && r_outofedges)
|
2007-11-06 10:17:14 +00:00
|
|
|
Sys_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3);
|
2001-02-19 21:15:25 +00:00
|
|
|
|
2001-05-15 21:13:07 +00:00
|
|
|
// back to high floating-point precision
|
2002-06-07 15:09:20 +00:00
|
|
|
R_HighFPPrecision ();
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-03-19 11:18:45 +00:00
|
|
|
//XXX FIXME static void R_RenderViewFishEye (void);
|
2003-01-15 16:53:34 +00:00
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
|
|
|
R_RenderView (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int dummy;
|
|
|
|
int delta;
|
|
|
|
|
|
|
|
delta = (byte *) & dummy - r_stack_start;
|
2001-02-19 21:15:25 +00:00
|
|
|
if (delta < -10000 || delta > 10000)
|
|
|
|
Sys_Error ("R_RenderView: called without enough stack");
|
|
|
|
|
2021-07-28 06:01:45 +00:00
|
|
|
if (Hunk_LowMark (0) & 3)
|
2001-02-19 21:15:25 +00:00
|
|
|
Sys_Error ("Hunk is missaligned");
|
|
|
|
|
2007-04-11 22:03:36 +00:00
|
|
|
if ((intptr_t) (&dummy) & 3)
|
2001-02-19 21:15:25 +00:00
|
|
|
Sys_Error ("Stack is missaligned");
|
|
|
|
|
2007-04-11 22:03:36 +00:00
|
|
|
if ((intptr_t) (&r_warpbuffer) & 3)
|
2001-02-19 21:15:25 +00:00
|
|
|
Sys_Error ("Globals are missaligned");
|
2021-03-19 11:18:45 +00:00
|
|
|
R_RenderView_ ();
|
|
|
|
/*XXX FIXME
|
2003-01-15 16:53:34 +00:00
|
|
|
if (!scr_fisheye->int_val)
|
|
|
|
R_RenderView_ ();
|
|
|
|
else
|
2021-03-19 11:18:45 +00:00
|
|
|
R_RenderViewFishEye ();*/
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
|
2001-02-26 06:48:02 +00:00
|
|
|
void
|
|
|
|
R_InitTurb (void)
|
2001-02-19 21:15:25 +00:00
|
|
|
{
|
2001-02-26 06:48:02 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < (SIN_BUFFER_SIZE); i++) {
|
|
|
|
sintable[i] = AMP + sin (i * 3.14159 * 2 / CYCLE) * AMP;
|
2001-05-15 04:50:53 +00:00
|
|
|
intsintable[i] = AMP2 + sin (i * 3.14159 * 2 / CYCLE) * AMP2;
|
|
|
|
// AMP2 not 20
|
2001-02-19 21:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-19 11:18:45 +00:00
|
|
|
/*XXX FIXME
|
2003-01-15 16:53:34 +00:00
|
|
|
#define BOX_FRONT 0
|
|
|
|
#define BOX_BEHIND 2
|
|
|
|
#define BOX_LEFT 3
|
|
|
|
#define BOX_RIGHT 1
|
|
|
|
#define BOX_TOP 4
|
|
|
|
#define BOX_BOTTOM 5
|
|
|
|
|
|
|
|
#define DEG(x) (x / M_PI * 180.0)
|
|
|
|
#define RAD(x) (x * M_PI / 180.0)
|
|
|
|
|
|
|
|
struct my_coords
|
|
|
|
{
|
|
|
|
double x, y, z;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct my_angles
|
|
|
|
{
|
|
|
|
double yaw, pitch, roll;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
x_rot (struct my_coords *c, double pitch)
|
|
|
|
{
|
|
|
|
double nx, ny, nz;
|
|
|
|
|
|
|
|
nx = c->x;
|
|
|
|
ny = (c->y * cos(pitch)) - (c->z * sin(pitch));
|
|
|
|
nz = (c->y * sin(pitch)) + (c->z * cos(pitch));
|
|
|
|
|
|
|
|
c->x = nx; c->y = ny; c->z = nz;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
y_rot (struct my_coords *c, double yaw)
|
|
|
|
{
|
|
|
|
double nx, ny, nz;
|
|
|
|
|
|
|
|
nx = (c->x * cos(yaw)) - (c->z * sin(yaw));
|
|
|
|
ny = c->y;
|
|
|
|
nz = (c->x * sin(yaw)) + (c->z * cos(yaw));
|
|
|
|
|
|
|
|
c->x = nx; c->y = ny; c->z = nz;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
z_rot (struct my_coords *c, double roll)
|
|
|
|
{
|
|
|
|
double nx, ny, nz;
|
|
|
|
|
|
|
|
nx = (c->x * cos(roll)) - (c->y * sin(roll));
|
|
|
|
ny = (c->x * sin(roll)) + (c->y * cos(roll));
|
|
|
|
nz = c->z;
|
|
|
|
|
|
|
|
c->x = nx; c->y = ny; c->z = nz;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
my_get_angles (struct my_coords *in_o, struct my_coords *in_u, struct my_angles *a)
|
|
|
|
{
|
|
|
|
double rad_yaw, rad_pitch;
|
|
|
|
struct my_coords o, u;
|
|
|
|
|
|
|
|
a->pitch = 0.0;
|
|
|
|
a->yaw = 0.0;
|
|
|
|
a->roll = 0.0;
|
|
|
|
|
|
|
|
// make a copy of the coords
|
|
|
|
o.x = in_o->x; o.y = in_o->y; o.z = in_o->z;
|
|
|
|
u.x = in_u->x; u.y = in_u->y; u.z = in_u->z;
|
|
|
|
|
|
|
|
// special case when looking straight up or down
|
|
|
|
if ((o.x == 0.0) && (o.z == 0.0)) {
|
|
|
|
a->yaw = 0.0;
|
|
|
|
if (o.y > 0.0) { a->pitch = -90.0; a->roll = 180.0 - DEG(atan2(u.x, u.z)); } // down
|
|
|
|
else { a->pitch = 90.0; a->roll = DEG(atan2(u.x, u.z)); } // up
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get yaw angle and then rotate o and u so that yaw = 0
|
|
|
|
rad_yaw = atan2 (-o.x, o.z);
|
|
|
|
a->yaw = DEG (rad_yaw);
|
|
|
|
|
|
|
|
y_rot (&o, -rad_yaw);
|
|
|
|
y_rot (&u, -rad_yaw);
|
|
|
|
|
|
|
|
// get pitch and then rotate o and u so that pitch = 0
|
|
|
|
rad_pitch = atan2 (-o.y, o.z);
|
|
|
|
a->pitch = DEG (rad_pitch);
|
|
|
|
|
|
|
|
x_rot (&o, -rad_pitch);
|
|
|
|
x_rot (&u, -rad_pitch);
|
|
|
|
|
|
|
|
// get roll
|
|
|
|
a->roll = DEG (-atan2(u.x, u.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_ypr (double yaw, double pitch, double roll, int side, struct my_angles *a)
|
|
|
|
{
|
|
|
|
struct my_coords o, u;
|
|
|
|
|
|
|
|
// get 'o' (observer) and 'u' ('this_way_up') depending on box side
|
|
|
|
switch(side) {
|
|
|
|
case BOX_FRONT:
|
|
|
|
o.x = 0.0; o.y = 0.0; o.z = 1.0;
|
|
|
|
u.x = 0.0; u.y = 1.0; u.z = 0.0;
|
|
|
|
break;
|
|
|
|
case BOX_BEHIND:
|
|
|
|
o.x = 0.0; o.y = 0.0; o.z = -1.0;
|
|
|
|
u.x = 0.0; u.y = 1.0; u.z = 0.0;
|
|
|
|
break;
|
|
|
|
case BOX_LEFT:
|
|
|
|
o.x = -1.0; o.y = 0.0; o.z = 0.0;
|
|
|
|
u.x = -1.0; u.y = 1.0; u.z = 0.0;
|
|
|
|
break;
|
|
|
|
case BOX_RIGHT:
|
|
|
|
o.x = 1.0; o.y = 0.0; o.z = 0.0;
|
|
|
|
u.x = 0.0; u.y = 1.0; u.z = 0.0;
|
|
|
|
break;
|
|
|
|
case BOX_TOP:
|
|
|
|
o.x = 0.0; o.y = -1.0; o.z = 0.0;
|
|
|
|
u.x = 0.0; u.y = 0.0; u.z = -1.0;
|
|
|
|
break;
|
|
|
|
case BOX_BOTTOM:
|
|
|
|
o.x = 0.0; o.y = 1.0; o.z = 0.0;
|
|
|
|
u.x = 0.0; u.y = 0.0; u.z = -1.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
z_rot (&o, roll); z_rot (&u, roll);
|
|
|
|
x_rot (&o, pitch); x_rot (&u, pitch);
|
|
|
|
y_rot (&o, yaw); y_rot (&u, yaw);
|
|
|
|
|
|
|
|
my_get_angles (&o, &u, a);
|
|
|
|
|
|
|
|
// normalise angles
|
|
|
|
while (a->yaw < 0.0) a->yaw += 360.0;
|
|
|
|
while (a->yaw > 360.0) a->yaw -= 360.0;
|
|
|
|
while (a->pitch < 0.0) a->pitch += 360.0;
|
|
|
|
while (a->pitch > 360.0) a->pitch -= 360.0;
|
|
|
|
while (a->roll < 0.0) a->roll += 360.0;
|
|
|
|
while (a->roll > 360.0) a->roll -= 360.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) {
|
|
|
|
for (x = 0; x < width; x++) {
|
|
|
|
double dx = x-width/2;
|
|
|
|
double dy = -(y-height/2);
|
|
|
|
double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width);
|
|
|
|
double roll = -atan2(dy, dx);
|
|
|
|
double sx = sin(yaw) * cos(roll);
|
|
|
|
double sy = sin(yaw) * sin(roll);
|
|
|
|
double sz = cos(yaw);
|
|
|
|
|
|
|
|
// determine which side of the box we need
|
|
|
|
double abs_x = fabs(sx);
|
|
|
|
double abs_y = fabs(sy);
|
|
|
|
double abs_z = fabs(sz);
|
|
|
|
int side;
|
|
|
|
double xs = 0, ys = 0;
|
|
|
|
if (abs_x > abs_y) {
|
|
|
|
if (abs_x > abs_z) { side = ((sx > 0.0) ? BOX_RIGHT : BOX_LEFT); }
|
|
|
|
else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); }
|
|
|
|
} else {
|
|
|
|
if (abs_y > abs_z) { side = ((sy > 0.0) ? BOX_TOP : BOX_BOTTOM); }
|
|
|
|
else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); }
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RC(x) ((x / 2.06) + 0.5)
|
|
|
|
#define R2(x) ((x / 2.03) + 0.5)
|
|
|
|
|
|
|
|
// scale up our vector [x,y,z] to the box
|
|
|
|
switch(side) {
|
|
|
|
case BOX_FRONT: xs = RC( sx / sz); ys = R2( sy / sz); break;
|
|
|
|
case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2( sy / -sz); break;
|
|
|
|
case BOX_LEFT: xs = RC( sz / -sx); ys = R2( sy / -sx); break;
|
|
|
|
case BOX_RIGHT: xs = RC(-sz / sx); ys = R2( sy / sx); break;
|
|
|
|
case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / -sy); break; //bot
|
|
|
|
case BOX_BOTTOM: xs = RC(-sx / sy); ys = R2( sz / -sy); break; //top??
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xs < 0.0) xs = 0.0;
|
|
|
|
if (xs >= 1.0) xs = 0.999;
|
|
|
|
if (ys < 0.0) ys = 0.0;
|
|
|
|
if (ys >= 1.0) ys = 0.999;
|
|
|
|
*buf++ = scrp+(((int)(xs*(double)width))+
|
|
|
|
((int)(ys*(double)height))*width)+
|
|
|
|
side*width*height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rendercopy (void *dest)
|
|
|
|
{
|
|
|
|
void *p = vid.buffer;
|
|
|
|
// XXX
|
|
|
|
vid.buffer = dest;
|
|
|
|
R_RenderView_ ();
|
|
|
|
vid.buffer = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
renderside (byte* bufs, double yaw, double pitch, double roll, int side)
|
|
|
|
{
|
|
|
|
struct my_angles a;
|
|
|
|
|
|
|
|
get_ypr (RAD(yaw), RAD(pitch), RAD(roll), side, &a);
|
|
|
|
if (side == BOX_RIGHT) { a.roll = -a.roll; a.pitch = -a.pitch; }
|
|
|
|
if (side == BOX_LEFT) { a.roll = -a.roll; a.pitch = -a.pitch; }
|
|
|
|
if (side == BOX_TOP) { a.yaw += 180.0; a.pitch = 180.0 - a.pitch; }
|
|
|
|
r_refdef.viewangles[YAW] = a.yaw;
|
|
|
|
r_refdef.viewangles[PITCH] = a.pitch;
|
|
|
|
r_refdef.viewangles[ROLL] = a.roll;
|
|
|
|
rendercopy (bufs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
renderlookup (byte **offs, byte* bufs)
|
|
|
|
{
|
2012-10-20 16:10:00 +00:00
|
|
|
byte *p = (byte*)vid.buffer;
|
2013-01-24 02:25:30 +00:00
|
|
|
unsigned x, y;
|
2003-01-15 16:53:34 +00:00
|
|
|
for (y = 0; y < vid.height; y++) {
|
|
|
|
for (x = 0; x < vid.width; x++, offs++)
|
|
|
|
p[x] = **offs;
|
|
|
|
p += vid.rowbytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
R_RenderViewFishEye (void)
|
|
|
|
{
|
|
|
|
int width = vid.width; //r_refdef.vrect.width;
|
|
|
|
int height = vid.height; //r_refdef.vrect.height;
|
|
|
|
int scrsize = width*height;
|
|
|
|
int fov = scr_ffov->int_val;
|
|
|
|
int views = scr_fviews->int_val;
|
|
|
|
double yaw = r_refdef.viewangles[YAW];
|
|
|
|
double pitch = r_refdef.viewangles[PITCH];
|
|
|
|
double roll = 0; //r_refdef.viewangles[ROLL];
|
|
|
|
static int pwidth = -1;
|
|
|
|
static int pheight = -1;
|
|
|
|
static int pfov = -1;
|
|
|
|
static int pviews = -1;
|
|
|
|
static byte *scrbufs = NULL;
|
|
|
|
static byte **offs = NULL;
|
|
|
|
|
|
|
|
if (fov < 1) fov = 1;
|
|
|
|
|
|
|
|
if (pwidth != width || pheight != height || pfov != fov) {
|
|
|
|
if (scrbufs) free (scrbufs);
|
|
|
|
if (offs) free (offs);
|
|
|
|
scrbufs = malloc (scrsize*6); // front|right|back|left|top|bottom
|
|
|
|
SYS_CHECKMEM (scrbufs);
|
|
|
|
offs = malloc (scrsize*sizeof(byte*));
|
|
|
|
SYS_CHECKMEM (offs);
|
|
|
|
pwidth = width;
|
|
|
|
pheight = height;
|
|
|
|
pfov = fov;
|
|
|
|
fisheyelookuptable (offs, width, height, scrbufs, ((double)fov)*M_PI/180.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (views != pviews) {
|
|
|
|
pviews = views;
|
|
|
|
memset (scrbufs, 0, scrsize*6);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (views) {
|
|
|
|
case 6: renderside (scrbufs+scrsize*2, yaw, pitch, roll, BOX_BEHIND);
|
|
|
|
case 5: renderside (scrbufs+scrsize*5, yaw, pitch, roll, BOX_BOTTOM);
|
|
|
|
case 4: renderside (scrbufs+scrsize*4, yaw, pitch, roll, BOX_TOP);
|
|
|
|
case 3: renderside (scrbufs+scrsize*3, yaw, pitch, roll, BOX_LEFT);
|
|
|
|
case 2: renderside (scrbufs+scrsize, yaw, pitch, roll, BOX_RIGHT);
|
|
|
|
default: renderside (scrbufs, yaw, pitch, roll, BOX_FRONT);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_refdef.viewangles[YAW] = yaw;
|
|
|
|
r_refdef.viewangles[PITCH] = pitch;
|
|
|
|
r_refdef.viewangles[ROLL] = roll;
|
|
|
|
renderlookup (offs, scrbufs);
|
2021-03-19 11:18:45 +00:00
|
|
|
}*/
|
2004-02-15 00:02:04 +00:00
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2011-12-23 03:51:47 +00:00
|
|
|
R_ClearState (void)
|
|
|
|
{
|
2021-12-02 09:30:57 +00:00
|
|
|
r_worldentity.renderer.model = 0;
|
2011-12-23 03:51:47 +00:00
|
|
|
R_ClearEfrags ();
|
|
|
|
R_ClearDlights ();
|
|
|
|
R_ClearParticles ();
|
|
|
|
}
|