fteqw/engine/client/renderer.c
Spoike 6e3f69f504 d3d rendering is diabled (framestate, read later - merged will compile just sw+gl for now).
fte particle scripts are disabled (classic works).
I'll fix these in the new year.
Redid framestate stuff again. Slightly better now, but this is the bulk of the changes here.
Reworked the renderqueue to provide batches of items instead of individual items. This cleans up the particle rendering code significantly, and is a step towards multiple concurrent particle systems. fte's scripted particles are broken as I'm trying to find a way to rework them to batch types together, rather than having to restart each batch after each particle when you have two particles in a trail. I'll fix it some time.
Reworked some alias model code regarding skeletal models. Added some conceptual skeletal bone control builtins available to csqc. Currently it can query the bone names and save off animation states, but can't animate - its just not complete.
Added more info to glsl custom shaders.
Updated surface sorting on halflife maps to properly cope with alphaed entities, rather than just texture-based blends (q2-style).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3095 fc73d0e0-1445-4013-8a0c-d673dee63da5
2008-12-23 02:55:20 +00:00

2742 lines
76 KiB
C

#include "quakedef.h"
#include "winquake.h"
#ifdef RGLQUAKE
#include "gl_draw.h"
#endif
#ifdef SWQUAKE
#include "sw_draw.h"
#endif
qboolean vid_isfullscreen;
#define VIDCOMMANDGROUP "Video config"
#define GRAPHICALNICETIES "Graphical Nicaties" //or eyecandy, which ever you prefer.
#define BULLETENVARS "BulletenBoard controls"
#define GLRENDEREROPTIONS "GL Renderer Options"
#define SWRENDEREROPTIONS "SW Renderer Options"
#define SCREENOPTIONS "Screen Options"
unsigned short d_8to16table[256];
unsigned int d_8to24bgrtable[256];
unsigned int d_8to24rgbtable[256];
unsigned int *d_8to32table = d_8to24bgrtable; //palette lookups while rendering r_pixbytes=4
extern int gl_anisotropy_factor;
// callbacks used for cvars
void SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue);
void SCR_Fov_Callback (struct cvar_s *var, char *oldvalue);
#if defined(RGLQUAKE)
void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldvalue);
#endif
cvar_t _vid_wait_override = FCVAR ("vid_wait", "_vid_wait_override", "",
CVAR_ARCHIVE);
cvar_t _windowed_mouse = SCVARF ("_windowed_mouse","1", CVAR_ARCHIVE);
cvar_t con_ocranaleds = SCVAR ("con_ocranaleds", "2");
cvar_t d_palconvwrite = SCVAR ("d_palconvwrite", "1");
cvar_t d_palremapsize = SCVARF ("d_palremapsize", "64",
CVAR_RENDERERLATCH);
cvar_t cl_cursor = SCVAR ("cl_cursor", "");
cvar_t cl_cursorsize = SCVAR ("cl_cursorsize", "32");
cvar_t cl_cursorbias = SCVAR ("cl_cursorbias", "4");
cvar_t gl_nocolors = SCVAR ("gl_nocolors", "0");
cvar_t gl_part_flame = SCVAR ("gl_part_flame", "1");
//opengl library
static cvar_t gl_driver = SCVARF ("gl_driver", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
#ifdef Q3SHADERS
cvar_t gl_shadeq1 = SCVARF ("gl_shadeq1", "0",
CVAR_SEMICHEAT);
cvar_t gl_shadeq1_name = SCVAR ("gl_shadeq1_name", "*");
//use if you want.
cvar_t gl_shadeq2 = SCVARF ("gl_shadeq2", "0",
CVAR_SEMICHEAT);
//use if you want.
cvar_t gl_shadeq3 = SCVARF ("gl_shadeq3", "1",
CVAR_SEMICHEAT);
extern cvar_t r_vertexlight;
#endif
cvar_t mod_md3flags = SCVAR ("mod_md3flags", "1");
cvar_t r_ambient = SCVARF ("r_ambient", "0",
CVAR_CHEAT);
cvar_t r_bloodstains = SCVAR ("r_bloodstains", "1");
cvar_t r_bouncysparks = SCVARF ("r_bouncysparks", "0",
CVAR_ARCHIVE);
cvar_t r_drawdisk = SCVAR ("r_drawdisk", "1");
cvar_t r_drawentities = SCVAR ("r_drawentities", "1");
cvar_t r_drawflat = SCVARF ("r_drawflat", "0",
CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK);
cvar_t r_drawflat_nonworldmodel = SCVAR ("r_drawflat_nonworldmodel", "0");
cvar_t r_drawviewmodel = SCVAR ("r_drawviewmodel", "1");
cvar_t r_drawviewmodelinvis = SCVAR ("r_drawviewmodelinvis", "0");
cvar_t r_dynamic = SCVARF ("r_dynamic", "1",
CVAR_ARCHIVE);
cvar_t r_fastsky = SCVAR ("r_fastsky", "0");
cvar_t r_fastskycolour = SCVARF ("r_fastskycolour", "0",
CVAR_RENDERERCALLBACK);
cvar_t r_fb_bmodels = SCVARF("gl_fb_bmodels", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_fb_models = FCVAR ("r_fb_models", "gl_fb_models", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_flashblend = SCVARF ("gl_flashblend", "0",
CVAR_ARCHIVE);
cvar_t r_floorcolour = SCVARF ("r_floorcolour", "255 255 255",
CVAR_RENDERERCALLBACK);
cvar_t r_floortexture = SCVARF ("r_floortexture", "",
CVAR_RENDERERCALLBACK);
cvar_t r_fullbright = SCVARF ("r_fullbright", "0",
CVAR_CHEAT);
cvar_t r_fullbrightSkins = SCVARF ("r_fullbrightSkins", "0",
CVAR_SEMICHEAT);
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
cvar_t r_lightstylesmooth = SCVAR ("r_lightstylesmooth", "0");
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
cvar_t r_loadlits = SCVAR ("r_loadlit", "1");
cvar_t r_menutint = SCVARF ("r_menutint", "0.68 0.4 0.13",
CVAR_RENDERERCALLBACK);
cvar_t r_netgraph = SCVAR ("r_netgraph", "0");
cvar_t r_nolerp = SCVAR ("r_nolerp", "0");
cvar_t r_nolightdir = SCVAR ("r_nolightdir", "0");
cvar_t r_novis = SCVAR ("r_novis", "0");
cvar_t r_part_rain = SCVARF ("r_part_rain", "0",
CVAR_ARCHIVE);
//whack in a value of 2 and you get easily visible players.
cvar_t r_sirds = SCVARF ("r_sirds", "0",
CVAR_SEMICHEAT);
cvar_t r_skyboxname = SCVARF ("r_skybox", "",
CVAR_RENDERERCALLBACK);
cvar_t r_speeds = SCVARF ("r_speeds", "0",
CVAR_CHEAT);
cvar_t r_stainfadeammount = SCVAR ("r_stainfadeammount", "1");
cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1");
cvar_t r_stains = SCVARFC("r_stains", "0.75",
CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback);
cvar_t r_wallcolour = SCVARF ("r_wallcolour", "255 255 255",
CVAR_RENDERERCALLBACK);
cvar_t r_walltexture = SCVARF ("r_walltexture", "",
CVAR_RENDERERCALLBACK);
cvar_t r_wateralpha = SCVAR ("r_wateralpha", "1");
cvar_t r_waterwarp = SCVARF ("r_waterwarp", "1",
CVAR_ARCHIVE);
cvar_t r_replacemodels = SCVARF ("r_replacemodels", "md3 md2",
CVAR_ARCHIVE);
//otherwise it would defeat the point.
cvar_t scr_allowsnap = SCVARF ("scr_allowsnap", "1",
CVAR_NOTFROMSERVER);
cvar_t scr_centersbar = SCVAR ("scr_centersbar", "0");
cvar_t scr_centertime = SCVAR ("scr_centertime", "2");
cvar_t scr_chatmodecvar = SCVAR ("scr_chatmode", "0");
cvar_t scr_conalpha = SCVARC ("scr_conalpha", "0.7",
Cvar_Limiter_ZeroToOne_Callback);
cvar_t scr_consize = SCVAR ("scr_consize", "0.5");
cvar_t scr_conspeed = SCVAR ("scr_conspeed", "300");
// 10 - 170
cvar_t scr_fov = SCVARFC("fov", "90",
CVAR_ARCHIVE,
SCR_Fov_Callback);
cvar_t scr_printspeed = SCVAR ("scr_printspeed", "8");
cvar_t scr_showpause = SCVAR ("showpause", "1");
cvar_t scr_showram = SCVAR ("showram", "1");
cvar_t scr_showturtle = SCVAR ("showturtle", "0");
cvar_t scr_sshot_compression = SCVAR ("scr_sshot_compression", "75");
cvar_t scr_sshot_type = SCVAR ("scr_sshot_type", "jpg");
cvar_t scr_viewsize = SCVARFC("viewsize", "100",
CVAR_ARCHIVE,
SCR_Viewsize_Callback);
cvar_t vid_conautoscale = SCVARF ("vid_conautoscale", "0",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK);
cvar_t vid_conheight = SCVARF ("vid_conheight", "480",
CVAR_ARCHIVE);
cvar_t vid_conwidth = SCVARF ("vid_conwidth", "640",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK);
//see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'.
cvar_t vid_renderer = SCVARF ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_allow_modex = SCVARF ("vid_allow_modex", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_bpp = SCVARF ("vid_bpp", "32",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_desktopsettings = SCVARF ("vid_desktopsettings", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_fullscreen = SCVARF ("vid_fullscreen", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_height = SCVARF ("vid_height", "480",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_multisample = SCVARF ("vid_multisample", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_refreshrate = SCVARF ("vid_displayfrequency", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
static cvar_t vid_stretch = SCVARF ("vid_stretch", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
//more readable defaults to match conwidth/conheight.
static cvar_t vid_width = SCVARF ("vid_width", "640",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
extern cvar_t bul_backcol;
extern cvar_t bul_forcemode;
extern cvar_t bul_norender;
extern cvar_t bul_nowater;
extern cvar_t bul_rippleamount;
extern cvar_t bul_ripplespeed;
extern cvar_t bul_scrollspeedx;
extern cvar_t bul_scrollspeedy;
extern cvar_t bul_sparkle;
extern cvar_t bul_text1;
extern cvar_t bul_text2;
extern cvar_t bul_text3;
extern cvar_t bul_text4;
extern cvar_t bul_text5;
extern cvar_t bul_text6;
extern cvar_t bul_textpalette;
extern cvar_t r_dodgytgafiles;
extern cvar_t r_dodgypcxfiles;
extern cvar_t r_drawentities;
extern cvar_t r_drawviewmodel;
extern cvar_t r_drawworld;
extern cvar_t r_fullbright;
extern cvar_t r_mirroralpha;
extern cvar_t r_netgraph;
extern cvar_t r_norefresh;
extern cvar_t r_novis;
extern cvar_t r_shadows;
extern cvar_t r_speeds;
extern cvar_t r_waterwarp;
void R_BulletenForce_f (void);
rendererstate_t currentrendererstate;
#if defined(SWQUAKE)
cvar_t d_smooth = SCVAR ("d_smooth", "0");
cvar_t r_aliastransadj = SCVAR ("r_aliastransadj", "100");
cvar_t r_aliastransbase = SCVAR ("r_aliastransbase", "200");
cvar_t r_clearcolor = SCVAR ("r_clearcolor", "218");
//cvar_t r_drawflat = SCVARF ("r_drawflat", "0",
// CVAR_CHEAT);
cvar_t r_draworder = SCVARF ("r_draworder", "0",
CVAR_CHEAT);
cvar_t r_dspeeds = SCVAR ("r_dspeeds", "0");
cvar_t r_graphheight = SCVAR ("r_graphheight", "15");
cvar_t r_maxedges = SCVAR ("r_maxedges", "0");
cvar_t r_maxsurfs = SCVAR ("r_maxsurfs", "0");
cvar_t r_numedges = SCVAR ("r_numedges", "0");
cvar_t r_numsurfs = SCVAR ("r_numsurfs", "0");
cvar_t r_aliasstats = SCVAR ("r_polymodelstats", "0");
cvar_t r_reportedgeout = SCVAR ("r_reportedgeout", "0");
cvar_t r_reportsurfout = SCVAR ("r_reportsurfout", "0");
cvar_t r_timegraph = SCVAR ("r_timegraph", "0");
cvar_t r_zgraph = SCVAR ("r_zgraph","0");
cvar_t sw_surfcachesize = SCVARF ("sw_surfcachesize", "0",
CVAR_RENDERERLATCH);
#endif
#if defined(RGLQUAKE) || defined(D3DQUAKE)
cvar_t gl_ati_truform = SCVAR ("gl_ati_truform", "0");
cvar_t gl_ati_truform_type = SCVAR ("gl_ati_truform_type", "1");
cvar_t gl_ati_truform_tesselation = SCVAR ("gl_ati_truform_tesselation", "3");
cvar_t gl_blend2d = SCVAR ("gl_blend2d", "1");
cvar_t gl_blendsprites = SCVAR ("gl_blendsprites", "1");
cvar_t gl_bump = SCVARF ("gl_bump", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t gl_compress = SCVARF ("gl_compress", "0",
CVAR_ARCHIVE);
cvar_t gl_conback = SCVARF ("gl_conback", "",
CVAR_RENDERERCALLBACK);
cvar_t gl_contrast = SCVAR ("gl_contrast", "1");
cvar_t gl_detail = SCVARF ("gl_detail", "0",
CVAR_ARCHIVE);
cvar_t gl_detailscale = SCVAR ("gl_detailscale", "5");
cvar_t gl_font = SCVARF ("gl_font", "",
CVAR_RENDERERCALLBACK);
cvar_t gl_fontinwardstep = SCVAR ("gl_fontinwardstep", "0");
cvar_t gl_lateswap = SCVAR ("gl_lateswap", "0");
cvar_t gl_lerpimages = SCVAR ("gl_lerpimages", "1");
cvar_t gl_lightmap_shift = SCVARF ("gl_lightmap_shift", "0",
CVAR_ARCHIVE | CVAR_LATCH);
//cvar_t gl_lightmapmode = SCVARF("gl_lightmapmode", "",
// CVAR_ARCHIVE);
cvar_t gl_load24bit = SCVARF ("gl_load24bit", "1",
CVAR_ARCHIVE);
cvar_t gl_max_size = SCVAR ("gl_max_size", "1024");
cvar_t gl_maxshadowlights = SCVARF ("gl_maxshadowlights", "2",
CVAR_ARCHIVE);
cvar_t gl_menutint_shader = SCVAR ("gl_menutint_shader", "1");
//by setting to 64 or something, you can use this as a wallhack
cvar_t gl_mindist = SCVARF ("gl_mindist", "4",
CVAR_CHEAT);
cvar_t gl_motionblur = SCVARF ("gl_motionblur", "0",
CVAR_ARCHIVE);
cvar_t gl_motionblurscale = SCVAR ("gl_motionblurscale", "1");
cvar_t gl_mylumassuck = SCVAR ("gl_mylumassuck", "0");
cvar_t gl_nobind = SCVAR ("gl_nobind", "0");
cvar_t gl_overbright = SCVARF ("gl_overbright", "0",
CVAR_ARCHIVE);
cvar_t gl_overbright_all = SCVARF ("gl_overbright_all", "0",
CVAR_ARCHIVE);
cvar_t gl_picmip = SCVAR ("gl_picmip", "0");
cvar_t gl_picmip2d = SCVAR ("gl_picmip2d", "0");
cvar_t gl_nohwblend = SCVAR ("gl_nohwblend","1");
cvar_t gl_savecompressedtex = SCVAR ("gl_savecompressedtex", "0");
cvar_t gl_schematics = SCVAR ("gl_schematics", "0");
cvar_t gl_skyboxdist = SCVAR ("gl_skyboxdist", "2300");
cvar_t gl_smoothcrosshair = SCVAR ("gl_smoothcrosshair", "1");
//gl blends. Set this to 1 to stop the outside of your conchars from being visible
cvar_t gl_smoothfont = SCVARF ("gl_smoothfont", "1",
CVAR_RENDERERCALLBACK);
#ifdef SPECULAR
cvar_t gl_specular = SCVAR ("gl_specular", "0");
#endif
// The callbacks are not in D3D yet (also ugly way of seperating this)
#ifdef RGLQUAKE
cvar_t gl_texture_anisotropic_filtering = SCVARFC("gl_texture_anisotropic_filtering", "0",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Texture_Anisotropic_Filtering_Callback);
cvar_t gl_texturemode = SCVARFC("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Texturemode_Callback);
cvar_t gl_texturemode2d = SCVARFC("gl_texturemode2d", "GL_LINEAR",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Texturemode2d_Callback);
#endif
cvar_t gl_triplebuffer = SCVARF ("gl_triplebuffer", "1",
CVAR_ARCHIVE);
cvar_t gl_ztrick = SCVAR ("gl_ztrick", "0");
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0",
CVAR_ARCHIVE);
cvar_t r_shadow_bumpscale_basetexture = SCVAR ("r_shadow_bumpscale_basetexture", "4");
cvar_t r_shadow_bumpscale_bumpmap = SCVAR ("r_shadow_bumpscale_bumpmap", "10");
cvar_t r_shadow_glsl_offsetmapping = SCVAR ("r_shadow_glsl_offsetmapping", "0");
cvar_t r_shadow_glsl_offsetmapping_bias = SCVAR ("r_shadow_glsl_offsetmapping_bias", "0.04");
cvar_t r_shadow_glsl_offsetmapping_scale = SCVAR ("r_shadow_glsl_offsetmapping_scale", "-0.04");
cvar_t r_shadow_realtime_world = SCVARF ("r_shadow_realtime_world", "0",
CVAR_CHEAT | CVAR_ARCHIVE);
cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0.8",
CVAR_CHEAT);
cvar_t r_shadows = SCVARF ("r_shadows", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "1");
cvar_t vid_preservegamma = SCVAR ("vid_preservegamma", "1");
cvar_t vid_hardwaregamma = SCVARF ("vid_hardwaregamma", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_desktopgamma = SCVARF ("vid_desktopgamma", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
extern cvar_t gl_dither;
extern cvar_t gl_maxdist;
extern cvar_t r_waterlayers;
#endif
#if defined(RGLQUAKE) || defined(D3DQUAKE)
void GLD3DRenderer_Init(void)
{
Cvar_Register (&gl_mindist, GLRENDEREROPTIONS);
Cvar_Register (&gl_load24bit, GRAPHICALNICETIES);
}
#endif
#if defined(RGLQUAKE)
void GLRenderer_Init(void)
{
extern cvar_t gl_contrast;
//screen
Cvar_Register (&gl_triplebuffer, GLRENDEREROPTIONS);
Cvar_Register (&vid_preservegamma, GLRENDEREROPTIONS);
Cvar_Register (&vid_hardwaregamma, GLRENDEREROPTIONS);
Cvar_Register (&vid_desktopgamma, GLRENDEREROPTIONS);
//renderer
Cvar_Register (&r_mirroralpha, GLRENDEREROPTIONS);
Cvar_Register (&r_norefresh, GLRENDEREROPTIONS);
Cvar_Register (&gl_clear, GLRENDEREROPTIONS);
Cvar_Register (&gl_cull, GLRENDEREROPTIONS);
Cvar_Register (&gl_smoothmodels, GRAPHICALNICETIES);
Cvar_Register (&gl_affinemodels, GLRENDEREROPTIONS);
Cvar_Register (&gl_nohwblend, GLRENDEREROPTIONS);
Cvar_Register (&r_flashblend, GLRENDEREROPTIONS);
Cvar_Register (&gl_playermip, GLRENDEREROPTIONS);
Cvar_Register (&gl_nocolors, GLRENDEREROPTIONS);
Cvar_Register (&gl_finish, GLRENDEREROPTIONS);
Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS);
Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS);
Cvar_Register (&r_shadows, GLRENDEREROPTIONS);
Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS);
Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_bumpmap, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_world, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_world_lightmaps, GLRENDEREROPTIONS);
Cvar_Register (&gl_keeptjunctions, GLRENDEREROPTIONS);
Cvar_Register (&gl_reporttjunctions, GLRENDEREROPTIONS);
Cvar_Register (&gl_ztrick, GLRENDEREROPTIONS);
Cvar_Register (&gl_motionblur, GLRENDEREROPTIONS);
Cvar_Register (&gl_motionblurscale, GLRENDEREROPTIONS);
Cvar_Register (&gl_max_size, GLRENDEREROPTIONS);
Cvar_Register (&gl_maxdist, GLRENDEREROPTIONS);
Cvar_Register (&vid_multisample, GLRENDEREROPTIONS);
Cvar_Register (&gl_fontinwardstep, GRAPHICALNICETIES);
Cvar_Register (&gl_font, GRAPHICALNICETIES);
Cvar_Register (&gl_conback, GRAPHICALNICETIES);
Cvar_Register (&gl_smoothfont, GRAPHICALNICETIES);
Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES);
Cvar_Register (&gl_bump, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping_scale, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping_bias, GRAPHICALNICETIES);
Cvar_Register (&gl_contrast, GLRENDEREROPTIONS);
#ifdef R_XFLIP
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
#endif
Cvar_Register (&gl_specular, GRAPHICALNICETIES);
// Cvar_Register (&gl_lightmapmode, GLRENDEREROPTIONS);
#ifdef WATERLAYERS
Cvar_Register (&r_waterlayers, GRAPHICALNICETIES);
#endif
Cvar_Register (&gl_nobind, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip2d, GLRENDEREROPTIONS);
Cvar_Register (&r_drawdisk, GLRENDEREROPTIONS);
Cvar_Register (&gl_texturemode, GLRENDEREROPTIONS);
Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS);
Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS);
Cvar_Register (&gl_savecompressedtex, GLRENDEREROPTIONS);
Cvar_Register (&gl_compress, GLRENDEREROPTIONS);
Cvar_Register (&gl_driver, GLRENDEREROPTIONS);
Cvar_Register (&gl_detail, GRAPHICALNICETIES);
Cvar_Register (&gl_detailscale, GRAPHICALNICETIES);
Cvar_Register (&gl_overbright, GRAPHICALNICETIES);
Cvar_Register (&gl_overbright_all, GRAPHICALNICETIES);
Cvar_Register (&gl_dither, GRAPHICALNICETIES);
Cvar_Register (&r_fb_bmodels, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform_type, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform_tesselation, GRAPHICALNICETIES);
Cvar_Register (&gl_skyboxdist, GLRENDEREROPTIONS);
Cvar_Register (&r_wallcolour, GLRENDEREROPTIONS);
Cvar_Register (&r_floorcolour, GLRENDEREROPTIONS);
Cvar_Register (&r_walltexture, GLRENDEREROPTIONS);
Cvar_Register (&r_floortexture, GLRENDEREROPTIONS);
Cvar_Register (&r_vertexdlights, GLRENDEREROPTIONS);
Cvar_Register (&gl_schematics, GLRENDEREROPTIONS);
#ifdef Q3SHADERS
Cvar_Register (&r_vertexlight, GLRENDEREROPTIONS);
Cvar_Register (&gl_shadeq1, GLRENDEREROPTIONS);
Cvar_Register (&gl_shadeq1_name, GLRENDEREROPTIONS);
Cvar_Register (&gl_shadeq2, GLRENDEREROPTIONS);
Cvar_Register (&gl_shadeq3, GLRENDEREROPTIONS);
Cvar_Register (&gl_blend2d, GLRENDEREROPTIONS);
#endif
Cvar_Register (&gl_blendsprites, GLRENDEREROPTIONS);
Cvar_Register (&gl_mylumassuck, GLRENDEREROPTIONS);
Cvar_Register (&gl_lightmap_shift, GLRENDEREROPTIONS);
Cvar_Register (&gl_menutint_shader, GLRENDEREROPTIONS);
R_BloomRegister();
}
#endif
#if defined(SWQUAKE)
extern cvar_t d_subdiv16;
extern cvar_t d_mipcap;
extern cvar_t d_mipscale;
extern cvar_t d_smooth;
void SWRenderer_Init(void)
{
Cvar_Register (&d_subdiv16, SWRENDEREROPTIONS);
Cvar_Register (&d_mipcap, SWRENDEREROPTIONS);
Cvar_Register (&d_mipscale, SWRENDEREROPTIONS);
Cvar_Register (&d_smooth, SWRENDEREROPTIONS);
Cvar_Register (&r_maxsurfs, SWRENDEREROPTIONS);
Cvar_Register (&r_numsurfs, SWRENDEREROPTIONS);
Cvar_Register (&r_maxedges, SWRENDEREROPTIONS);
Cvar_Register (&r_numedges, SWRENDEREROPTIONS);
Cvar_Register (&r_sirds, SWRENDEREROPTIONS);
Cvar_Register (&r_aliastransbase, SWRENDEREROPTIONS);
Cvar_Register (&r_aliastransadj, SWRENDEREROPTIONS);
Cvar_Register (&r_reportedgeout, SWRENDEREROPTIONS);
Cvar_Register (&r_aliasstats, SWRENDEREROPTIONS);
Cvar_Register (&r_clearcolor, SWRENDEREROPTIONS);
Cvar_Register (&r_timegraph, SWRENDEREROPTIONS);
Cvar_Register (&r_draworder, SWRENDEREROPTIONS);
Cvar_Register (&r_zgraph, SWRENDEREROPTIONS);
Cvar_Register (&r_graphheight, SWRENDEREROPTIONS);
Cvar_Register (&r_aliasstats, SWRENDEREROPTIONS);
Cvar_Register (&r_dspeeds, SWRENDEREROPTIONS);
Cvar_Register (&r_ambient, SWRENDEREROPTIONS);
Cvar_Register (&r_ambient, SWRENDEREROPTIONS);
Cvar_Register (&r_reportsurfout, SWRENDEREROPTIONS);
Cvar_Register (&d_palconvwrite, SWRENDEREROPTIONS);
Cvar_Register (&d_palremapsize, SWRENDEREROPTIONS);
Cvar_Register (&sw_surfcachesize, SWRENDEREROPTIONS);
}
#endif
void R_InitTextures (void)
{
int x,y, m;
qbyte *dest;
// create a simple checkerboard texture for the default
r_notexture_mip = Z_Malloc (sizeof(texture_t) + 16*16+8*8+4*4+2*2);
r_notexture_mip->pixbytes = 1;
r_notexture_mip->width = r_notexture_mip->height = 16;
r_notexture_mip->offsets[0] = sizeof(texture_t);
r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
for (m=0 ; m<4 ; m++)
{
dest = (qbyte *)r_notexture_mip + r_notexture_mip->offsets[m];
for (y=0 ; y< (16>>m) ; y++)
for (x=0 ; x< (16>>m) ; x++)
{
if ( (y< (8>>m) ) ^ (x< (8>>m) ) )
*dest++ = 0;
else
*dest++ = 0xff;
}
}
}
void R_SetRenderer_f (void);
void Renderer_Init(void)
{
currentrendererstate.bpp = -1; //no previous.
currentrendererstate.renderer = -1;
Cmd_AddCommand("setrenderer", R_SetRenderer_f);
Cmd_AddCommand("vid_restart", R_RestartRenderer_f);
#if defined(RGLQUAKE) || defined(D3DQUAKE)
GLD3DRenderer_Init();
#endif
#if defined(RGLQUAKE)
GLRenderer_Init();
#endif
#if defined(SWQUAKE)
SWRenderer_Init();
#endif
Cvar_Register (&r_novis, GLRENDEREROPTIONS);
//but register ALL vid_ commands.
Cvar_Register (&_vid_wait_override, VIDCOMMANDGROUP);
Cvar_Register (&vid_stretch, VIDCOMMANDGROUP);
Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP);
Cvar_Register (&vid_renderer, VIDCOMMANDGROUP);
Cvar_Register (&vid_fullscreen, VIDCOMMANDGROUP);
// Cvar_Register (&vid_stretch, VIDCOMMANDGROUP);
Cvar_Register (&vid_bpp, VIDCOMMANDGROUP);
Cvar_Register (&vid_conwidth, VIDCOMMANDGROUP);
Cvar_Register (&vid_conheight, VIDCOMMANDGROUP);
Cvar_Register (&vid_conautoscale, VIDCOMMANDGROUP);
Cvar_Register (&vid_allow_modex, VIDCOMMANDGROUP);
Cvar_Register (&vid_width, VIDCOMMANDGROUP);
Cvar_Register (&vid_height, VIDCOMMANDGROUP);
Cvar_Register (&vid_refreshrate, VIDCOMMANDGROUP);
Cvar_Register (&vid_desktopsettings, VIDCOMMANDGROUP);
Cvar_Register (&r_skyboxname, GRAPHICALNICETIES);
Cvar_Register(&r_dodgytgafiles, "Bug fixes");
Cvar_Register(&r_dodgypcxfiles, "Bug fixes");
Cvar_Register(&r_loadlits, GRAPHICALNICETIES);
Cvar_Register(&r_lightstylesmooth, GRAPHICALNICETIES);
Cvar_Register(&r_lightstylespeed, GRAPHICALNICETIES);
Cvar_Register(&r_stains, GRAPHICALNICETIES);
Cvar_Register(&r_stainfadetime, GRAPHICALNICETIES);
Cvar_Register(&r_stainfadeammount, GRAPHICALNICETIES);
Cvar_Register(&scr_viewsize, SCREENOPTIONS);
Cvar_Register(&scr_fov, SCREENOPTIONS);
Cvar_Register(&scr_chatmodecvar, SCREENOPTIONS);
Cvar_Register (&scr_sshot_type, SCREENOPTIONS);
Cvar_Register (&scr_sshot_compression, SCREENOPTIONS);
Cvar_Register(&cl_cursor, SCREENOPTIONS);
Cvar_Register(&cl_cursorsize, SCREENOPTIONS);
Cvar_Register(&cl_cursorbias, SCREENOPTIONS);
//screen
Cvar_Register (&scr_conspeed, SCREENOPTIONS);
Cvar_Register (&scr_conalpha, SCREENOPTIONS);
Cvar_Register (&scr_showram, SCREENOPTIONS);
Cvar_Register (&scr_showturtle, SCREENOPTIONS);
Cvar_Register (&scr_showpause, SCREENOPTIONS);
Cvar_Register (&scr_centertime, SCREENOPTIONS);
Cvar_Register (&scr_printspeed, SCREENOPTIONS);
Cvar_Register (&scr_allowsnap, SCREENOPTIONS);
Cvar_Register (&scr_consize, SCREENOPTIONS);
Cvar_Register (&scr_centersbar, SCREENOPTIONS);
Cvar_Register(&r_bloodstains, GRAPHICALNICETIES);
Cvar_Register(&r_fullbrightSkins, GRAPHICALNICETIES);
Cvar_Register (&mod_md3flags, GRAPHICALNICETIES);
//renderer
Cvar_Register (&r_fullbright, SCREENOPTIONS);
Cvar_Register (&r_drawentities, GRAPHICALNICETIES);
Cvar_Register (&r_drawviewmodel, GRAPHICALNICETIES);
Cvar_Register (&r_drawviewmodelinvis, GRAPHICALNICETIES);
Cvar_Register (&r_waterwarp, GRAPHICALNICETIES);
Cvar_Register (&r_speeds, SCREENOPTIONS);
Cvar_Register (&r_netgraph, SCREENOPTIONS);
Cvar_Register (&r_dynamic, GRAPHICALNICETIES);
Cvar_Register (&r_lightmap_saturation, GRAPHICALNICETIES);
Cvar_Register (&r_nolerp, GRAPHICALNICETIES);
Cvar_Register (&r_nolightdir, GRAPHICALNICETIES);
Cvar_Register (&r_fastsky, GRAPHICALNICETIES);
Cvar_Register (&r_fastskycolour, GRAPHICALNICETIES);
Cvar_Register (&r_wateralpha, GRAPHICALNICETIES);
Cvar_Register (&r_drawflat, GRAPHICALNICETIES);
Cvar_Register (&r_drawflat_nonworldmodel, GRAPHICALNICETIES);
Cvar_Register (&r_menutint, GRAPHICALNICETIES);
Cvar_Register (&r_fb_models, GRAPHICALNICETIES);
Cvar_Register (&r_replacemodels, GRAPHICALNICETIES);
//bulletens
Cvar_Register(&bul_nowater, BULLETENVARS);
Cvar_Register(&bul_rippleamount, BULLETENVARS);
Cvar_Register(&bul_ripplespeed, BULLETENVARS);
Cvar_Register(&bul_forcemode, BULLETENVARS);
Cvar_Register(&bul_sparkle, BULLETENVARS);
Cvar_Register(&bul_textpalette, BULLETENVARS);
Cvar_Register(&bul_scrollspeedy, BULLETENVARS);
Cvar_Register(&bul_scrollspeedx, BULLETENVARS);
Cvar_Register(&bul_backcol, BULLETENVARS);
Cvar_Register(&bul_text6, BULLETENVARS); //reverse order, to get forwards ordered console vars.
Cvar_Register(&bul_text5, BULLETENVARS);
Cvar_Register(&bul_text4, BULLETENVARS);
Cvar_Register(&bul_text3, BULLETENVARS);
Cvar_Register(&bul_text2, BULLETENVARS);
Cvar_Register(&bul_text1, BULLETENVARS);
// misc
Cvar_Register(&con_ocranaleds, "Console controls");
Cvar_Register(&bul_norender, BULLETENVARS); //find this one first...
Cmd_AddCommand("bul_make", R_BulletenForce_f);
P_InitParticleSystem();
R_InitTextures();
RQ_Init();
}
mpic_t *(*Draw_SafePicFromWad) (char *name);
mpic_t *(*Draw_CachePic) (char *path);
mpic_t *(*Draw_SafeCachePic) (char *path);
void (*Draw_Init) (void);
void (*Draw_ReInit) (void);
void (*Draw_Character) (int x, int y, unsigned int num);
void (*Draw_ColouredCharacter) (int x, int y, unsigned int num);
void (*Draw_String) (int x, int y, const qbyte *str);
void (*Draw_TinyCharacter) (int x, int y, unsigned int num);
void (*Draw_Alt_String) (int x, int y, const qbyte *str);
void (*Draw_Crosshair) (void);
void (*Draw_DebugChar) (qbyte num);
void (*Draw_Pic) (int x, int y, mpic_t *pic);
void (*Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic);
void (*Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height);
void (*Draw_TransPic) (int x, int y, mpic_t *pic);
void (*Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *image, qbyte *translation);
void (*Draw_ConsoleBackground) (int lines);
void (*Draw_EditorBackground) (int lines);
void (*Draw_TileClear) (int x, int y, int w, int h);
void (*Draw_Fill) (int x, int y, int w, int h, unsigned int c);
void (*Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b);
void (*Draw_FadeScreen) (void);
void (*Draw_BeginDisc) (void);
void (*Draw_EndDisc) (void);
void (*Draw_Image) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic); //gl-style scaled/coloured/subpic
void (*Draw_ImageColours) (float r, float g, float b, float a);
void (*R_Init) (void);
void (*R_DeInit) (void);
void (*R_ReInit) (void);
void (*R_RenderView) (void); // must set r_refdef first
qboolean (*R_CheckSky) (void);
void (*R_SetSky) (char *name, float rotate, vec3_t axis);
void (*R_NewMap) (void);
void (*R_PreNewMap) (void);
int (*R_LightPoint) (vec3_t point);
void (*R_PushDlights) (void);
void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius);
void (*R_LessenStains) (void);
void (*Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up...
void (*Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down
void (*Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette)
void (*Mod_Init) (void);
void (*Mod_ClearAll) (void);
struct model_s *(*Mod_ForName) (char *name, qboolean crash);
struct model_s *(*Mod_FindName) (char *name);
void *(*Mod_Extradata) (struct model_s *mod); // handles caching
void (*Mod_TouchModel) (char *name);
void (*Mod_NowLoadExternal) (void);
void (*Mod_Think) (void);
//qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms);
//int (*Mod_TagNumForName) (struct model_s *model, char *name);
int (*Mod_SkinForName) (struct model_s *model, char *name);
qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette);
void (*VID_DeInit) (void);
void (*VID_LockBuffer) (void);
void (*VID_UnlockBuffer) (void);
void (*D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height);
void (*D_EndDirectRect) (int x, int y, int width, int height);
void (*VID_ForceLockState) (int lk);
int (*VID_ForceUnlockedAndReturnState) (void);
void (*VID_SetPalette) (unsigned char *palette);
void (*VID_ShiftPalette) (unsigned char *palette);
char *(*VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
void (*VID_SetWindowCaption) (char *msg);
void (*SCR_UpdateScreen) (void);
r_qrenderer_t qrenderer=-1;
char *q_renderername = "Non-Selected renderer";
rendererinfo_t dedicatedrendererinfo = {
//ALL builds need a 'none' renderer, as 0.
"Dedicated server",
{
"none",
"dedicated",
"terminal",
"sv"
},
QR_NONE,
NULL, //Draw_PicFromWad; //Not supported
NULL, //Draw_CachePic;
NULL, //Draw_SafeCachePic;
NULL, //Draw_Init;
NULL, //Draw_Init;
NULL, //Draw_Character;
NULL, //Draw_ColouredCharacter;
NULL, //Draw_TinyCharacter;
NULL, //Draw_String;
NULL, //Draw_Alt_String;
NULL, //Draw_Crosshair;
NULL, //Draw_DebugChar;
NULL, //Draw_Pic;
NULL, //Draw_SubPic;
NULL, //Draw_TransPic;
NULL, //Draw_TransPicTranslate;
NULL, //Draw_ConsoleBackground;
NULL, //Draw_EditorBackground;
NULL, //Draw_TileClear;
NULL, //Draw_Fill;
NULL, //Draw_FillRGB;
NULL, //Draw_FadeScreen;
NULL, //Draw_BeginDisc;
NULL, //Draw_EndDisc;
NULL, //I'm lazy.
NULL, //Draw_Image
NULL, //Draw_ImageColours
NULL, //R_Init;
NULL, //R_DeInit;
NULL, //R_ReInit;
NULL, //R_RenderView;
NULL, //R_CheckSky;
NULL, //R_SetSky;
NULL, //R_NewMap;
NULL, //R_PreNewMap
NULL, //R_LightPoint;
NULL, //R_PushDlights;
NULL, //R_AddStain;
NULL, //R_LessenStains;
NULL, //Media_ShowFrameBGR_24_Flip;
NULL, //Media_ShowFrameRGBA_32;
NULL, //Media_ShowFrame8bit;
#ifdef SWQUAKE
SWMod_Init,
SWMod_ClearAll,
SWMod_ForName,
SWMod_FindName,
SWMod_Extradata,
SWMod_TouchModel,
SWMod_NowLoadExternal,
SWMod_Think,
#elif defined(RGLQUAKE) || defined(D3DQUAKE)
GLMod_Init,
GLMod_ClearAll,
GLMod_ForName,
GLMod_FindName,
GLMod_Extradata,
GLMod_TouchModel,
GLMod_NowLoadExternal,
GLMod_Think,
#else
#error "Need logic here!"
#endif
NULL, //Mod_GetTag
NULL, //fixme: server will need this one at some point.
NULL,
NULL, //VID_Init,
NULL, //VID_DeInit,
NULL, //VID_LockBuffer,
NULL, //VID_UnlockBuffer,
NULL, //D_BeginDirectRect,
NULL, //D_EndDirectRect,
NULL, //VID_ForceLockState,
NULL, //VID_ForceUnlockedAndReturnState,
NULL, //VID_SetPalette,
NULL, //VID_ShiftPalette,
NULL, //VID_GetRGBInfo,
NULL, //set caption
NULL, //SCR_UpdateScreen;
""
};
rendererinfo_t *pdedicatedrendererinfo = &dedicatedrendererinfo;
#ifdef SWQUAKE
rendererinfo_t softwarerendererinfo = {
"Software rendering",
{
"sw",
"software",
},
QR_SOFTWARE,
SWDraw_PicFromWad,
SWDraw_CachePic,
SWDraw_SafeCachePic,
SWDraw_Init,
SWDraw_Init,
SWDraw_Character,
SWDraw_ColouredCharacter,
SWDraw_TinyCharacter,
SWDraw_String,
SWDraw_Alt_String,
SWDraw_Crosshair,
SWDraw_DebugChar,
SWDraw_Pic,
NULL,//SWDraw_ScaledPic,
SWDraw_SubPic,
SWDraw_TransPic,
SWDraw_TransPicTranslate,
SWDraw_ConsoleBackground,
SWDraw_EditorBackground,
SWDraw_TileClear,
SWDraw_Fill,
SWDraw_FillRGB,
SWDraw_FadeScreen,
SWDraw_BeginDisc,
SWDraw_EndDisc,
SWDraw_Image,
SWDraw_ImageColours,
SWR_Init,
SWR_DeInit,
NULL,//SWR_ReInit,
SWR_RenderView,
SWR_CheckSky,
SWR_SetSky,
SWR_NewMap,
NULL,
SWR_LightPoint,
SWR_PushDlights,
SWR_AddStain,
SWR_LessenStains,
MediaSW_ShowFrameBGR_24_Flip,
MediaSW_ShowFrameRGBA_32,
MediaSW_ShowFrame8bit,
SWMod_Init,
SWMod_ClearAll,
SWMod_ForName,
SWMod_FindName,
SWMod_Extradata,
SWMod_TouchModel,
SWMod_NowLoadExternal,
SWMod_Think,
NULL, //Mod_GetTag
NULL, //Mod_TagForName
NULL,
SWVID_Init,
SWVID_Shutdown,
SWVID_LockBuffer,
SWVID_UnlockBuffer,
SWD_BeginDirectRect,
SWD_EndDirectRect,
SWVID_ForceLockState,
SWVID_ForceUnlockedAndReturnState,
SWVID_SetPalette,
SWVID_ShiftPalette,
SWVID_GetRGBInfo,
SWVID_SetCaption,
SWSCR_UpdateScreen,
""
};
rendererinfo_t *psoftwarerendererinfo = &softwarerendererinfo;
#endif
#ifdef RGLQUAKE
rendererinfo_t openglrendererinfo = {
"OpenGL",
{
"gl",
"opengl",
"hardware",
},
QR_OPENGL,
GLDraw_SafePicFromWad,
GLDraw_CachePic,
GLDraw_SafeCachePic,
GLDraw_Init,
GLDraw_ReInit,
GLDraw_Character,
GLDraw_ColouredCharacter,
GLDraw_TinyCharacter,
GLDraw_String,
GLDraw_Alt_String,
GLDraw_Crosshair,
GLDraw_DebugChar,
GLDraw_Pic,
GLDraw_ScalePic,
GLDraw_SubPic,
GLDraw_TransPic,
GLDraw_TransPicTranslate,
GLDraw_ConsoleBackground,
GLDraw_EditorBackground,
GLDraw_TileClear,
GLDraw_Fill,
GLDraw_FillRGB,
GLDraw_FadeScreen,
GLDraw_BeginDisc,
GLDraw_EndDisc,
GLDraw_Image,
GLDraw_ImageColours,
GLR_Init,
GLR_DeInit,
GLR_ReInit,
GLR_RenderView,
GLR_CheckSky,
GLR_SetSky,
GLR_NewMap,
GLR_PreNewMap,
GLR_LightPoint,
GLR_PushDlights,
GLR_AddStain,
GLR_LessenStains,
MediaGL_ShowFrameBGR_24_Flip,
MediaGL_ShowFrameRGBA_32,
MediaGL_ShowFrame8bit,
GLMod_Init,
GLMod_ClearAll,
GLMod_ForName,
GLMod_FindName,
GLMod_Extradata,
GLMod_TouchModel,
GLMod_NowLoadExternal,
GLMod_Think,
Mod_GetTag,
Mod_TagNumForName,
Mod_SkinNumForName,
GLVID_Init,
GLVID_DeInit,
GLVID_LockBuffer,
GLVID_UnlockBuffer,
GLD_BeginDirectRect,
GLD_EndDirectRect,
GLVID_ForceLockState,
GLVID_ForceUnlockedAndReturnState,
GLVID_SetPalette,
GLVID_ShiftPalette,
GLVID_GetRGBInfo,
GLVID_SetCaption, //setcaption
GLSCR_UpdateScreen,
""
};
rendererinfo_t *popenglrendererinfo = &openglrendererinfo;
#endif
#ifdef D3DQUAKE
rendererinfo_t d3d7rendererinfo;
rendererinfo_t *pd3d7rendererinfo = &d3d7rendererinfo;
#endif
rendererinfo_t *pd3drendererinfo;
rendererinfo_t d3d9rendererinfo;
rendererinfo_t *pd3d9rendererinfo = &d3d9rendererinfo;
rendererinfo_t **rendererinfo[] =
{
&pdedicatedrendererinfo,
#ifdef SWQUAKE
&psoftwarerendererinfo,
#endif
#ifdef RGLQUAKE
&popenglrendererinfo,
&pd3drendererinfo,
#endif
#ifdef D3DQUAKE
&pd3d7rendererinfo,
#endif
#ifdef D3DQUAKE
&pd3d9rendererinfo,
#endif
};
typedef struct vidmode_s
{
const char *description;
int width, height;
} vidmode_t;
vidmode_t vid_modes[] =
{
{ "320x200", 320, 200},
{ "320x240", 320, 240},
{ "400x300", 400, 300},
{ "512x384", 512, 384},
{ "640x480", 640, 480},
{ "800x600", 800, 600},
{ "960x720", 960, 720},
{ "1024x768 (XGA: 14-15inch LCD Native)", 1024, 768},
{ "1152x864", 1152, 864},
{ "1280x960", 1280, 960},
{ "1280x1024 (SXGA: 17-19inch LCD Native)", 1280, 1024},
{ "1440x900 (WXGA: 19inch Widescreen LCD Native Resolution)", 1440, 900},
{ "1600x1200 (UXGA: 20+inch LCD Native Resolution)", 1600, 1200}, //sw height is bound to 200 to 1024
{ "1680x1050 (WSXGA: 20inch Widescreen LCD Native)", 1680, 1050},
{ "1920x1200 (WUXGA: 24inch Widescreen LCD Native)", 1920, 1200},
{ "2048x1536", 2048, 1536}, //too much width will disable water warping (>1280) (but at that resolution, it's almost unnoticable)
{ "2560x1600 (30inch Widescreen LCD Native)", 2560, 1600}
};
#define NUMVIDMODES sizeof(vid_modes)/sizeof(vid_modes[0])
qboolean M_Vid_GetMove(int num, int *w, int *h)
{
if ((unsigned)num >= NUMVIDMODES)
return false;
*w = vid_modes[num].width;
*h = vid_modes[num].height;
return true;
}
typedef struct {
menucombo_t *renderer;
menucombo_t *modecombo;
menucombo_t *conscalecombo;
menucombo_t *bppcombo;
menucombo_t *texturefiltercombo;
menuedit_t *customwidth;
menuedit_t *customheight;
} videomenuinfo_t;
menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def);
void CheckCustomMode(struct menu_s *menu)
{
videomenuinfo_t *info = menu->data;
if (info->modecombo->selectedoption && info->conscalecombo->selectedoption)
{ //hide the custom options
info->customwidth->common.ishidden = true;
info->customheight->common.ishidden = true;
}
else
{
info->customwidth->common.ishidden = false;
info->customheight->common.ishidden = false;
}
#ifdef SWQUAKE
if (info->renderer->selectedoption < 1)
{
info->conscalecombo->common.ishidden = true;
}
else
#endif
{
if (!info->bppcombo->selectedoption)
info->bppcombo->selectedoption = 1;
info->conscalecombo->common.ishidden = false;
}
}
qboolean M_VideoApply (union menuoption_s *op,struct menu_s *menu,int key)
{
videomenuinfo_t *info = menu->data;
int selectedbpp;
if (key != K_ENTER)
return false;
if (info->modecombo->selectedoption)
{ //set a prefab
Cbuf_AddText(va("vid_width %i\n", vid_modes[info->modecombo->selectedoption-1].width), RESTRICT_LOCAL);
Cbuf_AddText(va("vid_height %i\n", vid_modes[info->modecombo->selectedoption-1].height), RESTRICT_LOCAL);
}
else
{ //use the custom one
Cbuf_AddText(va("vid_width %s\n", info->customwidth->text), RESTRICT_LOCAL);
Cbuf_AddText(va("vid_height %s\n", info->customheight->text), RESTRICT_LOCAL);
}
if (info->conscalecombo->selectedoption) //I am aware that this handicaps the menu a bit, but it should be easier for n00bs.
{ //set a prefab
Cbuf_AddText(va("vid_conwidth %i\n", vid_modes[info->conscalecombo->selectedoption-1].width), RESTRICT_LOCAL);
Cbuf_AddText(va("vid_conheight %i\n", vid_modes[info->conscalecombo->selectedoption-1].height), RESTRICT_LOCAL);
}
else
{ //use the custom one
Cbuf_AddText(va("vid_conwidth %s\n", info->customwidth->text), RESTRICT_LOCAL);
Cbuf_AddText(va("vid_conheight %s\n", info->customheight->text), RESTRICT_LOCAL);
}
selectedbpp = 16;
switch(info->bppcombo->selectedoption)
{
case 0:
if (info->renderer->selectedoption)
selectedbpp = 16;
else
selectedbpp = 8;
break;
case 1:
selectedbpp = 16;
break;
case 2:
selectedbpp = 32;
break;
}
switch(info->texturefiltercombo->selectedoption)
{
case 0:
Cbuf_AddText("gl_texturemode gl_nearest_mipmap_nearest\n", RESTRICT_LOCAL);
break;
case 1:
Cbuf_AddText("gl_texturemode gl_linear_mipmap_nearest\n", RESTRICT_LOCAL);
break;
case 2:
Cbuf_AddText("gl_texturemode gl_linear_mipmap_linear\n", RESTRICT_LOCAL);
break;
}
Cbuf_AddText(va("vid_bpp %i\n", selectedbpp), RESTRICT_LOCAL);
switch(info->renderer->selectedoption)
{
#ifdef SWQUAKE
case 0:
Cbuf_AddText("setrenderer sw\n", RESTRICT_LOCAL);
break;
case 1:
#else
case 0:
#endif
Cbuf_AddText("setrenderer gl\n", RESTRICT_LOCAL);
break;
#ifdef SWQUAKE
case 2:
#else
case 1:
#endif
Cbuf_AddText("setrenderer d3d7\n", RESTRICT_LOCAL);
break;
case 3:
Cbuf_AddText("setrenderer d3d9\n", RESTRICT_LOCAL);
break;
}
M_RemoveMenu(menu);
Cbuf_AddText("menu_video\n", RESTRICT_LOCAL);
return true;
}
void M_Menu_Video_f (void)
{
extern cvar_t r_stains, v_contrast;
#if defined(SWQUAKE)
extern cvar_t d_smooth;
#endif
#if defined(RGLQUAKE)
extern cvar_t r_bloom;
#endif
extern cvar_t r_bouncysparks;
static const char *modenames[128] = {"Custom"};
static const char *rendererops[] = {
#ifdef SWQUAKE
"Software",
#endif
#ifdef RGLQUAKE
"OpenGL",
#ifdef USE_D3D
"DirectX7",
#endif
#endif
#ifdef D3DQUAKE
"DirectX9",
#endif
NULL
};
static const char *bppnames[] =
{
"8",
"16",
"32",
NULL
};
static const char *texturefilternames[] =
{
"Nearest",
"Bilinear",
"Trilinear",
NULL
};
videomenuinfo_t *info;
menu_t *menu;
int prefabmode;
int prefab2dmode;
int currentbpp;
#ifdef RGLQUAKE
int currenttexturefilter;
#endif
int i, y;
prefabmode = -1;
prefab2dmode = -1;
for (i = 0; i < sizeof(vid_modes)/sizeof(vidmode_t); i++)
{
if (vid_modes[i].width == vid_width.value && vid_modes[i].height == vid_height.value)
prefabmode = i;
if (vid_modes[i].width == vid_conwidth.value && vid_modes[i].height == vid_conheight.value)
prefab2dmode = i;
modenames[i+1] = vid_modes[i].description;
}
modenames[i+1] = NULL;
key_dest = key_menu;
m_state = m_complex;
menu = M_CreateMenu(sizeof(videomenuinfo_t));
info = menu->data;
#if defined(SWQUAKE) && defined(RGLQUAKE)
if (qrenderer == QR_OPENGL)
{
#ifdef USE_D3D
if (!strcmp(vid_renderer.string, "d3d"))
i = 2;
else
#endif
i = 1;
}
else
#endif
#if defined(RGLQUAKE) && defined(USE_D3D)
if (!strcmp(vid_renderer.string, "d3d"))
i = 1;
else
#endif
i = 0;
if (vid_bpp.value >= 32)
currentbpp = 2;
else if (vid_bpp.value >= 16)
currentbpp = 1;
else
currentbpp = 0;
#ifdef RGLQUAKE
if (!Q_strcasecmp(gl_texturemode.string, "gl_nearest_mipmap_nearest"))
currenttexturefilter = 0;
else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_linear"))
currenttexturefilter = 2;
else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_nearest"))
currenttexturefilter = 1;
else
currenttexturefilter = 1;
#endif
MC_AddCenterPicture(menu, 4, "vidmodes");
y = 32;
info->renderer = MC_AddCombo(menu, 16, y, " Renderer ", rendererops, i); y+=8;
info->bppcombo = MC_AddCombo(menu, 16, y, " Color Depth ", bppnames, currentbpp); y+=8;
info->modecombo = MC_AddCombo(menu, 16, y, " Video Size ", modenames, prefabmode+1); y+=8;
info->conscalecombo = MC_AddCombo(menu, 16, y, " 2d Size ", modenames, prefab2dmode+1); y+=8;
MC_AddCheckBox(menu, 16, y, " Fullscreen ", &vid_fullscreen,0); y+=8;
y+=4;info->customwidth = MC_AddEdit(menu, 16, y, " Custom width ", vid_width.string); y+=8;
y+=4;info->customheight = MC_AddEdit(menu, 16, y, " Custom height", vid_height.string); y+=12;
y+=8;
MC_AddCommand(menu, 16, y, " Apply", M_VideoApply); y+=8;
y+=8;
MC_AddCheckBox(menu, 16, y, " Stain maps", &r_stains,0); y+=8;
MC_AddCheckBox(menu, 16, y, " Bouncy sparks", &r_bouncysparks,0); y+=8;
MC_AddCheckBox(menu, 16, y, " Rain", &r_part_rain,0); y+=8;
#if defined(SWQUAKE)
MC_AddCheckBox(menu, 16, y, " SW Smoothing", &d_smooth,0); y+=8;
#endif
#ifdef RGLQUAKE
MC_AddCheckBox(menu, 16, y, " GL Bumpmapping", &gl_bump,0); y+=8;
MC_AddCheckBox(menu, 16, y, " Bloom", &r_bloom,0); y+=8;
#endif
MC_AddCheckBox(menu, 16, y, " Dynamic lights", &r_dynamic,0); y+=8;
MC_AddSlider(menu, 16, y, " Screen size", &scr_viewsize, 30, 120, 0.1);y+=8;
MC_AddSlider(menu, 16, y, " Gamma", &v_gamma, 0.3, 1, 0.05); y+=8;
MC_AddSlider(menu, 16, y, " Contrast", &v_contrast, 1, 3, 0.05); y+=8;
#ifdef RGLQUAKE
info->texturefiltercombo = MC_AddCombo(menu, 16, y, " Texture Filter ", texturefilternames, currenttexturefilter); y+=8;
MC_AddSlider(menu, 16, y, "Anisotropy Level", &gl_texture_anisotropic_filtering, 1, 16, 1); y+=8; //urm, this shouldn't really be a slider, but should be a combo instead
#endif
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 152, 32, NULL, false);
menu->selecteditem = (union menuoption_s *)info->renderer;
menu->event = CheckCustomMode;
}
void R_SetRenderer(int wanted)
{
rendererinfo_t *ri;
if (wanted<0)
{ //-1 is used so we know when we've applied something instead of never setting anything.
wanted=0;
qrenderer = -1;
}
else
qrenderer = (*rendererinfo[wanted])->rtype;
ri = (*rendererinfo[wanted]);
q_renderername = ri->name[0];
Draw_SafePicFromWad = ri->Draw_SafePicFromWad; //Not supported
Draw_CachePic = ri->Draw_CachePic;
Draw_SafeCachePic = ri->Draw_SafeCachePic;
Draw_Init = ri->Draw_Init;
Draw_ReInit = ri->Draw_Init;
Draw_Character = ri->Draw_Character;
Draw_ColouredCharacter = ri->Draw_ColouredCharacter;
Draw_String = ri->Draw_String;
Draw_TinyCharacter = ri->Draw_TinyCharacter;
Draw_Alt_String = ri->Draw_Alt_String;
Draw_Crosshair = ri->Draw_Crosshair;
Draw_DebugChar = ri->Draw_DebugChar;
Draw_Pic = ri->Draw_Pic;
Draw_SubPic = ri->Draw_SubPic;
Draw_TransPic = ri->Draw_TransPic;
Draw_TransPicTranslate = ri->Draw_TransPicTranslate;
Draw_ConsoleBackground = ri->Draw_ConsoleBackground;
Draw_EditorBackground = ri->Draw_EditorBackground;
Draw_TileClear = ri->Draw_TileClear;
Draw_Fill = ri->Draw_Fill;
Draw_FillRGB = ri->Draw_FillRGB;
Draw_FadeScreen = ri->Draw_FadeScreen;
Draw_BeginDisc = ri->Draw_BeginDisc;
Draw_EndDisc = ri->Draw_EndDisc;
Draw_ScalePic = ri->Draw_ScalePic;
Draw_Image = ri->Draw_Image;
Draw_ImageColours = ri->Draw_ImageColours;
R_Init = ri->R_Init;
R_DeInit = ri->R_DeInit;
R_RenderView = ri->R_RenderView;
R_NewMap = ri->R_NewMap;
R_PreNewMap = ri->R_PreNewMap;
R_LightPoint = ri->R_LightPoint;
R_PushDlights = ri->R_PushDlights;
R_CheckSky = ri->R_CheckSky;
R_SetSky = ri->R_SetSky;
R_AddStain = ri->R_AddStain;
R_LessenStains = ri->R_LessenStains;
VID_Init = ri->VID_Init;
VID_DeInit = ri->VID_DeInit;
VID_LockBuffer = ri->VID_LockBuffer;
VID_UnlockBuffer = ri->VID_UnlockBuffer;
D_BeginDirectRect = ri->D_BeginDirectRect;
D_EndDirectRect = ri->D_EndDirectRect;
VID_ForceLockState = ri->VID_ForceLockState;
VID_ForceUnlockedAndReturnState = ri->VID_ForceUnlockedAndReturnState;
VID_SetPalette = ri->VID_SetPalette;
VID_ShiftPalette = ri->VID_ShiftPalette;
VID_GetRGBInfo = ri->VID_GetRGBInfo;
VID_SetWindowCaption = ri->VID_SetWindowCaption;
Media_ShowFrame8bit = ri->Media_ShowFrame8bit;
Media_ShowFrameRGBA_32 = ri->Media_ShowFrameRGBA_32;
Media_ShowFrameBGR_24_Flip = ri->Media_ShowFrameBGR_24_Flip;
Mod_Init = ri->Mod_Init;
Mod_Think = ri->Mod_Think;
Mod_ClearAll = ri->Mod_ClearAll;
Mod_ForName = ri->Mod_ForName;
Mod_FindName = ri->Mod_FindName;
Mod_Extradata = ri->Mod_Extradata;
Mod_TouchModel = ri->Mod_TouchModel;
Mod_NowLoadExternal = ri->Mod_NowLoadExternal;
// Mod_GetTag = ri->Mod_GetTag;
// Mod_TagNumForName = ri->Mod_TagNumForName;
Mod_SkinForName = ri->Mod_SkinForName;
SCR_UpdateScreen = ri->SCR_UpdateScreen;
}
static qbyte default_quakepal[768] =
{
0,0,0,15,15,15,31,31,31,47,47,47,63,63,63,75,75,75,91,91,91,107,107,107,123,123,123,139,139,139,155,155,155,171,171,171,187,187,187,203,203,203,219,219,219,235,235,235,15,11,7,23,15,11,31,23,11,39,27,15,47,35,19,55,43,23,63,47,23,75,55,27,83,59,27,91,67,31,99,75,31,107,83,31,115,87,31,123,95,35,131,103,35,143,111,35,11,11,15,19,19,27,27,27,39,39,39,51,47,47,63,55,55,75,63,63,87,71,71,103,79,79,115,91,91,127,99,99,
139,107,107,151,115,115,163,123,123,175,131,131,187,139,139,203,0,0,0,7,7,0,11,11,0,19,19,0,27,27,0,35,35,0,43,43,7,47,47,7,55,55,7,63,63,7,71,71,7,75,75,11,83,83,11,91,91,11,99,99,11,107,107,15,7,0,0,15,0,0,23,0,0,31,0,0,39,0,0,47,0,0,55,0,0,63,0,0,71,0,0,79,0,0,87,0,0,95,0,0,103,0,0,111,0,0,119,0,0,127,0,0,19,19,0,27,27,0,35,35,0,47,43,0,55,47,0,67,
55,0,75,59,7,87,67,7,95,71,7,107,75,11,119,83,15,131,87,19,139,91,19,151,95,27,163,99,31,175,103,35,35,19,7,47,23,11,59,31,15,75,35,19,87,43,23,99,47,31,115,55,35,127,59,43,143,67,51,159,79,51,175,99,47,191,119,47,207,143,43,223,171,39,239,203,31,255,243,27,11,7,0,27,19,0,43,35,15,55,43,19,71,51,27,83,55,35,99,63,43,111,71,51,127,83,63,139,95,71,155,107,83,167,123,95,183,135,107,195,147,123,211,163,139,227,179,151,
171,139,163,159,127,151,147,115,135,139,103,123,127,91,111,119,83,99,107,75,87,95,63,75,87,55,67,75,47,55,67,39,47,55,31,35,43,23,27,35,19,19,23,11,11,15,7,7,187,115,159,175,107,143,163,95,131,151,87,119,139,79,107,127,75,95,115,67,83,107,59,75,95,51,63,83,43,55,71,35,43,59,31,35,47,23,27,35,19,19,23,11,11,15,7,7,219,195,187,203,179,167,191,163,155,175,151,139,163,135,123,151,123,111,135,111,95,123,99,83,107,87,71,95,75,59,83,63,
51,67,51,39,55,43,31,39,31,23,27,19,15,15,11,7,111,131,123,103,123,111,95,115,103,87,107,95,79,99,87,71,91,79,63,83,71,55,75,63,47,67,55,43,59,47,35,51,39,31,43,31,23,35,23,15,27,19,11,19,11,7,11,7,255,243,27,239,223,23,219,203,19,203,183,15,187,167,15,171,151,11,155,131,7,139,115,7,123,99,7,107,83,0,91,71,0,75,55,0,59,43,0,43,31,0,27,15,0,11,7,0,0,0,255,11,11,239,19,19,223,27,27,207,35,35,191,43,
43,175,47,47,159,47,47,143,47,47,127,47,47,111,47,47,95,43,43,79,35,35,63,27,27,47,19,19,31,11,11,15,43,0,0,59,0,0,75,7,0,95,7,0,111,15,0,127,23,7,147,31,7,163,39,11,183,51,15,195,75,27,207,99,43,219,127,59,227,151,79,231,171,95,239,191,119,247,211,139,167,123,59,183,155,55,199,195,55,231,227,87,127,191,255,171,231,255,215,255,255,103,0,0,139,0,0,179,0,0,215,0,0,255,0,0,255,243,147,255,247,199,255,255,255,159,91,83
};
qbyte default_conchar[11356] =
{
#include "lhfont.h"
};
qboolean R_ApplyRenderer_Load (rendererstate_t *newr);
void D3DSucks(void)
{
SCR_DeInit();
if (!R_ApplyRenderer_Load(NULL))//&currentrendererstate))
Sys_Error("Failed to reload content after mode switch\n");
}
qboolean R_ApplyRenderer (rendererstate_t *newr)
{
if (newr->bpp == -1)
return false;
CL_AllowIndependantSendCmd(false); //FIXME: figure out exactly which parts are going to affect the model loading.
IN_Shutdown();
if (R_DeInit)
{
TRACE(("dbg: R_ApplyRenderer: R_DeInit\n"));
R_DeInit();
}
if (VID_DeInit)
{
TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n"));
VID_DeInit();
}
TRACE(("dbg: R_ApplyRenderer: SCR_DeInit\n"));
SCR_DeInit();
COM_FlushTempoaryPacks();
S_Shutdown();
if (qrenderer == QR_NONE || qrenderer==-1)
{
if (newr->renderer == QR_NONE && qrenderer != -1)
return true; //no point
Sys_CloseTerminal ();
}
R_SetRenderer(newr->renderer);
return R_ApplyRenderer_Load(newr);
}
qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
{
int i, j;
extern model_t *loadmodel;
extern int host_hunklevel;
Cache_Flush();
Hunk_FreeToLowMark(host_hunklevel); //is this a good idea?
TRACE(("dbg: R_ApplyRenderer: old renderer closed\n"));
pmove.numphysent = 0;
if (qrenderer) //graphics stuff only when not dedicated
{
qbyte *data;
#ifndef CLIENTONLY
isDedicated = false;
#endif
if (newr)
Con_Printf("Setting mode %i*%i*%i*%i\n", newr->width, newr->height, newr->bpp, newr->rate);
if (host_basepal)
BZ_Free(host_basepal);
if (host_colormap)
BZ_Free(host_colormap);
host_basepal = (qbyte *)COM_LoadMallocFile ("gfx/palette.lmp");
if (!host_basepal)
{
qbyte *pcx=NULL;
host_basepal = BZ_Malloc(768);
pcx = COM_LoadTempFile("pics/colormap.pcx");
if (!pcx || !ReadPCXPalette(pcx, com_filesize, host_basepal))
{
memcpy(host_basepal, default_quakepal, 768);
}
else
{
host_colormap = BZ_Malloc(256*VID_GRADES);
if (ReadPCXData(pcx, com_filesize, 256, VID_GRADES, host_colormap))
goto q2colormap; //skip the colormap.lmp file as we already read it
}
}
host_colormap = (qbyte *)COM_LoadMallocFile ("gfx/colormap.lmp");
if (!host_colormap)
{
#ifdef SWQUAKE
float f;
if (qrenderer == QR_SOFTWARE) //glquake doesn't care
{
data = host_colormap = BZ_Malloc(256*VID_GRADES+sizeof(int));
//let's try making one. this is probably caused by running out of baseq2.
for (j = 0; j < VID_GRADES; j++)
{
f = 1 - ((float)j/VID_GRADES);
for (i = 0; i < 256-vid.fullbright; i++)
{
data[i] = GetPaletteIndex(host_basepal[i*3+0]*f, host_basepal[i*3+1]*f, host_basepal[i*3+2]*f);
}
for (; i < 256; i++)
data[i] = i;
data+=256;
}
}
#endif
vid.fullbright=0;
}
else
{
j = VID_GRADES-1;
data = host_colormap + j*256;
vid.fullbright=0;
for (i = 255; i >= 0; i--)
{
if (host_colormap[i] == data[i])
vid.fullbright++;
else
break;
}
}
if (vid.fullbright < 2)
vid.fullbright = 0; //transparent colour doesn't count.
q2colormap:
TRACE(("dbg: R_ApplyRenderer: Palette loaded\n"));
#ifdef _WIN32
if (hwnd_dialog)
{
DestroyWindow (hwnd_dialog);
hwnd_dialog = NULL;
}
#endif
if (newr)
if (!VID_Init(newr, host_basepal))
{
return false;
}
TRACE(("dbg: R_ApplyRenderer: vid applied\n"));
W_LoadWadFile("gfx.wad");
TRACE(("dbg: R_ApplyRenderer: wad loaded\n"));
Draw_Init();
TRACE(("dbg: R_ApplyRenderer: draw inited\n"));
R_Init();
TRACE(("dbg: R_ApplyRenderer: renderer inited\n"));
SCR_Init();
TRACE(("dbg: R_ApplyRenderer: screen inited\n"));
Sbar_Flush();
IN_ReInit();
}
else
{
#ifdef CLIENTONLY
Sys_Error("Tried setting dedicated mode\n");
//we could support this, but there's no real reason to actually do so.
//fixme: despite the checks in the setrenderer command, we can still get here via a config using vid_renderer.
#else
TRACE(("dbg: R_ApplyRenderer: isDedicated = true\n"));
isDedicated = true;
if (cls.state)
{
int os = sv.state;
sv.state = ss_dead; //prevents server from being killed off too.
CL_Disconnect();
sv.state = os;
}
Sys_InitTerminal();
Con_PrintToSys();
#endif
}
TRACE(("dbg: R_ApplyRenderer: initing mods\n"));
Mod_Init();
TRACE(("dbg: R_ApplyRenderer: initing bulletein boards\n"));
WipeBulletenTextures();
// host_hunklevel = Hunk_LowMark();
if (R_PreNewMap)
if (cl.worldmodel)
{
TRACE(("dbg: R_ApplyRenderer: R_PreNewMap (how handy)\n"));
R_PreNewMap();
}
#ifndef CLIENTONLY
if (sv.worldmodel)
{
edict_t *ent;
#ifdef Q2SERVER
q2edict_t *q2ent;
#endif
TRACE(("dbg: R_ApplyRenderer: reloading server map\n"));
sv.worldmodel = Mod_ForName (sv.modelname, false);
TRACE(("dbg: R_ApplyRenderer: loaded\n"));
if (sv.worldmodel->needload)
{
SV_Error("Bsp went missing on render restart\n");
}
TRACE(("dbg: R_ApplyRenderer: doing that funky phs thang\n"));
SV_CalcPHS ();
TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
SV_ClearWorld ();
if (svs.gametype == GT_PROGS)
{
for (i = 0; i < MAX_MODELS; i++)
{
if (sv.strings.model_precache[i] && *sv.strings.model_precache[i] && (!strcmp(sv.strings.model_precache[i] + strlen(sv.strings.model_precache[i]) - 4, ".bsp") || i-1 < sv.worldmodel->numsubmodels))
sv.models[i] = Mod_FindName(sv.strings.model_precache[i]);
else
sv.models[i] = NULL;
}
ent = sv.edicts;
// ent->v->model = PR_NewString(svprogfuncs, sv.worldmodel->name); //FIXME: is this a problem for normal ents?
for (i=0 ; i<sv.num_edicts ; i++)
{
ent = EDICT_NUM(svprogfuncs, i);
if (!ent)
continue;
if (ent->isfree)
continue;
if (ent->area.prev)
{
ent->area.prev = ent->area.next = NULL;
SV_LinkEdict (ent, false); // relink ents so touch functions continue to work.
}
}
}
#ifdef Q2SERVER
else if (svs.gametype == GT_QUAKE2)
{
for (i = 0; i < MAX_MODELS; i++)
{
if (sv.strings.configstring[Q2CS_MODELS+i] && *sv.strings.configstring[Q2CS_MODELS+i] && (!strcmp(sv.strings.configstring[Q2CS_MODELS+i] + strlen(sv.strings.configstring[Q2CS_MODELS+i]) - 4, ".bsp") || i-1 < sv.worldmodel->numsubmodels))
sv.models[i] = Mod_FindName(sv.strings.configstring[Q2CS_MODELS+i]);
else
sv.models[i] = NULL;
}
q2ent = ge->edicts;
for (i=0 ; i<ge->num_edicts ; i++, q2ent = (q2edict_t *)((char *)q2ent + ge->edict_size))
{
if (!q2ent)
continue;
if (!q2ent->inuse)
continue;
if (q2ent->area.prev)
{
q2ent->area.prev = q2ent->area.next = NULL;
SVQ2_LinkEdict (q2ent); // relink ents so touch functions continue to work.
}
}
}
#endif
else
SV_UnspawnServer();
}
#endif
#ifdef PLUGINS
Plug_ResChanged();
#endif
TRACE(("dbg: R_ApplyRenderer: starting on client state\n"));
if (cl.worldmodel)
{
int staticmodelindex[MAX_STATIC_ENTITIES];
for (i = 0; i < cl.num_statics; i++) //static entities contain pointers to the model index.
{
staticmodelindex[i] = 0;
for (j = 1; j < MAX_MODELS; j++)
if (cl_static_entities[i].model == cl.model_precache[j])
{
staticmodelindex[i] = j;
break;
}
}
cl.worldmodel = NULL;
cl_numvisedicts=0;
TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n"));
for (i=1 ; i<MAX_MODELS ; i++)
{
if (!cl.model_name[i][0])
break;
cl.model_precache[i] = NULL;
TRACE(("dbg: R_ApplyRenderer: reloading model %s\n", cl.model_name[i]));
cl.model_precache[i] = Mod_ForName (cl.model_name[i], false);
if (!cl.model_precache[i])
{
Con_Printf ("\nThe required model file '%s' could not be found.\n\n"
, cl.model_name[i]);
Con_Printf ("You may need to download or purchase a client "
"pack in order to play on this server.\n\n");
CL_Disconnect ();
#ifdef VM_UI
UI_Reset();
#endif
return false;
}
}
#ifdef CSQC_DAT
for (i=1 ; i<MAX_CSQCMODELS ; i++)
{
if (!cl.model_csqcname[i][0])
break;
cl.model_csqcprecache[i] = NULL;
TRACE(("dbg: R_ApplyRenderer: reloading csqc model %s\n", cl.model_csqcname[i]));
cl.model_csqcprecache[i] = Mod_ForName (cl.model_csqcname[i], false);
if (!cl.model_csqcprecache[i])
{
Con_Printf ("\nThe required model file '%s' could not be found.\n\n"
, cl.model_csqcname[i]);
Con_Printf ("You may need to download or purchase a client "
"pack in order to play on this server.\n\n");
CL_Disconnect ();
#ifdef VM_UI
UI_Reset();
#endif
return false;
}
}
#endif
loadmodel = cl.worldmodel = cl.model_precache[1];
TRACE(("dbg: R_ApplyRenderer: done the models\n"));
if (loadmodel->needload)
{
CL_Disconnect ();
#ifdef VM_UI
UI_Reset();
#endif
memcpy(&currentrendererstate, newr, sizeof(currentrendererstate));
return true;
}
TRACE(("dbg: R_ApplyRenderer: checking any wad textures\n"));
Mod_NowLoadExternal();
TRACE(("dbg: R_ApplyRenderer: R_NewMap\n"));
R_NewMap();
TRACE(("dbg: R_ApplyRenderer: efrags\n"));
for (i = 0; i < cl.num_statics; i++) //make the static entities reappear.
{
cl_static_entities[i].model = cl.model_precache[staticmodelindex[i]];
#ifdef SWQUAKE
cl_static_entities[i].palremap = D_IdentityRemap();
#endif
if (staticmodelindex[i]) //make sure it's worthwhile.
{
R_AddEfrags(&cl_static_entities[i]);
}
}
}
#ifdef VM_UI
else
UI_Reset();
#endif
switch (qrenderer)
{
case QR_NONE:
Con_Printf( "\n"
"-----------------------------\n"
"Dedicated console created\n");
break;
case QR_SOFTWARE:
Con_Printf( "\n"
"-----------------------------\n"
"Software renderer initialized\n");
break;
case QR_OPENGL:
Con_Printf( "\n"
"-----------------------------\n"
"OpenGL renderer initialized\n");
break;
case QR_DIRECT3D:
Con_Printf( "\n"
"-----------------------------\n"
"Direct3d renderer initialized\n");
break;
}
TRACE(("dbg: R_ApplyRenderer: S_Restart_f\n"));
if (!isDedicated)
S_DoRestart();
TRACE(("dbg: R_ApplyRenderer: done\n"));
if (newr)
memcpy(&currentrendererstate, newr, sizeof(currentrendererstate));
return true;
}
void R_RestartRenderer_f (void)
{
int i, j;
rendererstate_t oldr;
rendererstate_t newr;
#ifdef MENU_DAT
MP_Shutdown();
#endif
memset(&newr, 0, sizeof(newr));
TRACE(("dbg: R_RestartRenderer_f\n"));
Media_CaptureDemoEnd();
Cvar_ApplyLatches(CVAR_RENDERERLATCH);
newr.width = vid_width.value;
newr.height = vid_height.value;
newr.allow_modex = vid_allow_modex.value;
newr.multisample = vid_multisample.value;
newr.bpp = vid_bpp.value;
newr.fullscreen = vid_fullscreen.value;
newr.rate = vid_refreshrate.value;
Q_strncpyz(newr.glrenderer, gl_driver.string, sizeof(newr.glrenderer));
newr.renderer = -1;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!*rendererinfo[i])
continue; //not valid in this build. :(
for (j = 4-1; j >= 0; j--)
{
if (!(*rendererinfo[i])->name[j])
continue;
if (!stricmp((*rendererinfo[i])->name[j], vid_renderer.string))
{
newr.renderer = i;
break;
}
}
}
if (newr.renderer == -1)
{
Con_Printf("vid_renderer unset or invalid. Using default.\n");
//gotta do this after main hunk is saved off.
#if defined(RGLQUAKE) && defined(SWQUAKE)
Cmd_ExecuteString("setrenderer sw 8\n", RESTRICT_LOCAL);
Cbuf_AddText("menu_video\n", RESTRICT_LOCAL);
#elif defined(RGLQUAKE)
Cmd_ExecuteString("setrenderer gl\n", RESTRICT_LOCAL);
#elif defined(D3DQUAKE)
Cmd_ExecuteString("setrenderer d3d9\n", RESTRICT_LOCAL);
#else
Cmd_ExecuteString("setrenderer sw\n", RESTRICT_LOCAL);
#endif
return;
}
// use desktop settings if set to 0 and not dedicated
if (newr.renderer != QR_NONE)
{
int dbpp, dheight, dwidth, drate;
if (!Sys_GetDesktopParameters(&dwidth, &dheight, &dbpp, &drate))
{
// force default values for systems not supporting desktop parameters
dwidth = 640;
dheight = 480;
if (newr.renderer == QR_SOFTWARE) // hack for software default
dbpp = 8;
else
dbpp = 32;
}
if (vid_desktopsettings.value)
{
newr.width = dwidth;
newr.height = dheight;
newr.bpp = dbpp;
newr.rate = drate;
}
else
{
if (newr.width <= 0 || newr.height <= 0)
{
newr.width = dwidth;
newr.height = dheight;
}
if (newr.bpp <= 0)
newr.bpp = dbpp;
}
}
TRACE(("dbg: R_RestartRenderer_f renderer %i\n", newr.renderer));
memcpy(&oldr, &currentrendererstate, sizeof(rendererstate_t));
if (!R_ApplyRenderer(&newr))
{
TRACE(("dbg: R_RestartRenderer_f failed\n"));
if (R_ApplyRenderer(&oldr))
{
TRACE(("dbg: R_RestartRenderer_f old restored\n"));
Con_Printf(CON_ERROR "Video mode switch failed. Old mode restored.\n"); //go back to the old mode, the new one failed.
}
else
{
qboolean failed = true;
if (newr.rate != 0)
{
Con_Printf(CON_NOTICE "Trying default refresh rate\n");
newr.rate = 0;
failed = !R_ApplyRenderer(&newr);
}
if (failed)
{
Con_Printf(CON_NOTICE "Trying 640*480\n");
newr.width = 640;
newr.height = 480;
failed = !R_ApplyRenderer(&newr);
}
if (failed)
{
newr.renderer = QR_NONE;
if (R_ApplyRenderer(&newr))
{
TRACE(("dbg: R_RestartRenderer_f going to dedicated\n"));
Con_Printf(CON_ERROR "Video mode switch failed. Old mode wasn't supported either. Console forced.\n\nChange the following vars to something useable, and then use the setrenderer command.\n");
Con_Printf("%s: %s\n", vid_width.name, vid_width.string);
Con_Printf("%s: %s\n", vid_height.name, vid_height.string);
Con_Printf("%s: %s\n", vid_bpp.name, vid_bpp.string);
Con_Printf("%s: %s\n", vid_refreshrate.name, vid_refreshrate.string);
Con_Printf("%s: %s\n", vid_renderer.name, vid_renderer.string);
}
else
Sys_Error("Couldn't fall back to previous renderer\n");
}
}
}
Cvar_ApplyCallbacks(CVAR_RENDERERCALLBACK);
SCR_EndLoadingPlaque();
TRACE(("dbg: R_RestartRenderer_f success\n"));
#ifdef MENU_DAT
MP_Init();
#endif
}
void R_SetRenderer_f (void)
{
int i, j;
int best;
char *param = Cmd_Argv(1);
if (Cmd_Argc() == 1 || !stricmp(param, "help"))
{
Con_Printf ("\nValid setrenderer parameters are:\n");
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if ((*rendererinfo[i]))
Con_Printf("%s: %s\n", (*rendererinfo[i])->name[0], (*rendererinfo[i])->description);
}
return;
}
best = -1;
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
{
if (!*rendererinfo[i])
continue; //not valid in this build. :(
for (j = 4-1; j >= 0; j--)
{
if (!(*rendererinfo[i])->name[j])
continue;
if (!stricmp((*rendererinfo[i])->name[j], param))
{
best = i;
break;
}
}
}
#ifdef CLIENTONLY
if (best == 0)
{
Con_Printf("Client-only builds cannot use dedicated modes.\n");
return;
}
#endif
if (best == -1)
{
Con_Printf("setrenderer: parameter not supported (%s)\n", param);
return;
}
else
{
if (Cmd_Argc() == 3)
Cvar_Set(&vid_bpp, Cmd_Argv(2));
}
Cvar_Set(&vid_renderer, param);
R_RestartRenderer_f();
}
/*
================
R_GetSpriteFrame
================
*/
mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
{
msprite_t *psprite;
mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
int i, numframes, frame;
float *pintervals, fullinterval, targettime, time;
psprite = currententity->model->cache.data;
frame = currententity->framestate.g[FS_REG].frame[0];
if ((frame >= psprite->numframes) || (frame < 0))
{
Con_DPrintf ("R_DrawSprite: no such frame %d (%s)\n", frame, currententity->model->name);
frame = 0;
}
if (psprite->frames[frame].type == SPR_SINGLE)
{
pspriteframe = psprite->frames[frame].frameptr;
}
else if (psprite->frames[frame].type == SPR_ANGLED)
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 0.5-4)&7];
}
else
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pintervals = pspritegroup->intervals;
numframes = pspritegroup->numframes;
fullinterval = pintervals[numframes-1];
time = currententity->framestate.g[FS_REG].frametime[0];
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by 0
targettime = time - ((int)(time / fullinterval)) * fullinterval;
for (i=0 ; i<(numframes-1) ; i++)
{
if (pintervals[i] > targettime)
break;
}
pspriteframe = pspritegroup->frames[i];
}
return pspriteframe;
}
float r_projection_matrix[16];
float r_view_matrix[16];
void MYgluPerspective(double fovx, double fovy, double zNear, double zFar)
{
double xmin, xmax, ymin, ymax;
ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
xmax = zNear * tan( fovx * M_PI / 360.0 );
xmin = -xmax;
r_projection_matrix[0] = (2*zNear) / (xmax - xmin);
r_projection_matrix[4] = 0;
r_projection_matrix[8] = (xmax + xmin) / (xmax - xmin);
r_projection_matrix[12] = 0;
r_projection_matrix[1] = 0;
r_projection_matrix[5] = (2*zNear) / (ymax - ymin);
r_projection_matrix[9] = (ymax + ymin) / (ymax - ymin);
r_projection_matrix[13] = 0;
r_projection_matrix[2] = 0;
r_projection_matrix[6] = 0;
r_projection_matrix[10] = - (zFar+zNear)/(zFar-zNear);
r_projection_matrix[14] = - (2.0f*zFar*zNear)/(zFar-zNear);
r_projection_matrix[3] = 0;
r_projection_matrix[7] = 0;
r_projection_matrix[11] = -1;
r_projection_matrix[15] = 0;
}
void GL_InfinatePerspective(double fovx, double fovy,
double zNear)
{
// nudge infinity in just slightly for lsb slop
float nudge = 1;// - 1.0 / (1<<23);
double xmin, xmax, ymin, ymax;
ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
xmax = zNear * tan( fovx * M_PI / 360.0 );
xmin = -xmax;
r_projection_matrix[0] = (2*zNear) / (xmax - xmin);
r_projection_matrix[4] = 0;
r_projection_matrix[8] = (xmax + xmin) / (xmax - xmin);
r_projection_matrix[12] = 0;
r_projection_matrix[1] = 0;
r_projection_matrix[5] = (2*zNear) / (ymax - ymin);
r_projection_matrix[9] = (ymax + ymin) / (ymax - ymin);
r_projection_matrix[13] = 0;
r_projection_matrix[2] = 0;
r_projection_matrix[6] = 0;
r_projection_matrix[10] = -1 * nudge;
r_projection_matrix[14] = -2*zNear * nudge;
r_projection_matrix[3] = 0;
r_projection_matrix[7] = 0;
r_projection_matrix[11] = -1;
r_projection_matrix[15] = 0;
}
void GL_ParallelPerspective(double xmin, double xmax, double ymax, double ymin,
double znear, double zfar)
{
r_projection_matrix[0] = 2/(xmax-xmin);
r_projection_matrix[4] = 0;
r_projection_matrix[8] = 0;
r_projection_matrix[12] = (xmax+xmin)/(xmax-xmin);
r_projection_matrix[1] = 0;
r_projection_matrix[5] = 2/(ymax-ymin);
r_projection_matrix[9] = 0;
r_projection_matrix[13] = (ymax+ymin)/(ymax-ymin);
r_projection_matrix[2] = 0;
r_projection_matrix[6] = 0;
r_projection_matrix[10] = -2/(zfar-znear);
r_projection_matrix[14] = (zfar+znear)/(zfar-znear);
r_projection_matrix[3] = 0;
r_projection_matrix[7] = 0;
r_projection_matrix[11] = 0;
r_projection_matrix[15] = 1;
}
/*
===============
R_TextureAnimation
Returns the proper texture for a given time and base texture
===============
*/
extern entity_t *currententity;
texture_t *R_TextureAnimation (texture_t *base)
{
int reletive;
int count;
if (currententity->framestate.g[FS_REG].frame[0])
{
if (base->alternate_anims)
base = base->alternate_anims;
}
if (!base->anim_total)
return base;
reletive = (int)(cl.time*10) % base->anim_total;
count = 0;
while (base->anim_min > reletive || base->anim_max <= reletive)
{
base = base->anim_next;
if (!base)
Sys_Error ("R_TextureAnimation: broken cycle");
if (++count > 100)
Sys_Error ("R_TextureAnimation: infinite cycle");
}
return base;
}
mleaf_t *r_viewleaf, *r_oldviewleaf;
mleaf_t *r_viewleaf2, *r_oldviewleaf2;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
int r_visframecount;
mleaf_t *r_vischain; // linked list of visible leafs
/*
===============
R_MarkLeaves
===============
*/
void R_MarkLeaves (void)
{
qbyte fatvis[MAX_MAP_LEAFS/8];
qbyte *vis;
mnode_t *node;
int i;
qbyte solid[4096];
#ifdef Q3BSPS
if (cl.worldmodel->fromgame == fg_quake3)
{
int cluster;
mleaf_t *leaf;
if (r_oldviewcluster == r_viewcluster && !r_novis.value && r_viewcluster != -1)
return;
// development aid to let you run around and see exactly where
// the pvs ends
// if (r_lockpvs->value)
// return;
r_vischain = NULL;
r_visframecount++;
r_oldviewcluster = r_viewcluster;
if (r_novis.value || r_viewcluster == -1 || !cl.worldmodel->vis )
{
// mark everything
for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numleafs ; i++, leaf++)
{
if ( !leaf->nummarksurfaces ) {
continue;
}
leaf->visframe = r_visframecount;
leaf->vischain = r_vischain;
r_vischain = leaf;
}
return;
}
vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, NULL);//, cl.worldmodel);
for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numleafs ; i++, leaf++)
{
cluster = leaf->cluster;
if ( cluster == -1 || !leaf->nummarksurfaces ) {
continue;
}
if ( vis[cluster>>3] & (1<<(cluster&7)) ) {
leaf->visframe = r_visframecount;
leaf->vischain = r_vischain;
r_vischain = leaf;
}
}
return;
}
#endif
#ifdef Q2BSPS
if (cl.worldmodel->fromgame == fg_quake2)
{
int c;
mleaf_t *leaf;
int cluster;
if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2)
return;
r_oldviewcluster = r_viewcluster;
r_oldviewcluster2 = r_viewcluster2;
if (r_novis.value == 2)
return;
r_visframecount++;
if (r_novis.value || r_viewcluster == -1 || !cl.worldmodel->vis)
{
// mark everything
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
cl.worldmodel->leafs[i].visframe = r_visframecount;
for (i=0 ; i<cl.worldmodel->numnodes ; i++)
cl.worldmodel->nodes[i].visframe = r_visframecount;
return;
}
vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster, NULL);//, cl.worldmodel);
// may have to combine two clusters because of solid water boundaries
if (r_viewcluster2 != r_viewcluster)
{
memcpy (fatvis, vis, (cl.worldmodel->numleafs+7)/8);
vis = CM_ClusterPVS (cl.worldmodel, r_viewcluster2, NULL);//, cl.worldmodel);
c = (cl.worldmodel->numleafs+31)/32;
for (i=0 ; i<c ; i++)
((int *)fatvis)[i] |= ((int *)vis)[i];
vis = fatvis;
}
for (i=0,leaf=cl.worldmodel->leafs ; i<cl.worldmodel->numleafs ; i++, leaf++)
{
cluster = leaf->cluster;
if (cluster == -1)
continue;
if (vis[cluster>>3] & (1<<(cluster&7)))
{
node = (mnode_t *)leaf;
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
return;
}
#endif
if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.value) || r_novis.value == 2)
return;
// if (mirror)
// return;
r_visframecount++;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
if (r_novis.value)
{
vis = solid;
memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
}
else if (r_viewleaf2)
{
int c;
Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf2, fatvis);
vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL);
c = (cl.worldmodel->numleafs+31)/32;
for (i=0 ; i<c ; i++)
((int *)fatvis)[i] |= ((int *)vis)[i];
vis = fatvis;
}
else
vis = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, NULL);
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
{
if (vis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
}
mplane_t frustum[4];
/*
=================
R_CullBox
Returns true if the box is completely outside the frustom
=================
*/
qboolean R_CullBox (vec3_t mins, vec3_t maxs)
{
int i;
for (i=0 ; i<4 ; i++)
if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2)
return true;
return false;
}
qboolean R_CullSphere (vec3_t org, float radius)
{
//four frustrum planes all point inwards in an expanding 'cone'.
int i;
float d;
for (i=0 ; i<4 ; i++)
{
d = DotProduct(frustum[i].normal, org)-frustum[i].dist;
if (d <= -radius)
return true;
}
return false;
}
qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs)
{
int i;
vec3_t wmin, wmax;
float fmin, fmax;
//convert the model's bbox to the expanded maximum size of the entity, as drawn with this model.
//The result is an axial box, which we pass to R_CullBox
for (i = 0; i < 3; i++)
{
fmin = DotProduct(modmins, e->axis[i]);
fmax = DotProduct(modmaxs, e->axis[i]);
if (fmin > -16)
fmin = -16;
if (fmax < 16)
fmax = 16;
if (fmin < fmax)
{
wmin[i] = e->origin[i]+fmin;
wmax[i] = e->origin[i]+fmax;
}
else
{ //box went inside out
wmin[i] = e->origin[i]+fmax;
wmax[i] = e->origin[i]+fmin;
}
}
return R_CullBox(wmin, wmax);
}
int SignbitsForPlane (mplane_t *out)
{
int bits, j;
// for fast box on planeside test
bits = 0;
for (j=0 ; j<3 ; j++)
{
if (out->normal[j] < 0)
bits |= 1<<j;
}
return bits;
}
#if 1
void R_SetFrustum (void)
{
float scale;
int i;
float mvp[16];
if ((int)r_novis.value & 4)
return;
Matrix4_Multiply(r_projection_matrix, r_view_matrix, mvp);
for (i = 0; i < 4; i++)
{
if (i & 1)
{
frustum[i].normal[0] = mvp[3] + mvp[0+i/2];
frustum[i].normal[1] = mvp[7] + mvp[4+i/2];
frustum[i].normal[2] = mvp[11] + mvp[8+i/2];
frustum[i].dist = mvp[15] + mvp[12+i/2];
}
else
{
frustum[i].normal[0] = mvp[3] - mvp[0+i/2];
frustum[i].normal[1] = mvp[7] - mvp[4+i/2];
frustum[i].normal[2] = mvp[11] - mvp[8+i/2];
frustum[i].dist = mvp[15] - mvp[12+i/2];
}
scale = 1/sqrt(DotProduct(frustum[i].normal, frustum[i].normal));
frustum[i].normal[0] *= scale;
frustum[i].normal[1] *= scale;
frustum[i].normal[2] *= scale;
frustum[i].dist *= -scale;
frustum[i].type = PLANE_ANYZ;
frustum[i].signbits = SignbitsForPlane (&frustum[i]);
}
}
#else
void R_SetFrustum (void)
{
int i;
if ((int)r_novis.value & 4)
return;
/* removed - assumes fov_x == fov_y
if (r_refdef.fov_x == 90)
{
// front side is visible
VectorAdd (vpn, vright, frustum[0].normal);
VectorSubtract (vpn, vright, frustum[1].normal);
VectorAdd (vpn, vup, frustum[2].normal);
VectorSubtract (vpn, vup, frustum[3].normal);
}
else
*/
{
// rotate VPN right by FOV_X/2 degrees
RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
// rotate VPN left by FOV_X/2 degrees
RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
// rotate VPN up by FOV_X/2 degrees
RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
// rotate VPN down by FOV_X/2 degrees
RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
}
for (i=0 ; i<4 ; i++)
{
frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
frustum[i].signbits = SignbitsForPlane (&frustum[i]);
}
}
#endif