From 7d0ec7ce187f7333a7ada2884108757a4fec6449 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Mon, 15 Oct 2001 11:46:20 +0000 Subject: [PATCH] Major update, been neglecting CVS for some time... clipping engine (r_clip.c) to determine exactly what is visible (this has altered MANY parts of the rendering engine) fixed visibility bug with multiple players on a listen server vid_glx.c has been improved/cleaned up greatly and now pays attention to vid_mouse and vid_dga and will not grab the mouse until after the first frame snd_alsa_0_5.c has been fixed (Qprintf vs fprintf bug) nehahra works again (was missing svc_skybox support) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@915 d7cf8633-e32d-0410-b094-e92efae38249 --- buildnumber.c | 2 +- cl_input.c | 8 +- cl_main.c | 12 +- cl_parse.c | 7 +- cmd.h | 8 - common.c | 129 ++---- common.h | 67 ++-- gl_models.c | 21 +- gl_rmain.c | 257 ++++++++---- gl_rmisc.c | 9 - gl_rsurf.c | 1013 +++++++++++++++++++++++++++++++++++++++++------ gl_screen.c | 72 ++-- gl_textures.c | 6 +- glquake.h | 38 -- host.c | 9 +- host_cmd.c | 4 +- image.c | 4 +- mathlib.c | 49 ++- mathlib.h | 35 +- menu.c | 9 +- model_brush.c | 19 +- model_brush.h | 28 +- progs.h | 18 +- protocol.h | 1 + quakeio.c | 6 +- quakeio.h | 2 +- r_clip.c | 1029 ++++++++++++++++++++++++++++++++++++++++++++++++ r_clip.h | 14 + r_light.c | 49 ++- r_part.c | 8 +- r_sprites.c | 95 ++++- render.h | 51 ++- snd_alsa_0_5.c | 4 +- sv_main.c | 3 +- sv_user.c | 15 +- sys_linux.c | 8 +- sys_win.c | 9 +- transform.c | 6 + transform.h | 1 + vid.h | 17 +- vid_3dfxsvga.c | 2 - vid_glx.c | 390 ++++++++++-------- view.c | 158 ++++---- wad.c | 2 +- world.c | 142 ++++--- 45 files changed, 3001 insertions(+), 835 deletions(-) create mode 100644 r_clip.c create mode 100644 r_clip.h diff --git a/buildnumber.c b/buildnumber.c index 82d779f3..5bfe6ad4 100644 --- a/buildnumber.c +++ b/buildnumber.c @@ -1,4 +1,4 @@ -#define BUILDNUMBER 103 +#define BUILDNUMBER 104 int buildnumber = BUILDNUMBER; diff --git a/cl_input.c b/cl_input.c index 18ba2fc1..d49dd439 100644 --- a/cl_input.c +++ b/cl_input.c @@ -227,10 +227,10 @@ float CL_KeyState (kbutton_t *key) //========================================================================== -cvar_t cl_upspeed = {"cl_upspeed","200"}; -cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true}; -cvar_t cl_backspeed = {"cl_backspeed","200", true}; -cvar_t cl_sidespeed = {"cl_sidespeed","350"}; +cvar_t cl_upspeed = {"cl_upspeed","400"}; +cvar_t cl_forwardspeed = {"cl_forwardspeed","400", true}; +cvar_t cl_backspeed = {"cl_backspeed","400", true}; +cvar_t cl_sidespeed = {"cl_sidespeed","350", true}; cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"}; diff --git a/cl_main.c b/cl_main.c index e44e29e7..d0f306b7 100644 --- a/cl_main.c +++ b/cl_main.c @@ -667,8 +667,16 @@ void CL_RelinkEntities (void) CL_AllocDlight (ent, ent->render.origin, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0); } - if (!chase_active.value && ((i == cl.viewentity) || (ent->render.flags & RENDER_EXTERIORMODEL))) - continue; + if (chase_active.value) + { + if (ent->render.flags & RENDER_VIEWMODEL) + continue; + } + else + { + if (i == cl.viewentity || (ent->render.flags & RENDER_EXTERIORMODEL)) + continue; + } if (ent->render.model == NULL) continue; diff --git a/cl_parse.c b/cl_parse.c index a548373b..7b68ddef 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -67,7 +67,7 @@ char *svc_strings[128] = "svc_cutscene", "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y "svc_hidelmp", // [string] iconlabel - "", // 37 + "svc_skybox", // [string] skyname "", // 38 "", // 39 "", // 40 @@ -246,7 +246,7 @@ void CL_ParseEntityLump(char *entdata) char wadname[128]; int i, j, k; FOG_clear(); // LordHavoc: no fog until set - R_SetSkyBox(""); // LordHavoc: no enviroment mapped sky until set + R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set r_farclip.value = 6144; // LordHavoc: default farclip distance data = entdata; if (!data) @@ -1196,6 +1196,9 @@ void CL_ParseServerMessage (void) case svc_showlmp: SHOWLMP_decodeshow(); break; + case svc_skybox: + R_SetSkyBox(MSG_ReadString()); + break; } } diff --git a/cmd.h b/cmd.h index 5583b329..da1daa65 100644 --- a/cmd.h +++ b/cmd.h @@ -91,14 +91,6 @@ char *Cmd_CompleteCommand (char *partial); // attempts to match a partial command for automatic command line completion // returns NULL if nothing fits -int Cmd_CompleteAliasCountPossible (char *partial); -char **Cmd_CompleteAliasBuildList (char *partial); -int Cmd_CompleteCountPossible (char *partial); -char **Cmd_CompleteBuildList (char *partial); -char *Cmd_CompleteAlias (char *partial); -// Enhanced console completion by Fett erich@heintz.com -// Added by EvilTypeGuy eviltypeguy@qeradiant.com - int Cmd_Argc (void); char *Cmd_Argv (int arg); char *Cmd_Args (void); diff --git a/common.c b/common.c index a39cc5e5..8f8464a4 100644 --- a/common.c +++ b/common.c @@ -50,10 +50,6 @@ qboolean msg_suppress_1 = 0; void COM_InitFilesystem (void); -// if a packfile directory differs from this, it is assumed to be hacked -#define PAK0_COUNT 339 -#define PAK0_CRC 32981 - char com_token[1024]; int com_argc; char **com_argv; @@ -63,27 +59,6 @@ char com_cmdline[CMDLINE_LENGTH]; qboolean standard_quake = true, rogue = false, hipnotic = false, nehahra = false; -// this graphic needs to be in the pak file to use registered features -unsigned short pop[] = -{ - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000 -,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000 -,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600 -,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563 -,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564 -,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564 -,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563 -,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500 -,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200 -,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000 -,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000 -}; - /* @@ -102,39 +77,12 @@ into the cache directory, then opened there. FIXME: The file "parms.txt" will be read out of the game directory and appended to the current command line arguments to allow different games to initialize startup parms differently. This could be used to add a "-sspeed 22050" for the high quality sound edition. Because they are added at the end, they will not override an explicit setting on the original command line. - + */ //============================================================================ -// ClearLink is used for new headnodes -void ClearLink (link_t *l) -{ - l->prev = l->next = l; -} - -void RemoveLink (link_t *l) -{ - l->next->prev = l->prev; - l->prev->next = l->next; -} - -void InsertLinkBefore (link_t *l, link_t *before) -{ - l->next = before; - l->prev = before->prev; - l->prev->next = l; - l->next->prev = l; -} -void InsertLinkAfter (link_t *l, link_t *after) -{ - l->next = after->next; - l->prev = after; - l->prev->next = l; - l->next->prev = l; -} - /* ============================================================================ @@ -147,7 +95,7 @@ void InsertLinkAfter (link_t *l, link_t *after) void Q_memset (void *dest, int fill, int count) { int i; - + if ( (((long)dest | count) & 3) == 0) { count >>= 2; @@ -266,7 +214,7 @@ int Q_strncmp (char *s1, char *s2, int count) int Q_strncasecmp (char *s1, char *s2, int n) { int c1, c2; - + while (1) { c1 = *s1++; @@ -428,7 +376,7 @@ float Q_atof (char *str) val /= 10; total--; } - + return val*sign; } */ @@ -441,7 +389,7 @@ float Q_atof (char *str) ============================================================================ */ -#ifndef WIN32 +#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG) short (*BigShort) (short l); short (*LittleShort) (short l); int (*BigLong) (int l); @@ -698,7 +646,7 @@ int MSG_ReadLong (void) msg_badread = true; return -1; } - + c = net_message.data[msg_readcount] + (net_message.data[msg_readcount+1]<<8) + (net_message.data[msg_readcount+2]<<16) @@ -879,11 +827,20 @@ char *COM_SkipPath (char *pathname) COM_StripExtension ============ */ +// LordHavoc: replacement for severely broken COM_StripExtension that was used in original quake. void COM_StripExtension (char *in, char *out) { - while (*in && *in != '.') + char *last = NULL; + while (*in) + { + if (*in == '.') + last = in; + if ((*in == '/') || (*in == '\\') || (*in == ':')) + last = NULL; *out++ = *in++; - *out = 0; + } + if (last) + *last = 0; } /* @@ -1079,16 +1036,11 @@ being registered. */ void COM_CheckRegistered (void) { - QFile *h; - unsigned short check[128]; - int i; - Cvar_Set ("cmdline", com_cmdline); - COM_FOpenFile("gfx/pop.lmp", &h, false, true); static_registered = 0; - if (!h) + if (!Sys_FileTime("gfx/pop.lmp")) { if (com_modified) Con_Printf ("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n"); @@ -1102,13 +1054,6 @@ void COM_CheckRegistered (void) // Sys_Error ("You must have the registered version to use modified games"); return; } - - Qread (h, check, sizeof(check)); - Qclose (h); - - for (i=0 ; i<128 ; i++) - if (pop[i] != (unsigned short)BigShort (check[i])) - Sys_Error ("Corrupted data file."); // Cvar_Set ("cmdline", com_cmdline); Cvar_Set ("registered", "1"); @@ -1242,7 +1187,7 @@ COM_Init */ void COM_Init (char *basedir) { -#ifndef WIN32 +#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG) byte swaptest[2] = {1,0}; // set the byte swapping variables in a portable manner @@ -1403,7 +1348,7 @@ LordHavoc: Previously only used for CopyFile, now also used for COM_WriteFile. void COM_CreatePath (char *path) { char *ofs, save; - + for (ofs = path+1 ; *ofs ; ofs++) { if (*ofs == '/' || *ofs == '\\' || *ofs == ':') @@ -1598,12 +1543,7 @@ int COM_FindFile (char *filename, QFile **file, qboolean quiet, qboolean zip) findtime = Sys_FileTime (netpath); if (findtime == -1) - { - sprintf (netpath, "%s/%s",search->filename, gzfilename); - findtime = Sys_FileTime (netpath); - if (findtime == -1) - continue; - } + continue; #if CACHEENABLE // see if the file needs to be updated in the cache @@ -1754,15 +1694,14 @@ of the list so they override previous pack files. */ pack_t *COM_LoadPackFile (char *packfile) { - dpackheader_t header; - int i; - packfile_t *newfiles; - int numpackfiles; - pack_t *pack; - int packhandle; + dpackheader_t header; + int i; + packfile_t *newfiles; + int numpackfiles; + pack_t *pack; + int packhandle; // LordHavoc: changed from stack array to temporary malloc, allowing huge pack directories - dpackfile_t *info; - unsigned short crc; + dpackfile_t *info; if (Sys_FileOpenRead (packfile, &packhandle) == -1) { @@ -1781,24 +1720,12 @@ pack_t *COM_LoadPackFile (char *packfile) if (numpackfiles > MAX_FILES_IN_PACK) Sys_Error ("%s has %i files", packfile, numpackfiles); - if (numpackfiles != PAK0_COUNT) - com_modified = true; // not the original file - newfiles = Hunk_AllocName (numpackfiles * sizeof(packfile_t), "pack file-table"); info = qmalloc(sizeof(*info)*MAX_FILES_IN_PACK); Sys_FileSeek (packhandle, header.dirofs); Sys_FileRead (packhandle, (void *)info, header.dirlen); -// crc the directory to check for modifications - CRC_Init (&crc); - // LordHavoc: speedup - CRC_ProcessBytes(&crc, (byte *)info, header.dirlen); -// for (i=0 ; im))) - -//============================================================================ - #ifndef NULL #define NULL ((void *)0) #endif -#define Q_MAXCHAR ((char)0x7f) -#define Q_MAXSHORT ((short)0x7fff) -#define Q_MAXINT ((int)0x7fffffff) -#define Q_MAXLONG ((int)0x7fffffff) -#define Q_MAXFLOAT ((int)0x7fffffff) - -#define Q_MINCHAR ((char)0x80) -#define Q_MINSHORT ((short)0x8000) -#define Q_MININT ((int)0x80000000) -#define Q_MINLONG ((int)0x80000000) -#define Q_MINFLOAT ((int)0x7fffffff) - //============================================================================ -#ifdef WIN32 -short ShortSwap (short l); -int LongSwap (int l); +#if !defined(ENDIAN_LITTLE) && !defined(ENDIAN_BIG) +#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || (defined(__alpha__) || defined(__alpha)) || defined(__arm__) || (defined(__mips__) && defined(__MIPSEL__)) || defined(__LITTLE_ENDIAN__) +#define ENDIAN_LITTLE +#else +#define ENDIAN_BIG +#endif +#endif + +short ShortSwap (short l); +int LongSwap (int l); float FloatSwap (float f); + +#ifdef ENDIAN_LITTLE +// little endian #define BigShort(l) ShortSwap(l) #define LittleShort(l) (l) #define BigLong(l) LongSwap(l) #define LittleLong(l) (l) #define BigFloat(l) FloatSwap(l) #define LittleFloat(l) (l) +#elif ENDIAN_BIG +// big endian +#define BigShort(l) (l) +#define LittleShort(l) ShortSwap(l) +#define BigLong(l) (l) +#define LittleLong(l) LongSwap(l) +#define BigFloat(l) (l) +#define LittleFloat(l) FloatSwap(l) #else -extern short (*BigShort) (short l); -extern short (*LittleShort) (short l); -extern int (*BigLong) (int l); -extern int (*LittleLong) (int l); -extern float (*BigFloat) (float l); -extern float (*LittleFloat) (float l); +// figure it out at runtime +extern short (*BigShort) (short l); +extern short (*LittleShort) (short l); +extern int (*BigLong) (int l); +extern int (*LittleLong) (int l); +extern float (*BigFloat) (float l); +extern float (*LittleFloat) (float l); #endif //============================================================================ diff --git a/gl_models.c b/gl_models.c index 2829b944..9bf9b724 100644 --- a/gl_models.c +++ b/gl_models.c @@ -149,16 +149,16 @@ void R_AliasLerpVerts(int vertcount, float *av, *avn; av = aliasvert; avn = aliasvertnorm; - VectorScaleQuick(fscale1, lerp1, scale1); + VectorScale(fscale1, lerp1, scale1); if (lerp2) { - VectorScaleQuick(fscale2, lerp2, scale2); + VectorScale(fscale2, lerp2, scale2); if (lerp3) { - VectorScaleQuick(fscale3, lerp3, scale3); + VectorScale(fscale3, lerp3, scale3); if (lerp4) { - VectorScaleQuick(fscale4, lerp4, scale4); + VectorScale(fscale4, lerp4, scale4); translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3 + translate4[0] * lerp4; translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3 + translate4[1] * lerp4; translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3 + translate4[2] * lerp4; @@ -563,7 +563,6 @@ void ZymoticLerpBones(int count, zymbonematrix *bonebase, frameblend_t *blend, z { float lerp1, lerp2, lerp3, lerp4; zymbonematrix *out, rootmatrix, m, *bone1, *bone2, *bone3, *bone4; - lerp1 = 1 - lerp2; out = zymbonepose; AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]); VectorScale(rootmatrix.m[0], rootscale, rootmatrix.m[0]); @@ -753,19 +752,11 @@ void ZymoticTransformVerts(int vertcount, int *bonecounts, zymvertex_t *vert) } } -float ixtable[4096]; - void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist) { int a, b, c, d; float *out, v1[3], v2[3], normal[3]; int *u; - if (!ixtable[1]) - { - ixtable[0] = 0; - for (a = 1;a < 4096;a++) - ixtable[a] = 1.0f / a; - } // clear normals memset(aliasvertnorm, 0, sizeof(float[3]) * vertcount); memset(aliasvertusage, 0, sizeof(int) * vertcount); @@ -947,8 +938,8 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, f VectorAdd (org, clmodel->mins, mins); VectorAdd (org, clmodel->maxs, maxs); - if (cull && R_VisibleCullBox (mins, maxs)) - return; +// if (cull && R_CullBox (mins, maxs)) +// return; c_models++; diff --git a/gl_rmain.c b/gl_rmain.c index b8bd3f9f..37052fd9 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -entity_t r_worldentity; - qboolean r_cache_thrash; // compatability vec3_t modelorg, r_entorigin; @@ -60,6 +58,7 @@ mleaf_t *r_viewleaf, *r_oldviewleaf; unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value +float ixtable[4096]; void R_MarkLeaves (void); @@ -88,21 +87,23 @@ cvar_t gl_fogstart = {"gl_fogstart", "0"}; cvar_t gl_fogend = {"gl_fogend","0"}; cvar_t glfog = {"glfog", "0"}; +/* int R_VisibleCullBox (vec3_t mins, vec3_t maxs) { int sides; mnode_t *nodestack[8192], *node; int stack = 0; - if (R_CullBox(mins, maxs)) - return true; - node = cl.worldmodel->nodes; loc0: if (node->contents < 0) { if (((mleaf_t *)node)->visframe == r_framecount) + { + if (R_CullBox(mins, maxs)) + return true; return false; + } if (!stack) return true; node = nodestack[--stack]; @@ -131,6 +132,7 @@ loc0: node = node->children[1]; goto loc0; } +*/ qboolean lighthalf; @@ -263,7 +265,12 @@ void gl_main_newmap(void) void GL_Main_Init(void) { + int a; FOG_registercvars(); + // LordHavoc: setup 1.0f / N table for quick recipricols of integers + ixtable[0] = 0; + for (a = 1;a < 4096;a++) + ixtable[a] = 1.0f / a; Cvar_RegisterVariable (&r_drawentities); Cvar_RegisterVariable (&r_drawviewmodel); Cvar_RegisterVariable (&r_speeds); @@ -296,10 +303,12 @@ extern void R_Light_Init(void); extern void R_Particles_Init(void); extern void R_Explosion_Init(void); extern void CL_Effects_Init(void); +extern void R_Clip_Init(void); void Render_Init(void) { R_Modules_Shutdown(); + R_Clip_Init(); GL_Draw_Init(); GL_Main_Init(); GL_Models_Init(); @@ -372,9 +381,6 @@ float modelalpha; //================================================================================== -void R_DrawBrushModel (entity_t *e); -void R_DrawSpriteModel (entity_t *e, frameblend_t *blend); - void R_LerpUpdate(entity_t *ent) { int frame; @@ -442,12 +448,49 @@ void R_PrepareEntities (void) } } +void R_Entity_Callback(void *data, void *junk) +{ + ((entity_t *)data)->render.visframe = r_framecount; +} + +void R_AddModelEntities (void) +{ + int i; + vec3_t mins, maxs; + frameblend_t blend[4]; + + if (!r_drawentities.value) + return; + + for (i = 0;i < cl_numvisedicts;i++) + { + currententity = cl_visedicts[i]; + if (currententity->render.model->type == mod_brush) + { + modelalpha = currententity->render.alpha; + R_DrawBrushModel (currententity); + } + else if (currententity->render.model->type == mod_alias) + { + VectorAdd(currententity->render.origin, currententity->render.model->mins, mins); + VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs); + R_Clip_AddBox(mins, maxs, R_Entity_Callback, currententity, NULL); + } + else if (currententity->render.model->type == mod_sprite) + { + R_LerpUpdate(currententity); + R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); + R_ClipSprite(currententity, blend); + } + } +} + /* ============= R_DrawEntitiesOnList ============= */ -// LordHavoc: split so bmodels are rendered before any other objects +/* void R_DrawEntitiesOnList1 (void) { int i; @@ -457,6 +500,8 @@ void R_DrawEntitiesOnList1 (void) for (i = 0;i < cl_numvisedicts;i++) { + if (cl_visedicts[i]->render.visframe != r_framecount) + continue; if (cl_visedicts[i]->render.model->type != mod_brush) continue; currententity = cl_visedicts[i]; @@ -465,37 +510,55 @@ void R_DrawEntitiesOnList1 (void) R_DrawBrushModel (currententity); } } +*/ -void R_DrawEntitiesOnList2 (void) +void R_DrawModels (void) { int i; frameblend_t blend[4]; +// vec3_t mins, maxs; if (!r_drawentities.value) return; for (i = 0;i < cl_numvisedicts;i++) { + if (cl_visedicts[i]->render.visframe != r_framecount) + continue; currententity = cl_visedicts[i]; + if (currententity->render.model->type != mod_alias && currententity->render.model->type != mod_sprite) + continue; + modelalpha = currententity->render.alpha; - switch (currententity->render.model->type) + if (currententity->render.model->type == mod_alias) { - case mod_alias: + // only lerp models here because sprites were already lerped for their clip polygon R_LerpUpdate(currententity); R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap); - break; - - case mod_sprite: - R_LerpUpdate(currententity); + } + else //if (currententity->render.model->type == mod_sprite) + { + // build blend array R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); R_DrawSpriteModel (currententity, blend); - break; + } - default: + /* + VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->mins, mins); + VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->maxs, maxs); + + switch (cl_visedicts[i]->render.model->type) + { + case mod_alias: + R_Clip_AddBox(mins, maxs, R_DrawModelCallback, cl_visedicts[i], NULL); + break; + case mod_sprite: + R_Clip_AddBox(mins, maxs, R_DrawSpriteCallback, cl_visedicts[i], NULL); break; } + */ } } @@ -534,7 +597,11 @@ void R_SetFrustum (void) { int i; - if (r_refdef.fov_x == 90) + // LordHavoc: note to all quake engine coders, this code was making the + // view frustum taller than it should have been (it assumed the view is + // square; it is not square), so I disabled it + /* + if (r_refdef.fov_x == 90) { // front side is visible @@ -546,6 +613,7 @@ void R_SetFrustum (void) } 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 @@ -554,14 +622,14 @@ void R_SetFrustum (void) 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]); - BoxOnPlaneSideClassify(&frustum[i]); + PlaneClassify(&frustum[i]); } } @@ -783,16 +851,6 @@ void GL_BlendView(void) glEnable(GL_TEXTURE_2D); } -#define TIMEREPORT(VAR) \ - if (r_speeds2.value)\ - {\ - temptime = currtime;\ - currtime = Sys_DoubleTime();\ - VAR = (int) ((currtime - temptime) * 1000000.0);\ - }\ - else\ - VAR = 0; - /* ================ R_RenderView @@ -802,33 +860,88 @@ r_refdef must be set before the first call */ extern void R_Sky(void); extern void UploadLightmaps(void); -char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81]; +extern void R_DrawSurfaces(void); +extern void R_DrawPortals(void); +char r_speeds2_string[1024]; +int speedstringcount; + +void timestring(int t, char *desc) +{ + char tempbuf[256]; + int length; + if (t < 1000000) + sprintf(tempbuf, " %6ius %s", t, desc); + else + sprintf(tempbuf, " %6ims %s", t / 1000, desc); + length = strlen(tempbuf); +// while (length < 20) +// tempbuf[length++] = ' '; +// tempbuf[length] = 0; + if (speedstringcount + length > 80) + { + strcat(r_speeds2_string, "\n"); + speedstringcount = 0; + } + // skip the space at the beginning if it's the first on the line + if (speedstringcount == 0) + { + strcat(r_speeds2_string, tempbuf + 1); + speedstringcount = length - 1; + } + else + { + strcat(r_speeds2_string, tempbuf); + speedstringcount += length; + } +} + +#define TIMEREPORT(NAME) \ + if (r_speeds2.value)\ + {\ + temptime = currtime;\ + currtime = Sys_DoubleTime();\ + timestring((int) ((currtime - temptime) * 1000000.0), NAME);\ + } + void R_RenderView (void) { double starttime, currtime, temptime; - int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend, time_total; // if (r_norefresh.value) // return; - if (!r_worldentity.render.model || !cl.worldmodel) + if (!cl.worldmodel) Host_Error ("R_RenderView: NULL worldmodel"); - lighthalf = gl_lightmode.value; - - FOG_framebegin(); - if (r_speeds2.value) + { starttime = currtime = Sys_DoubleTime(); + + speedstringcount = 0; + sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i transpoly\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", + r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]), + c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly, + c_faces, c_nodes, c_leafs, + c_models, c_bmodels, c_sprites, c_particles, c_dlights); + } else starttime = currtime = 0; + + R_MoveParticles (); + R_MoveExplosions(); + + lighthalf = gl_lightmode.value; + + FOG_framebegin(); + R_Clear(); - TIMEREPORT(time_clear) + TIMEREPORT("clear ") // render normal view R_SetupFrame (); R_SetFrustum (); R_SetupGL (); + R_Clip_StartFrame(); R_PrepareEntities(); @@ -836,60 +949,62 @@ void R_RenderView (void) wallpolyclear(); transpolyclear(); - TIMEREPORT(time_setup) + TIMEREPORT("setup ") R_DrawWorld (); - TIMEREPORT(time_world) - R_DrawEntitiesOnList1 (); // BSP models - TIMEREPORT(time_bmodels) + TIMEREPORT("world ") + + R_AddModelEntities(); + TIMEREPORT("addmodels") + + R_Clip_EndFrame(); + TIMEREPORT("scanedge ") + + // now mark the lit surfaces + R_PushDlights (); + // yes this does add the world surfaces after the brush models + R_DrawSurfaces (); + R_DrawPortals (); + TIMEREPORT("surfaces "); UploadLightmaps(); - TIMEREPORT(time_upload) + TIMEREPORT("uploadlmap") - skypolyrender(); // fogged sky polys, affects depth + // fogged sky polys, affects depth + skypolyrender(); + // does not affect depth, draws over the sky polys if (currentskypoly) - R_Sky(); // does not affect depth, draws over the sky polys - TIMEREPORT(time_sky) + R_Sky(); + TIMEREPORT("skypoly ") wallpolyrender(); - TIMEREPORT(time_wall) + TIMEREPORT("wallpoly ") GL_DrawDecals(); - TIMEREPORT(time_drawdecals) + TIMEREPORT("ddecal ") + // don't let sound skip if going slow if (!intimerefresh && !r_speeds2.value) - S_ExtraUpdate (); // don't let sound get messed up if going slow + S_ExtraUpdate (); - R_DrawEntitiesOnList2 (); // other models -// R_RenderDlights (); R_DrawViewModel (); - TIMEREPORT(time_models) - R_MoveParticles (); - TIMEREPORT(time_moveparticles) + R_DrawModels (); + TIMEREPORT("models ") + R_DrawParticles (); - TIMEREPORT(time_drawparticles) - R_MoveExplosions(); - TIMEREPORT(time_moveexplosions) + TIMEREPORT("dparticles") R_DrawExplosions(); - TIMEREPORT(time_drawexplosions) + TIMEREPORT("dexplosion") transpolyrender(); - TIMEREPORT(time_transpoly) + TIMEREPORT("transpoly ") FOG_frameend(); GL_BlendView(); - TIMEREPORT(time_blend) + TIMEREPORT("blend ") + if (r_speeds2.value) - { - time_total = (int) ((Sys_DoubleTime() - starttime) * 1000000.0); - sprintf(r_speeds2_string1, "%6i walls %6i dlitwalls %7i modeltris %7i transpoly\n", c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly); - sprintf(r_speeds2_string2, "BSP: %6i faces %6i nodes %6i leafs\n", c_faces, c_nodes, c_leafs); - sprintf(r_speeds2_string3, "%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights); - sprintf(r_speeds2_string4, "%6ius clear %6ius setup %6ius world %6ius bmodel %6ius upload", time_clear, time_setup, time_world, time_bmodels, time_upload); - sprintf(r_speeds2_string5, "%6ius sky %6ius wall %6ius models %6ius mpart %6ius dpart ", time_sky, time_wall, time_models, time_moveparticles, time_drawparticles); - sprintf(r_speeds2_string6, "%6ius mexplo %6ius dexplo %6ius decals %6ius trans %6ius blend ", time_moveexplosions, time_drawexplosions, time_drawdecals, time_transpoly, time_blend); - sprintf(r_speeds2_string7, "%6ius permdl %6ius total ", time_models / max(c_models, 1), time_total); - } + timestring((int) ((Sys_DoubleTime() - starttime) * 1000000.0), "total "); } diff --git a/gl_rmisc.c b/gl_rmisc.c index d570e3b2..5a8a874b 100644 --- a/gl_rmisc.c +++ b/gl_rmisc.c @@ -48,19 +48,16 @@ void R_Envmap_f (void) r_refdef.viewangles[0] = 0; r_refdef.viewangles[1] = 0; r_refdef.viewangles[2] = 0; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); R_RenderView (); glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); r_refdef.viewangles[1] = 90; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); R_RenderView (); glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); r_refdef.viewangles[1] = 180; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); R_RenderView (); glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); @@ -73,14 +70,12 @@ void R_Envmap_f (void) r_refdef.viewangles[0] = -90; r_refdef.viewangles[1] = 0; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); R_RenderView (); glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); r_refdef.viewangles[0] = 90; r_refdef.viewangles[1] = 0; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); R_RenderView (); glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); @@ -133,10 +128,6 @@ void R_NewMap (void) for (i=0 ; i<256 ; i++) d_lightstylevalue[i] = 264; // normal light value - memset (&r_worldentity, 0, sizeof(r_worldentity)); - r_worldentity.render.model = cl.worldmodel; - currententity = &r_worldentity; - r_viewleaf = NULL; R_Modules_NewMap(); diff --git a/gl_rsurf.c b/gl_rsurf.c index 8029f021..7479d5e3 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. int lightmap_textures; -// LordHavoc: skinny but tall lightmaps for quicker subimage uploads #define BLOCK_WIDTH 256 #define BLOCK_HEIGHT 256 // LordHavoc: increased lightmap limit from 64 to 1024 @@ -48,6 +47,8 @@ cvar_t r_ambient = {"r_ambient", "0"}; cvar_t gl_vertex = {"gl_vertex", "0"}; cvar_t r_dlightmap = {"r_dlightmap", "1"}; cvar_t r_drawportals = {"r_drawportals", "0"}; +cvar_t r_testvis = {"r_testvis", "0"}; +cvar_t r_solidworldnode = {"r_solidworldnode", "1"}; qboolean lightmaprgba, nosubimagefragments, nosubimage; int lightmapbytes; @@ -79,11 +80,13 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&gl_vertex); Cvar_RegisterVariable(&r_dlightmap); Cvar_RegisterVariable(&r_drawportals); + Cvar_RegisterVariable(&r_testvis); + Cvar_RegisterVariable(&r_solidworldnode); R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } -int dlightdivtable[32768]; +int dlightdivtable[32768]; /* R_AddDynamicLights @@ -260,12 +263,12 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights */ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) { - int smax, tmax; - int i, j, size, size3; - byte *lightmap; - int scale; - int maps; - int *bl; + int smax, tmax; + int i, j, size, size3; + byte *lightmap; + int scale; + int maps; + int *bl; surf->cached_dlight = 0; surf->cached_lighthalf = lighthalf; @@ -660,7 +663,7 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) || (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2]) || (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3])))) R_UpdateLightmap(s, s->lightmaptexturenum); - if (r_dlightmap.value || s->dlightframe != r_framecount) + if (s->dlightframe != r_framecount || r_dlightmap.value) { // LordHavoc: fast path version for no vertex lighting cases wp = &wallpoly[currentwallpoly]; @@ -674,7 +677,7 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture); wp->firstvert = currentwallvert; wp->numverts = p->numverts; - wp->lit = lit; + wp->lit = false; wp++; currentwallpoly++; currentwallvert += p->numverts; @@ -844,6 +847,67 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model); +float bmverts[256*3]; + +int vertexworld; + +/* +void RBrushModelSurf_DoVisible(msurface_t *surf) +{ +// float *v, *bmv, *endbmv; +// glpoly_t *p; +// for (p = surf->polys;p;p = p->next) +// { +// for (v = p->verts[0], bmv = bmpoints, endbmv = bmv + p->numverts * 3;bmv < endbmv;v += VERTEXSIZE, bmv += 3) +// softwaretransform(v, bmv); +// if (R_Clip_Polygon(bmpoints, p->numverts, sizeof(float) * 3, surf->flags & SURF_CLIPSOLID)) + surf->visframe = r_framecount; +// } +} +*/ + +void RBrushModelSurf_Callback(void *data, void *data2) +{ + entity_t *ent = data2; + msurface_t *surf = data; + texture_t *t; + + /* + // FIXME: implement better dupe prevention in AddPolygon callback code + if (ent->render.model->firstmodelsurface != 0) + { + // it's not an instanced model, so we already rely on there being only one of it (usually a valid assumption, but QC can break this) + if (surf->visframe == r_framecount) + return; + } + */ + surf->visframe = r_framecount; + + c_faces++; + + currententity = ent; + modelalpha = ent->render.alpha; + + softwaretransformforbrushentity (ent); + + if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) + { + // sky and liquid don't need sorting (skypoly/transpoly) + if (surf->flags & SURF_DRAWSKY) + RSurf_DrawSky(surf, true); + else + RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), true, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); + } + else + { + t = R_TextureAnimation(surf->texinfo->texture); + if (surf->texinfo->texture->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1) + RSurf_DrawWallVertex(surf, t, true, true); + else + RSurf_DrawWall(surf, t, true); + } +} + /* ================= R_DrawBrushModel @@ -851,12 +915,13 @@ R_DrawBrushModel */ void R_DrawBrushModel (entity_t *e) { - int i; + int i, j; vec3_t mins, maxs; msurface_t *s; model_t *clmodel; - int rotated, vertexlit = false; + int rotated; vec3_t org; + glpoly_t *p; currententity = e; @@ -878,7 +943,7 @@ void R_DrawBrushModel (entity_t *e) VectorAdd (e->render.origin, clmodel->maxs, maxs); } - if (R_VisibleCullBox (mins, maxs)) + if (R_CullBox (mins, maxs)) return; c_bmodels++; @@ -896,16 +961,16 @@ void R_DrawBrushModel (entity_t *e) modelorg[2] = DotProduct (temp, up); } + softwaretransformforbrushentity (e); + for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++) { + s->visframe = -1; if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0)) s->visframe = r_framecount; - else - s->visframe = -1; } -// calculate dynamic lighting for bmodel if it's not an -// instanced model +// calculate dynamic lighting for bmodel if it's not an instanced model for (i = 0;i < MAX_DLIGHTS;i++) { if (!cl_dlights[i].radius) @@ -914,11 +979,7 @@ void R_DrawBrushModel (entity_t *e) VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org); R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel); } - vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1; - - e->render.angles[0] = -e->render.angles[0]; // stupid quake bug - softwaretransformforentity (e); - e->render.angles[0] = -e->render.angles[0]; // stupid quake bug +// vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1; // draw texture for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++) @@ -926,6 +987,13 @@ void R_DrawBrushModel (entity_t *e) if (s->visframe == r_framecount) { // R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent); + for (p = s->polys;p;p = p->next) + { + for (j = 0;j < p->numverts;j++) + softwaretransform(&p->verts[j][0], bmverts + j * 3); + R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && modelalpha == 1, RBrushModelSurf_Callback, s, e, NULL); + } + /* if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) { // sky and liquid don't need sorting (skypoly/transpoly) @@ -942,6 +1010,7 @@ void R_DrawBrushModel (entity_t *e) else RSurf_DrawWall(s, t, true); } + */ } } UploadLightmaps(); @@ -955,6 +1024,7 @@ void R_DrawBrushModel (entity_t *e) ============================================================= */ +/* static byte *worldvis; void R_MarkLeaves (void) @@ -968,63 +1038,364 @@ void R_MarkLeaves (void) worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); } +*/ -void R_SolidWorldNode (void) +void RSurf_Callback(void *data, void *junk) +{ + ((msurface_t *)data)->visframe = r_framecount; +} + +/* +void RSurf_Callback(void *data, void *junk) +{ + msurface_t *surf = data; + texture_t *t; + +// if (surf->visframe == r_framecount) +// return; + + surf->visframe = r_framecount; + + c_faces++; + + if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) + { + // sky and liquid don't need sorting (skypoly/transpoly) + if (surf->flags & SURF_DRAWSKY) + RSurf_DrawSky(surf, false); + else + RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); + } + else + { + t = R_TextureAnimation(surf->texinfo->texture); + if (vertexworld) + RSurf_DrawWallVertex(surf, t, false, false); + else + RSurf_DrawWall(surf, t, false); + } +} +*/ + +/* +mleaf_t *r_oldviewleaf; +int r_markvisframecount = 0; + +void R_MarkLeaves (void) { - int l; + static float noviscache; + int i, l, k, c; mleaf_t *leaf; msurface_t *surf, **mark, **endmark; + model_t *model = cl.worldmodel; +// mportal_t *portal; + glpoly_t *p; + byte *in; + int row; + + // ignore testvis if the map just changed + if (r_testvis.value && model->nodes->markvisframe == r_markvisframecount) + return; + + if (r_oldviewleaf == r_viewleaf && noviscache == r_novis.value) + return; + + r_oldviewleaf = r_viewleaf; + noviscache = r_novis.value; - for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++) + if ((in = r_viewleaf->compressed_vis)) { - if (leaf->nummarksurfaces) + row = (model->numleafs+7)>>3; + + if (!r_testvis.value) + r_markvisframecount++; + + // LordHavoc: mark the root node as visible, it will terminate all other ascensions + model->nodes->markvisframe = r_markvisframecount; + + k = 0; + while (k < row) { - if (R_CullBox(leaf->mins, leaf->maxs)) - continue; + c = *in++; + if (c) + { + l = model->numleafs - (k << 3); + if (l > 8) + l = 8; + for (i=0 ; ileafs[(k << 3)+i+1]; + node = (mnode_t *)leaf; + do + { + node->markvisframe = r_markvisframecount; + node = node->parent; + } + while (node->markvisframecount != r_markvisframecount); + } + } + k++; + } + else + k += *in++; + } + } + else + { + // LordHavoc: no vis data, mark everything as visible + model->nodes->markvisframe = r_markvisframecount; - c_leafs++; + for (i = 1;i < model->numleafs;i++) + { + node = (mnode_t *)&model->leafs[i]; + do + { + node->markvisframe = r_markvisframecount; + node = node->parent; + } + while (node->markvisframecount != r_markvisframecount); + } + } +} +*/ - leaf->visframe = r_framecount; +void R_SolidWorldNode (void) +{ + if ((int) r_solidworldnode.value == 2) + { + mnode_t *nodestack[8192], *node = cl.worldmodel->nodes; + int nodestackpos = 0; + glpoly_t *p; - if (leaf->nummarksurfaces) +loc0: + if (node->numsurfaces) + { + msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces; + tinyplane_t plane; + if (PlaneDiff (r_origin, node->plane) < 0) { - mark = leaf->firstmarksurface; - endmark = mark + leaf->nummarksurfaces; - do + for (;surf < surfend;surf++) { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) + if (surf->flags & SURF_PLANEBACK) { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; + VectorNegate(surf->plane->normal, plane.normal); + plane.dist = -surf->plane->dist; + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, &plane); } - else + } + } + else + { + for (;surf < surfend;surf++) + { + if (!(surf->flags & SURF_PLANEBACK)) + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); + } + } + } + + // recurse down the children + if (node->children[0]->contents >= 0) + { + if (node->children[1]->contents >= 0) + { + if (nodestackpos < 8192) + nodestack[nodestackpos++] = node->children[1]; + node = node->children[0]; + goto loc0; + } + node = node->children[0]; + goto loc0; + } + else if (node->children[1]->contents >= 0) + { + node = node->children[1]; + goto loc0; + } + else if (nodestackpos > 0) + { + node = nodestack[--nodestackpos]; + goto loc0; + } + } + else if ((int) r_solidworldnode.value == 1) + { + glpoly_t *p; + msurface_t *surf, *endsurf; + tinyplane_t plane; + + + surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; + endsurf = surf + cl.worldmodel->nummodelsurfaces; + for (;surf < endsurf;surf++) + { + if (PlaneDiff(r_origin, surf->plane) < 0) + { + if (surf->flags & SURF_PLANEBACK) + { + VectorNegate(surf->plane->normal, plane.normal); + plane.dist = -surf->plane->dist; + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); + } + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)&surf->plane); + } + } + } + else + { + int l; + mleaf_t *leaf; + msurface_t *surf, **mark, **endmark; + glpoly_t *p; + tinyplane_t plane; + + for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++) + { + if (R_CullBox(leaf->mins, leaf->maxs)) + continue; +// leaf->visframe = r_framecount; + c_leafs++; + if (leaf->nummarksurfaces) + { +// if (R_CullBox(leaf->mins, leaf->maxs)) +// continue; + + if (leaf->nummarksurfaces) + { + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + do { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) + { + if (surf->flags & SURF_PLANEBACK) + { + VectorNegate(surf->plane->normal, plane.normal); + plane.dist = -surf->plane->dist; + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); + } + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); + } } + while (mark < endmark); + } + } + } + } +} + +/* +void RSurf_Callback(void *data, void *junk) +{ + ((msurface_t *)data)->visframe = r_framecount; +} + +int R_FrustumTestPolygon(float *points, int numpoints, int stride); + +void RSurf_DoVisible(msurface_t *surf) +{ + glpoly_t *p; + for (p = surf->polys;p;p = p->next) + if (R_FrustumTestPolygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float)) >= 3) +// R_Clip_Polygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float), true, RSurf_Callback, surf, 1); +// if (R_Clip_Polygon((float *) p->verts, p->numverts, VERTEXSIZE * sizeof(float), surf->flags & SURF_CLIPSOLID)) + surf->visframe = r_framecount; +} +*/ + +//mleaf_t *llistbuffer[32768], *l, **llist; + +/* +void RSurfLeaf_Callback(void *data) +{ + int portalstackpos = 0; + mleaf_t *leaf; + mportal_t *p, *portalstack[32768]; + msurface_t *surf, **mark, **endmark; + do + { + + leaf = data; + if (leaf->visframe == r_framecount) + return; + leaf->visframe = r_framecount; + + c_leafs++; + + if (leaf->nummarksurfaces) + { + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + do + { + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) + { + if (surf->flags & SURF_PLANEBACK) + RSurf_DoVisible(surf); + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + RSurf_DoVisible(surf); } - while (mark < endmark); + } + while (mark < endmark); + } + + // follow portals into other leafs + for (p = leaf->portals;p;p = p->next) + { + if (p->past->visframe != r_framecount && DotProduct(r_origin, p->plane.normal) < p->plane.dist) + { + // R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3, RSurfLeaf_Callback, p->past, 1); + if (R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3)) + portalstack[portalstackpos++] = p; } } } + while(portalstackpos); + RSurfLeaf_Callback(p->past); + // upon returning, R_ProcessSpans will notice that the spans have changed and restart the line, this is ok because we're not adding any polygons that aren't already behind the portal } +*/ /* // experimental and inferior to the other in recursion depth allowances void R_PortalWorldNode (void) { - int i, j; +// int i, j; mportal_t *p; msurface_t *surf, **mark, **endmark; - mleaf_t *leaf, *llistbuffer[8192], **l, **llist; + mleaf_t *leaf, *llistbuffer[32768], **l, **llist; leaf = r_viewleaf; - leaf->worldnodeframe = r_framecount; + leaf->visframe = r_framecount; l = llist = &llistbuffer[0]; *llist++ = r_viewleaf; while (l < llist) @@ -1033,8 +1404,6 @@ void R_PortalWorldNode (void) c_leafs++; - leaf->visframe = r_framecount; - if (leaf->nummarksurfaces) { mark = leaf->firstmarksurface; @@ -1049,47 +1418,427 @@ void R_PortalWorldNode (void) if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) { if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; + RSurf_DoVisible(surf); } else { if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; + RSurf_DoVisible(surf); } } while (mark < endmark); } // follow portals into other leafs - p = leaf->portals; - for (;p;p = p->next) + for (p = leaf->portals;p;p = p->next) { - leaf = p->past; - if (leaf->worldnodeframe != r_framecount) + if (p->past->visframe != r_framecount) { - leaf->worldnodeframe = r_framecount; - i = (leaf - cl.worldmodel->leafs) - 1; - if ((worldvis[i>>3] & (1<<(i&7))) && R_NotCulledBox(leaf->mins, leaf->maxs)) - *llist++ = leaf; + if (R_Clip_Portal((float *) p->points, p->numpoints, sizeof(float) * 3)) + { + p->past->visframe = r_framecount; + *llist++ = p->past; + } } } + +// for (p = leaf->portals;p;p = p->next) +// { +// leaf = p->past; +// if (leaf->worldnodeframe != r_framecount) +// { +// leaf->worldnodeframe = r_framecount; +// i = (leaf - cl.worldmodel->leafs) - 1; +// if ((worldvis[i>>3] & (1<<(i&7))) && R_NotCulledBox(leaf->mins, leaf->maxs)) +// *llist++ = leaf; +// } +// } } +// i = 0; +// j = 0; +// p = r_viewleaf->portals; +// for (;p;p = p->next) +// { +// j++; +// if (p->past->worldnodeframe != r_framecount) +// i++; +// } +// if (i) +// Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, j); +} +*/ + +/* +#define MAXRECURSIVEPORTALPLANES 1024 +#define MAXRECURSIVEPORTALS 256 + +tinyplane_t portalplanes[MAXRECURSIVEPORTALPLANES]; +int portalplanestack[MAXRECURSIVEPORTALS]; +int portalplanecount; +int ranoutofportalplanes; +int ranoutofportals; +int ranoutofleafs; +int portalcantseeself; +int portalrecursion; + +int R_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p) +{ + int i, outpoints, prevside, side; + float *prevpoint, prevdist, dist, dot; + + if (inpoints < 3) + return inpoints; + // begin with the last point, then enter the loop with the first point as current + prevpoint = in + 3 * (inpoints - 1); + prevdist = DotProduct(prevpoint, p->normal) - p->dist; + prevside = prevdist >= 0 ? SIDE_FRONT : SIDE_BACK; i = 0; - j = 0; - p = r_viewleaf->portals; - for (;p;p = p->next) + outpoints = 0; + goto begin; + for (;i < inpoints;i++) { - j++; - if (p->past->worldnodeframe != r_framecount) - i++; + prevpoint = in; + prevdist = dist; + prevside = side; + in += 3; + +begin: + dist = DotProduct(in, p->normal) - p->dist; + side = dist >= 0 ? SIDE_FRONT : SIDE_BACK; + + if (prevside == SIDE_FRONT) + { + if (outpoints >= maxoutpoints) + return -1; + VectorCopy(prevpoint, out); + out += 3; + outpoints++; + if (side == SIDE_FRONT) + continue; + } + else if (side == SIDE_BACK) + continue; + + // generate a split point + if (outpoints >= maxoutpoints) + return -1; + dot = prevdist / (prevdist - dist); + out[0] = prevpoint[0] + dot * (in[0] - prevpoint[0]); + out[1] = prevpoint[1] + dot * (in[1] - prevpoint[1]); + out[2] = prevpoint[2] + dot * (in[2] - prevpoint[2]); + out += 3; + outpoints++; + } + + return outpoints; +} + +float portaltemppoints[2][256][3]; +float portaltemppoints2[256][3]; + +int R_FrustumTestPolygon(float *points, int numpoints, int stride) +{ + int i; + float *out; + if (numpoints < 3) + return numpoints; + out = &portaltemppoints[0][0][0]; + for (i = 0;i < numpoints;i++) + { + VectorCopy(points, portaltemppoints[0][i]); + (byte *)points += stride; + } + numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, (tinyplane_t *)&frustum[0]); + if (numpoints < 3) + return numpoints; + numpoints = R_ClipPolygonToPlane(&portaltemppoints[1][0][0], &portaltemppoints[0][0][0], numpoints, 256, (tinyplane_t *)&frustum[1]); + if (numpoints < 3) + return numpoints; + numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, (tinyplane_t *)&frustum[2]); + if (numpoints < 3) + return numpoints; + return R_ClipPolygonToPlane(&portaltemppoints[1][0][0], &portaltemppoints[0][0][0], numpoints, 256, (tinyplane_t *)&frustum[3]); +} + +void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p) +{ + vec3_t v1, v2; + VectorSubtract(point1, point2, v1); + VectorSubtract(point3, point2, v2); + CrossProduct(v1, v2, p->normal); +// VectorNormalize(p->normal); + VectorNormalizeFast(p->normal); + p->dist = DotProduct(point1, p->normal); +} + +int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints) +{ + int numpoints, i; + if (targnumpoints < 3) + return targnumpoints; + if (maxpoints < 3) + return -1; + numpoints = targnumpoints; + memcpy(&portaltemppoints[0][0][0], targpoints, numpoints * 3 * sizeof(float)); + for (i = 0;i < clipnumplanes;i++) + { + numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i); + if (numpoints < 3) + return numpoints; + memcpy(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float)); + } + if (numpoints > maxpoints) + return -1; + memcpy(out, &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float)); + return numpoints; +} + +#define MAXRECURSIVEPORTALLEAFS 256 + +//mleaf_t *leafstack[MAXRECURSIVEPORTALLEAFS]; +//int leafstackpos; +int r_portalframecount; + +void R_RecursivePortalWorldNode (mleaf_t *leaf, int firstclipplane, int numclipplanes) +{ + mportal_t *p; + +// if (leafstackpos >= MAXRECURSIVEPORTALLEAFS) +// { +// ranoutofleafs = true; +// return; +// } + +// leafstack[leafstackpos++] = leaf; + + if (leaf->visframe != r_framecount) + { + c_leafs++; + leaf->visframe = r_framecount; + if (leaf->nummarksurfaces) + { + msurface_t *surf, **mark, **endmark; + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + do + { + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) + { + if (surf->flags & SURF_PLANEBACK) + RSurf_DoVisible(surf); + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + RSurf_DoVisible(surf); + } + } + while (mark < endmark); + } + } + + // follow portals into other leafs + for (p = leaf->portals;p;p = p->next) + { + int newpoints, i, prev; + vec3_t center; + vec3_t v1, v2; + tinyplane_t *newplanes; + // only flow through portals facing away from the viewer + if (PlaneDiff(r_origin, (&p->plane)) < 0) + { +*/ + /* + for (i = 0;i < leafstackpos;i++) + if (leafstack[i] == p->past) + break; + if (i < leafstackpos) + { + portalrecursion = true; + continue; + } + */ +/* + newpoints = R_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256); + if (newpoints < 3) + continue; + else if (firstclipplane + numclipplanes + newpoints > MAXRECURSIVEPORTALPLANES) + ranoutofportalplanes = true; + else + { + // go ahead and mark the leaf early, nothing can abort here + if (!r_testvis.value) + p->visframe = r_portalframecount; + + // find the center by averaging + VectorClear(center); + for (i = 0;i < newpoints;i++) + VectorAdd(center, portaltemppoints2[i], center); + // ixtable is a 1.0f / N table + VectorScale(center, ixtable[newpoints], center); + // calculate the planes, and make sure the polygon can see it's own center + newplanes = &portalplanes[firstclipplane + numclipplanes]; + for (prev = newpoints - 1, i = 0;i < newpoints;prev = i, i++) + { +// R_TriangleToPlane(r_origin, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i); + VectorSubtract(r_origin, portaltemppoints2[i], v1); + VectorSubtract(portaltemppoints2[prev], portaltemppoints2[i], v2); + CrossProduct(v1, v2, newplanes[i].normal); + VectorNormalizeFast(newplanes[i].normal); + newplanes[i].dist = DotProduct(r_origin, newplanes[i].normal); + if (DotProduct(newplanes[i].normal, center) <= newplanes[i].dist) + { + // polygon can't see it's own center, discard and use parent portal + break; + } + } + if (i == newpoints) + R_RecursivePortalWorldNode(p->past, firstclipplane + numclipplanes, newpoints); + else + R_RecursivePortalWorldNode(p->past, firstclipplane, numclipplanes); + } + } + } +// leafstackpos--; +} + +//float viewportalpoints[16*3]; + +*/ + +int r_portalframecount = 0; + +/* +void R_Portal_Callback(void *data, void *data2) +{ + mleaf_t *leaf = data; + if (!r_testvis.value) + ((mportal_t *)data2)->visframe = r_portalframecount; + if (leaf->visframe != r_framecount) + { + c_leafs++; + leaf->visframe = r_framecount; } - if (i) - Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, j); } */ -void R_PortalWorldNode (void) +void R_PVSWorldNode() +{ + int i/*, l*/, k, c, row, numbits, bit, leafnum, numleafs; + mleaf_t *leaf; + msurface_t *surf, **mark, **endmark; + model_t *model = cl.worldmodel; + byte *in; +// mportal_t *portal; + glpoly_t *p; + tinyplane_t plane; + +// c_leafs++; +// r_viewleaf->visframe = r_framecount; + if (!r_testvis.value) + r_portalframecount++; + + numleafs = model->numleafs; + numbits = numleafs - 1; + k = 0; + in = r_viewleaf->compressed_vis; + row = (numbits + 7) >> 3; + while (k < row) + { + c = *in++; + if (c) + { + for (i = 0, bit = 1;c;i++, bit <<= 1) + { + if (c & bit) + { + leafnum = (k << 3)+i+1; + if (leafnum >= numleafs) + return; + c -= bit; + leaf = &model->leafs[leafnum]; + if (R_NotCulledBox(leaf->mins, leaf->maxs)) + { + //for (portal = leaf->portals;portal;portal = portal->next) + // if (DotProduct(r_origin, portal->plane.normal) > portal->plane.dist) + // R_Clip_AddPolygon((float *)portal->points, portal->numpoints, sizeof(mvertex_t), false, R_Portal_Callback, leaf, portal, portal->plane); + //leaf->visframe = r_framecount; + c_leafs++; + if (leaf->nummarksurfaces) + { + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + do + { + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) + { + if (surf->flags & SURF_PLANEBACK) + { + VectorNegate(surf->plane->normal, plane.normal); + plane.dist = -surf->plane->dist; + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); + } + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + for (p = surf->polys;p;p = p->next) + R_Clip_AddPolygon((float *)p->verts, p->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); + } + } + while (mark < endmark); + } + } + } + } + k++; + } + else + k += *in++; + } +} + + /* + if (!r_testvis.value) + r_portalframecount = r_framecount; + portalplanecount = 0; +// leafstackpos = 0; + ranoutofportalplanes = false; + ranoutofportals = false; + ranoutofleafs = false; + portalcantseeself = 0; + portalrecursion = false; + memcpy(&portalplanes[0], &frustum[0], sizeof(tinyplane_t)); + memcpy(&portalplanes[1], &frustum[1], sizeof(tinyplane_t)); + memcpy(&portalplanes[2], &frustum[2], sizeof(tinyplane_t)); + memcpy(&portalplanes[3], &frustum[3], sizeof(tinyplane_t)); + R_RecursivePortalWorldNode(r_viewleaf, 0, 4); + if (ranoutofportalplanes) + Con_Printf("R_RecursivePortalWorldNode: ran out of %d plane stack when recursing through portals\n", MAXRECURSIVEPORTALPLANES); + if (ranoutofportals) + Con_Printf("R_RecursivePortalWorldNode: ran out of %d portal stack when recursing through portals\n", MAXRECURSIVEPORTALS); + if (ranoutofleafs) + Con_Printf("R_RecursivePortalWorldNode: ran out of %d leaf stack when recursing through portals\n", MAXRECURSIVEPORTALLEAFS); +// if (portalcantseeself) +// Con_Printf("R_RecursivePortalWorldNode: %d portals could not see themself during clipping\n", portalcantseeself); + if (portalrecursion) + Con_Printf("R_RecursivePortalWorldNode: portal saw into previously encountered leaf??\n"); + */ + +/* +void R_OldPortalWorldNode (void) { int portalstack, i; mportal_t *p, *pstack[8192]; @@ -1170,15 +1919,22 @@ loc1: if (i) Con_Printf("%i portals of viewleaf (%i portals) were not checked\n", i, portalstack); } +*/ + +entity_t clworldent; void R_DrawSurfaces (void) { msurface_t *surf, *endsurf; - texture_t *t; + texture_t *t, *currentt; int vertex = gl_vertex.value; + currententity = &clworldent; + modelalpha = 1; + softwaretransformidentity(); surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; endsurf = surf + cl.worldmodel->nummodelsurfaces; + t = currentt = NULL; for (;surf < endsurf;surf++) { if (surf->visframe == r_framecount) @@ -1190,11 +1946,22 @@ void R_DrawSurfaces (void) if (surf->flags & SURF_DRAWSKY) RSurf_DrawSky(surf, false); else - RSurf_DrawWater(surf, R_TextureAnimation(surf->texinfo->texture), false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); + { + if (currentt != surf->texinfo->texture) + { + currentt = surf->texinfo->texture; + t = R_TextureAnimation(surf->texinfo->texture); + } + RSurf_DrawWater(surf, t, false, surf->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); + } } else { - t = R_TextureAnimation(surf->texinfo->texture); + if (currentt != surf->texinfo->texture) + { + currentt = surf->texinfo->texture; + t = R_TextureAnimation(surf->texinfo->texture); + } if (vertex) RSurf_DrawWallVertex(surf, t, false, false); else @@ -1207,12 +1974,13 @@ void R_DrawSurfaces (void) void R_DrawPortals(void) { int drawportals, i, r, g, b; - mleaf_t *leaf, *endleaf; - mportal_t *portal; - mvertex_t *point, *endpoint; +// mleaf_t *leaf, *endleaf; + mportal_t *portal, *endportal; + mvertex_t *point/*, *endpoint*/; drawportals = (int)r_drawportals.value; if (drawportals < 1) return; + /* leaf = cl.worldmodel->leafs; endleaf = leaf + cl.worldmodel->numleafs; for (;leaf < endleaf;leaf++) @@ -1236,6 +2004,32 @@ void R_DrawPortals(void) } } } + */ + portal = cl.worldmodel->portals; + endportal = portal + cl.worldmodel->numportals; + for (;portal < endportal;portal++) + { + if (portal->visframe == r_portalframecount) + { + i = portal - cl.worldmodel->portals; + r = (i & 0x0007) << 5; + g = (i & 0x0038) << 2; + b = (i & 0x01C0) >> 1; + transpolybegin(0, 0, 0, TPOLYTYPE_ALPHA); + point = portal->points; + if (PlaneDiff(r_origin, (&portal->plane)) > 0) + { + for (i = portal->numpoints - 1;i >= 0;i--) + transpolyvertub(point[i].position[0], point[i].position[1], point[i].position[2], 0, 0, r, g, b, 32); + } + else + { + for (i = 0;i < portal->numpoints;i++) + transpolyvertub(point[i].position[0], point[i].position[1], point[i].position[2], 0, 0, r, g, b, 32); + } + transpolyend(); + } + } } /* @@ -1245,38 +2039,31 @@ R_DrawWorld */ void R_DrawWorld (void) { - entity_t ent; - wateralpha = bound(0, r_wateralpha.value*255.0f, 255); + vertexworld = gl_vertex.value; - memset (&ent, 0, sizeof(ent)); - ent.render.model = cl.worldmodel; - ent.render.colormod[0] = ent.render.colormod[1] = ent.render.colormod[2] = 1; - modelalpha = ent.render.alpha = 1; - ent.render.scale = 1; + memset (&clworldent, 0, sizeof(clworldent)); + clworldent.render.model = cl.worldmodel; + clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1; + modelalpha = clworldent.render.alpha = 1; + clworldent.render.scale = 1; VectorCopy (r_origin, modelorg); - currententity = &ent; + currententity = &clworldent; softwaretransformidentity(); // LordHavoc: clear transform if (cl.worldmodel) { - if (r_viewleaf->contents == CONTENTS_SOLID) + if (r_novis.value || r_viewleaf->compressed_vis == NULL) R_SolidWorldNode (); else { - R_MarkLeaves (); - R_PortalWorldNode (); +// R_MarkLeaves (); + R_PVSWorldNode (); } } - - R_PushDlights (); // now mark the lit surfaces - - R_DrawSurfaces (); - - R_DrawPortals (); } /* @@ -1355,53 +2142,43 @@ int AllocBlock (int w, int h, short *x, short *y) } -mvertex_t *r_pcurrentvertbase; -model_t *currentmodel; - -int nColinElim; +//int nColinElim; /* ================ BuildSurfaceDisplayList ================ */ -void BuildSurfaceDisplayList (msurface_t *fa) +void BuildSurfaceDisplayList (model_t *model, mvertex_t *vertices, msurface_t *fa) { int i, j, lindex, lnumverts; - medge_t *pedges, *r_pedge; - int vertpage; + medge_t *pedges; float *vec; float s, t; glpoly_t *poly; // reconstruct the polygon - pedges = currentmodel->edges; + pedges = model->edges; lnumverts = fa->numedges; - vertpage = 0; // // draw texture // - poly = Hunk_AllocName (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float), "surfaces"); + poly = Hunk_AllocName (sizeof(glpolysizeof_t) + lnumverts * sizeof(float[VERTEXSIZE]), "surfaces"); poly->next = fa->polys; - poly->flags = fa->flags; fa->polys = poly; +// poly->flags = fa->flags; poly->numverts = lnumverts; for (i=0 ; isurfedges[fa->firstedge + i]; + lindex = model->surfedges[fa->firstedge + i]; if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = r_pcurrentvertbase[r_pedge->v[0]].position; - } + vec = vertices[pedges[lindex].v[0]].position; else - { - r_pedge = &pedges[-lindex]; - vec = r_pcurrentvertbase[r_pedge->v[1]].position; - } + vec = vertices[pedges[-lindex].v[1]].position; + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; @@ -1452,7 +2229,7 @@ void BuildSurfaceDisplayList (msurface_t *fa) // skip co-linear points #define COLINEAR_EPSILON 0.001 if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) && - (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && + (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON)) { int j; @@ -1468,9 +2245,9 @@ void BuildSurfaceDisplayList (msurface_t *fa) --i; } } + poly->numverts = lnumverts; } */ - poly->numverts = lnumverts; } /* @@ -1574,8 +2351,6 @@ void GL_BuildLightmaps (void) break; if (m->name[0] == '*') continue; - r_pcurrentvertbase = m->vertexes; - currentmodel = m; for (i=0 ; inumsurfaces ; i++) { if ( m->surfaces[i].flags & SURF_DRAWTURB ) @@ -1583,7 +2358,7 @@ void GL_BuildLightmaps (void) if ( m->surfaces[i].flags & SURF_DRAWSKY ) continue; GL_CreateSurfaceLightmap (m->surfaces + i); - BuildSurfaceDisplayList (m->surfaces + i); + BuildSurfaceDisplayList (m, m->vertexes, m->surfaces + i); } } diff --git a/gl_screen.c b/gl_screen.c index 07238d49..56ba7f3a 100644 --- a/gl_screen.c +++ b/gl_screen.c @@ -274,33 +274,30 @@ static void SCR_CalcRefdef (void) // intermission is always full screen if (cl.intermission) - size = 120; - else - size = scr_viewsize.value; - - if (size >= 120) - sb_lines = 0; // no status bar at all - else if (size >= 110) - sb_lines = 24; // no inventory - else - sb_lines = 24+16+8; - - if (scr_viewsize.value >= 100.0) { full = true; - size = 100.0; + size = 1; + sb_lines = 0; } else - size = scr_viewsize.value; - if (cl.intermission) { - full = true; - size = 100; - sb_lines = 0; + if (scr_viewsize.value >= 120) + sb_lines = 0; // no status bar at all + else if (scr_viewsize.value >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24+16+8; + + if (scr_viewsize.value >= 100.0) + { + full = true; + size = 1.0f; + } + else + size = scr_viewsize.value * (1.0f / 100.0f); } - size /= 100.0; - // LordHavoc: always fullyscreen rendering + // LordHavoc: always fullscreen rendering h = vid.height/* - sb_lines*/; r_refdef.vrect.width = vid.width * size; @@ -599,7 +596,7 @@ void SCR_ScreenShot_f (void) filename[2] = (i/1000)%10 + '0'; filename[3] = (i/ 100)%10 + '0'; filename[4] = (i/ 10)%10 + '0'; - filename[5] = (i/ 1)%10 + '0'; + filename[5] = (i/ 1)%10 + '0'; sprintf (checkname, "%s/%s", com_gamedir, filename); if (Sys_FileTime(checkname) == -1) break; // file doesn't exist @@ -691,7 +688,7 @@ void SCR_DrawNotifyString (void) // for (j=0 ; j 0) + Draw_String(0, y, r_speeds2_string + j, i - j); + if (r_speeds2_string[i] == '\n') + i++; + y += 8; + } } V_UpdateBlends(); diff --git a/gl_textures.c b/gl_textures.c index 3cc49e4d..c7b6221b 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -364,14 +364,14 @@ void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, inrow = (int *)indata + inwidth*(i*inheight/outheight); frac = fracstep >> 1; j = outwidth - 4; - while(j >= 0) + while (j >= 0) { out[0] = inrow[frac >> 16];frac += fracstep; out[1] = inrow[frac >> 16];frac += fracstep; out[2] = inrow[frac >> 16];frac += fracstep; out[3] = inrow[frac >> 16];frac += fracstep; out += 4; - j--; + j -= 4; } if (j & 2) { @@ -605,6 +605,8 @@ rtexture_t *R_LoadTexture (char *identifier, int width, int height, byte *data, if (!identifier[0]) Host_Error("R_LoadTexture: no identifier\n"); + if (data == NULL) + Host_Error("R_LoadTexture: \"%s\" has no data\n", identifier); // clear the alpha flag if the texture has no transparent pixels if (flags & TEXF_ALPHA) diff --git a/glquake.h b/glquake.h index 0607c59f..7a521f1c 100644 --- a/glquake.h +++ b/glquake.h @@ -73,7 +73,6 @@ extern void R_TimeRefresh_f (void); //==================================================== -extern entity_t r_worldentity; extern qboolean r_cache_thrash; // compatability extern vec3_t modelorg, r_entorigin; extern entity_t *currententity; @@ -156,40 +155,3 @@ extern void (GLAPIENTRY *qglUnlockArraysEXT) (void); //#endif #endif - -// LordHavoc: vertex transform -#include "transform.h" - -// LordHavoc: transparent polygon system -#include "gl_poly.h" - -#define gl_solid_format 3 -#define gl_alpha_format 4 - -//#define PARANOID - -// LordHavoc: was a major time waster -#define R_CullBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) == 2 || frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) == 2 || frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) == 2 || frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) == 2) -#define R_NotCulledBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) != 2 && frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) != 2 && frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) != 2 && frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) != 2) - -extern qboolean fogenabled; -extern vec3_t fogcolor; -extern vec_t fogdensity; -//#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])))) -#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0])*((v)[0] - r_origin[0])+((v)[1] - r_origin[1])*((v)[1] - r_origin[1])+((v)[2] - r_origin[2])*((v)[2] - r_origin[2]))))) -#define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255))) - -#include "r_modules.h" - -extern qboolean lighthalf; - -#include "r_lerpanim.h" - -void GL_LockArray(int first, int count); -void GL_UnlockArray(void); - -void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap); - -extern cvar_t r_render; -extern cvar_t r_upload; -#include "image.h" diff --git a/host.c b/host.c index b419f8a9..2ba18dca 100644 --- a/host.c +++ b/host.c @@ -539,11 +539,16 @@ qboolean Host_FilterTime (double time) return false; } - host_realframetime = host_frametime = realtime - oldrealtime; // LordHavoc: copy into host_realframetime as well + // LordHavoc: copy into host_realframetime as well + host_realframetime = host_frametime = realtime - oldrealtime; oldrealtime = realtime; if (cls.timedemo) - return true; // disable time effects + { + // disable time effects + cl.frametime = host_frametime; + return true; + } if (host_framerate.value > 0) host_frametime = host_framerate.value; diff --git a/host_cmd.c b/host_cmd.c index b34c09bc..74550321 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -573,7 +573,7 @@ void Host_Loadgame_f (void) str = Qgetline (f); for (i=0 ; i> 1); + return y * (1.5f - (number * 0.5f * y * y)); +} + +void _VectorNormalizeFast(vec3_t v) +{ + float y, number; + + number = DotProduct(v, v); + + if (number != 0.0) + { + *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1); + y = y * (1.5f - (number * 0.5f * y * y)); + + VectorScale(v, y, v); + } +} + #if 0 // LordHavoc: no longer used at all void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) @@ -538,6 +564,19 @@ void BoxOnPlaneSideClassify(mplane_t *p) } } +void PlaneClassify(mplane_t *p) +{ + if (p->normal[0] == 1) + p->type = 0; + else if (p->normal[1] == 1) + p->type = 1; + else if (p->normal[2] == 1) + p->type = 2; + else + p->type = 3; + BoxOnPlaneSideClassify(p); +} + void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { float angle; @@ -641,7 +680,7 @@ vec_t Length(vec3_t v) { int i; float length; - + length = 0; for (i=0 ; i< 3 ; i++) length += v[i]*v[i]; @@ -691,14 +730,14 @@ float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allo } -void VectorInverse (vec3_t v) +void _VectorInverse (vec3_t v) { v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; } -void VectorScale (vec3_t in, vec_t scale, vec3_t out) +void _VectorScale (vec3_t in, vec_t scale, vec3_t out) { out[0] = in[0]*scale; out[1] = in[1]*scale; diff --git a/mathlib.h b/mathlib.h index 4b613ba9..d3cfe5ee 100644 --- a/mathlib.h +++ b/mathlib.h @@ -62,8 +62,19 @@ extern int nanmask; #define VectorDistance2(a, b) ((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2])) #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b))) #define VectorLength(a) sqrt(DotProduct(a, a)) -#define VectorScaleQuick(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);} +#define VectorScale(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);} #define VectorMAQuick(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];} +#define VectorNormalizeFast(_v)\ +{\ + float _y, _number;\ + _number = DotProduct(_v, _v);\ + if (_number != 0.0)\ + {\ + *((long *)&_y) = 0x5f3759df - ((* (long *) &_number) >> 1);\ + _y = _y * (1.5f - (_number * 0.5f * _y * _y));\ + VectorScale(_v, _y, _v);\ + }\ +}\ void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); @@ -77,9 +88,12 @@ int VectorCompare (vec3_t v1, vec3_t v2); vec_t Length (vec3_t v); float VectorNormalizeLength (vec3_t v); // returns vector length float VectorNormalizeLength2 (vec3_t v, vec3_t dest); // returns vector length -void VectorInverse (vec3_t v); -void VectorScale (vec3_t in, vec_t scale, vec3_t out); +void _VectorInverse (vec3_t v); +void _VectorScale (vec3_t in, vec_t scale, vec3_t out); int Q_log2(int val); +void _VectorNormalizeFast (vec3_t v); + +float Q_RSqrt(float number); #define NUMVERTEXNORMALS 162 extern float m_bytenormals[NUMVERTEXNORMALS][3]; @@ -98,7 +112,7 @@ void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful! void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up); -void BoxOnPlaneSideClassify(struct mplane_s *p); +void PlaneClassify(struct mplane_s *p); #define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ (((p)->type < 3)? \ @@ -118,6 +132,8 @@ void BoxOnPlaneSideClassify(struct mplane_s *p); #define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) #define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist) +//#define PlaneDist(point,plane) (DotProduct((point), (plane)->normal)) +//#define PlaneDiff(point,plane) (DotProduct((point), (plane)->normal) - (plane)->dist) #define lhrandom(MIN,MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN)) @@ -125,3 +141,14 @@ void BoxOnPlaneSideClassify(struct mplane_s *p); #define min(A,B) (A < B ? A : B) #define max(A,B) (A > B ? A : B) #endif + +// LordHavoc: minimal plane structure +typedef struct +{ + float normal[3], dist; +} tinyplane_t; + +typedef struct +{ + double normal[3], dist; +} tinydoubleplane_t; diff --git a/menu.c b/menu.c index 8e3cfbe7..23b6d3de 100644 --- a/menu.c +++ b/menu.c @@ -1236,7 +1236,7 @@ again: //============================================================================= /* OPTIONS MENU */ -#define OPTIONS_ITEMS 23 +#define OPTIONS_ITEMS (vid_menudrawfn ? 23 : 22) #define SLIDER_RANGE 10 @@ -1410,7 +1410,9 @@ void M_Options_Draw (void) M_Print(16, y, " Use Mouse");M_DrawCheckbox(220, y, vid_mouse.value);y += 8; M_Print(16, y, " Crosshair");M_DrawSlider(220, y, crosshair.value / 5);y += 8; M_Print(16, y, " Show Framerate");M_DrawCheckbox(220, y, showfps.value);y += 8; - M_Print(16, y, " Video Options");y += 8; + if (vid_menudrawfn) + M_Print(16, y, " Video Options"); + y += 8; // cursor M_DrawCharacter(200, 32 + options_cursor*8, 12+((int)(realtime*4)&1)); @@ -1440,7 +1442,8 @@ void M_Options_Key (int k) Cbuf_AddText ("exec default.cfg\n"); break; case 22: - M_Menu_Video_f (); + if (vid_menudrawfn) + M_Menu_Video_f (); break; default: M_AdjustSliders (1); diff --git a/model_brush.c b/model_brush.c index b01c1c37..70eae3a6 100644 --- a/model_brush.c +++ b/model_brush.c @@ -817,7 +817,7 @@ void Mod_LoadFaces (lump_t *l) && (out->texinfo->texture->name[2] == 'y' || out->texinfo->texture->name[2] == 'Y')) { // LordHavoc: for consistency reasons, mark sky as fullbright and solid as well - out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA); + out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID); GL_SubdivideSurface (out); // cut up polygon for warps continue; } @@ -839,7 +839,8 @@ void Mod_LoadFaces (lump_t *l) GL_SubdivideSurface (out); // cut up polygon for warps continue; } - + + out->flags |= SURF_CLIPSOLID; } } @@ -1153,7 +1154,6 @@ void Mod_LoadPlanes (lump_t *l) mplane_t *out; dplane_t *in; int count; - int bits; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -1166,18 +1166,13 @@ void Mod_LoadPlanes (lump_t *l) for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); -// if (out->normal[j] < 0) -// bits |= 1<dist = LittleFloat (in->dist); - out->type = LittleLong (in->type); -// out->signbits = bits; - BoxOnPlaneSideClassify(out); + // LordHavoc: recalculated by PlaneClassify, FIXME: validate type and report error if type does not match normal? +// out->type = LittleLong (in->type); + PlaneClassify(out); } } @@ -1574,6 +1569,7 @@ void Mod_FinalizePortals(void) VectorCopy(p->winding->points[j], point->position); point++; } + PlaneClassify(&portal->plane); // link into leaf's portal chain portal->next = portal->here->portals; @@ -1595,6 +1591,7 @@ void Mod_FinalizePortals(void) VectorCopy(p->winding->points[j], point->position); point++; } + PlaneClassify(&portal->plane); // link into leaf's portal chain portal->next = portal->here->portals; diff --git a/model_brush.h b/model_brush.h index cfb371e6..24710e2e 100644 --- a/model_brush.h +++ b/model_brush.h @@ -70,11 +70,10 @@ typedef struct texture_s #define SURF_DRAWTILED 0x20 #define SURF_DRAWBACKGROUND 0x40 //#define SURF_UNDERWATER 0x80 -// LordHavoc: added these for lava and teleport textures #define SURF_DRAWNOALPHA 0x100 #define SURF_DRAWFULLBRIGHT 0x200 -// LordHavoc: light both sides -#define SURF_LIGHTBOTHSIDES 0x400 +#define SURF_LIGHTBOTHSIDES 0x400 +#define SURF_CLIPSOLID 0x800 // this polygon can obscure other polygons typedef struct { @@ -89,17 +88,23 @@ typedef struct } mtexinfo_t; // LordHavoc: was 7, I added one more for raw lightmap position +// (xyz st uv l) #define VERTEXSIZE 8 typedef struct glpoly_s { struct glpoly_s *next; - struct glpoly_s *chain; int numverts; - int flags; // for SURF_UNDERWATER - float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) + float verts[4][VERTEXSIZE]; // variable sized } glpoly_t; +typedef struct glpolysizeof_s +{ + struct glpoly_s *next; + int numverts; + int flags; // for SURF_UNDERWATER +} glpolysizeof_t; + typedef struct msurface_s { int visframe; // should be drawn when node is crossed @@ -109,7 +114,7 @@ typedef struct msurface_s int firstedge; // look up in model->surfedges[], negative numbers int numedges; // are backwards edges - + short texturemins[2]; short extents[2]; @@ -118,7 +123,7 @@ typedef struct msurface_s glpoly_t *polys; // multiple if warped mtexinfo_t *texinfo; - + // lighting info int dlightframe; int dlightbits[8]; @@ -146,7 +151,7 @@ typedef struct mnode_s // node specific mplane_t *plane; - struct mnode_s *children[2]; + struct mnode_s *children[2]; unsigned short firstsurface; unsigned short numsurfaces; @@ -163,8 +168,8 @@ typedef struct mleaf_s struct mportal_s *portals; // leaf specific - int visframe; // visible if current (r_framecount) - int worldnodeframe; // used by certain worldnode variants to avoid processing the same leaf twice in a frame +// int visframe; // visible if current (r_framecount) +// int worldnodeframe; // used by certain worldnode variants to avoid processing the same leaf twice in a frame // for bounding box culling vec3_t mins; @@ -199,6 +204,7 @@ typedef struct mportal_s mvertex_t *points; int numpoints; mplane_t plane; + int visframe; // is this portal visible this frame? } mportal_t; diff --git a/progs.h b/progs.h index a6603d5d..699d84b7 100644 --- a/progs.h +++ b/progs.h @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -29,21 +29,26 @@ typedef union eval_s func_t function; int _int; int edict; -} eval_t; +} eval_t; + +typedef struct link_s +{ + struct link_s *prev, *next; +} link_t; // LordHavoc: increased number of leafs per entity limit from 16 to 256 #define MAX_ENT_LEAFS 256 typedef struct edict_s { qboolean free; - link_t area; // linked to a division node or leaf - + link_t area; + int num_leafs; short leafnums[MAX_ENT_LEAFS]; entity_state_t baseline; entity_state_t deltabaseline; // LordHavoc: previous frame - + float freetime; // sv.time when the object was freed // LordHavoc: for MOVETYPE_STEP interpolation vec3_t steporigin; @@ -54,7 +59,8 @@ typedef struct edict_s entvars_t v; // C exported fields from progs // other fields from progs come immediately after } edict_t; -#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) +//#define EDICT_FROM_AREA(l) ((edict_t *)((byte *)l - (int)&(((edict_t *)0)->area))) +//#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) // LordHavoc: in an effort to eliminate time wasted on GetEdictFieldValue... see pr_edict.c for the functions which use these. extern int eval_gravity; diff --git a/protocol.h b/protocol.h index df79dc83..e7b494b2 100644 --- a/protocol.h +++ b/protocol.h @@ -199,6 +199,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_showlmp 35 // [string] slotname [string] lmpfilename [short] x [short] y #define svc_hidelmp 36 // [string] slotname +#define svc_skybox 37 // [string] skyname #define svc_unusedlh1 #define svc_fog 51 // unfinished diff --git a/quakeio.c b/quakeio.c index 9c75da1a..6e475ccb 100644 --- a/quakeio.c +++ b/quakeio.c @@ -377,16 +377,18 @@ Qgetline (QFile *file) return 0; len = strlen (buf); - while (buf[len - 1] != '\n') { + while (buf[len - 1] != '\n' && buf[len - 1] != '\r') { char *t = realloc (buf, size + 256); if (!t) - return 0; + Host_Error("Qgetline: realloc failed, out of memory?\n"); buf = t; size += 256; if (!Qgets (file, buf + len, size - len)) break; len = strlen (buf); } + while ((len = strlen(buf)) && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) + buf[len - 1] = 0; return buf; } diff --git a/quakeio.h b/quakeio.h index d8319ba7..cf8a9b50 100644 --- a/quakeio.h +++ b/quakeio.h @@ -30,7 +30,7 @@ #ifndef __quakeio_h #define __quakeio_h -#define HAVE_ZLIB +//#define HAVE_ZLIB #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/r_clip.c b/r_clip.c new file mode 100644 index 00000000..373e1fa3 --- /dev/null +++ b/r_clip.c @@ -0,0 +1,1029 @@ + +#include "quakedef.h" + +typedef struct clipsurf_s +{ + struct clipsurf_s *next, *prev; + int state; + int visible; + int solid; + int removed; + void (*callback)(void *nativedata, void *nativedata2); + void *nativedata; + void *nativedata2; + float wstepx, wstepy, w00; + // wcurrent is a cached copy of w00 + wstepy * y, + // updated each time the surface is added to the stack, + // for quicker comparisons. + float wcurrent; + // this is a linked list of all edges belonging to this surface, + // used to remove them if this is a non-solid surface that is + // marked visible (it can not hide anything, so it is useless) +// struct clipedge_s *edgechain; +} +clipsurf_t; + +typedef struct clipedge_s +{ + float x, realx, realxstep; + struct clipedge_s *next, *prev, *nextremove; + clipsurf_t *psurf; + int leading; + int pad; +} +clipedge_t; + +clipsurf_t *pavailsurf, *clipsurfs, *clipsurfsend; +clipedge_t *pavailedge, *clipedges, *clipedgesend, *newedges, **removeedges; + +clipsurf_t surfstack; +clipedge_t edgehead, edgetail; +clipedge_t maxedge = {2000000000.0f}; + +cvar_t r_clipwidth = {"r_clipwidth", "800"}; +cvar_t r_clipheight = {"r_clipheight", "600"}; +cvar_t r_clipedges = {"r_clipedges", "32768", true}; +cvar_t r_clipsurfaces = {"r_clipsurfaces", "8192", true}; + +int clipwidth = 0, clipheight = 0; +int maxclipsurfs = 0, maxclipedges = 0; +int needededges, neededsurfs; + +#if CLIPTEST +typedef struct +{ + float w; // inverse depth (1/z) +} +clippixel_t; + +clippixel_t *clipbuffer; +#endif + +float r_clip_viewmatrix[3][3], r_clip_viewmulx, r_clip_viewmuly, r_clip_viewcenterx, r_clip_viewcentery; +// REMOVELATER +//float xscale, yscale, xscaleinv, yscaleinv; +//float r_clip_nearclipdist, r_clip_nearclipdist2; +tinyplane_t r_clip_viewplane[5]; + +void R_Clip_MakeViewMatrix(void) +{ + float pixelaspect, screenaspect, horizontalfieldofview, verticalfieldofview; + pixelaspect = (float) clipheight / (float) clipwidth * 320 / 240.0; + horizontalfieldofview = 2.0 * tan (r_refdef.fov_x/360*M_PI); + screenaspect = clipwidth * pixelaspect / clipheight; + verticalfieldofview = horizontalfieldofview / screenaspect; + r_clip_viewcenterx = clipwidth * 0.5 - 0.5; + r_clip_viewcentery = clipheight * 0.5 - 0.5; + r_clip_viewmulx = clipwidth / horizontalfieldofview; + r_clip_viewmuly = r_clip_viewmulx * pixelaspect; + // this constructs a transposed rotation matrix for the view (transposed matrices do the opposite of their normal behavior) + VectorCopy (vright, r_clip_viewmatrix[0]); + VectorNegate (vup, r_clip_viewmatrix[1]); + VectorCopy (vpn, r_clip_viewmatrix[2]); +// r_clip_nearclipdist = DotProduct(r_origin, vpn) + 4.0f; +// r_clip_nearclipdist2 = r_clip_nearclipdist - 8.0f; + VectorCopy (vpn, r_clip_viewplane[0].normal); + r_clip_viewplane[0].dist = DotProduct(r_origin, vpn); + memcpy(&r_clip_viewplane[1], &frustum[0], sizeof(tinyplane_t)); + memcpy(&r_clip_viewplane[2], &frustum[1], sizeof(tinyplane_t)); + memcpy(&r_clip_viewplane[3], &frustum[2], sizeof(tinyplane_t)); + memcpy(&r_clip_viewplane[4], &frustum[3], sizeof(tinyplane_t)); +// REMOVELATER +// maxscreenscaleinv = (1.0f / max(clipwidth, clipheight)) * horizontalfieldofview * 0.5f; +// xscale = clipwidth / horizontalfieldofview; +// xscaleinv = 1.0 / xscale; +// yscale = xscale * pixelaspect; +// yscaleinv = 1.0 / yscale; +} + +void R_Clip_StartFrame(void) +{ + int i; + int newwidth, newheight, newmaxedges, newmaxsurfs; + newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2); + newheight = bound(60, (int) r_clipheight.value, vid.height * 2); + newmaxedges = bound(128, (int) r_clipedges.value, 262144); + newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536); + if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs) + { +#if CLIPTEST + if (clipbuffer) + qfree(clipbuffer); +#endif + if (clipedges) + qfree(clipedges); + if (clipsurfs) + qfree(clipsurfs); + if (newedges) + qfree(newedges); + if (removeedges) + qfree(removeedges); + clipwidth = newwidth; + clipheight = newheight; + maxclipedges = newmaxedges; + maxclipsurfs = newmaxsurfs; +#if CLIPTEST + clipbuffer = qmalloc(clipwidth * clipheight * sizeof(clippixel_t)); +#endif + clipedges = qmalloc(maxclipedges * sizeof(clipedge_t)); + clipsurfs = qmalloc(maxclipsurfs * sizeof(clipsurf_t)); + newedges = qmalloc(clipheight * sizeof(clipedge_t)); + removeedges = qmalloc(clipheight * sizeof(clipedge_t *)); + clipedgesend = clipedges + maxclipedges; + clipsurfsend = clipsurfs + maxclipsurfs; + } +#if CLIPTEST + memset(clipbuffer, 0, clipwidth * clipheight * sizeof(clippixel_t)); +#endif + pavailedge = clipedges; + pavailsurf = clipsurfs; + // Clear the lists of edges to add and remove on each scan line. + + needededges = 0; + neededsurfs = 0; + for (i = 0;i < clipheight;i++) + { + newedges[i].next = &maxedge; + removeedges[i] = NULL; + } + + R_Clip_MakeViewMatrix(); +} + +void ScanEdges (void); + +void R_Clip_EndFrame(void) +{ + ScanEdges(); + if (maxclipedges < needededges) + { + Con_Printf("R_Clip: ran out of edges, increasing limit from %d to %d\n", maxclipedges, needededges); + Cvar_SetValue("r_clipedges", needededges); + } + if (maxclipsurfs < neededsurfs) + { + Con_Printf("R_Clip: ran out of surfaces, increasing limit from %d to %d\n", maxclipsurfs, neededsurfs); + Cvar_SetValue("r_clipsurfaces", neededsurfs); + } +} + +void r_clip_start(void) +{ +} + +void r_clip_shutdown(void) +{ +#if CLIPTEST + if (clipbuffer) + qfree(clipbuffer); + clipbuffer = NULL; +#endif + if (clipsurfs) + qfree(clipsurfs); + clipsurfs = NULL; + if (clipedges) + qfree(clipedges); + clipedges = NULL; + if (newedges) + qfree(newedges); + newedges = NULL; + if (removeedges) + qfree(removeedges); + removeedges = NULL; + clipwidth = -1; + clipheight = -1; +} + +void r_clip_newmap(void) +{ +} + +void R_Clip_Init(void) +{ + Cvar_RegisterVariable(&r_clipwidth); + Cvar_RegisterVariable(&r_clipheight); + Cvar_RegisterVariable(&r_clipedges); + Cvar_RegisterVariable(&r_clipsurfaces); + R_RegisterModule("R_Clip", r_clip_start, r_clip_shutdown, r_clip_newmap); +} + +int R_Clip_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p) +{ + float y, number; + vec3_t v1, v2; + VectorSubtract(point1, point2, v1); + VectorSubtract(point3, point2, v2); + CrossProduct(v1, v2, p->normal); + number = DotProduct(p->normal, p->normal); + if (number >= 0.1f) + { + *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1); + y = y * (1.5f - (number * 0.5f * y * y)); + VectorScale(p->normal, y, p->normal); + p->dist = DotProduct(point1, p->normal); + return true; + } + else + return false; +} + +/* +int R_Clip_TriangleToDoublePlane(double *point1, double *point2, double *point3, tinydoubleplane_t *p) +{ + double y, number; + double v1[3], v2[3]; + VectorSubtract(point1, point2, v1); + VectorSubtract(point3, point2, v2); + CrossProduct(v1, v2, p->normal); + number = DotProduct(p->normal, p->normal); + if (number >= 0.1) + { + y = 1.0 / sqrt(number); + VectorScale(p->normal, y, p->normal); + p->dist = DotProduct(point1, p->normal); + return true; + } + else + return false; +} +*/ + +int R_Clip_ClipPolygonToPlane(float *in, float *out, int inpoints, int stride, tinyplane_t *plane) +{ + int i, outpoints, prevside, side; + float *prevpoint, prevdist, dist, dot; + + // begin with the last point, then enter the loop with the first point as current + prevpoint = (float *) ((byte *)in + stride * (inpoints - 1)); + prevdist = DotProduct(prevpoint, plane->normal) - plane->dist; + prevside = prevdist >= 0 ? SIDE_FRONT : SIDE_BACK; + i = 0; + outpoints = 0; + goto begin; + for (;i < inpoints;i++) + { + prevpoint = in; + prevdist = dist; + prevside = side; + (byte *)in += stride; + +begin: + dist = DotProduct(in, plane->normal) - plane->dist; + side = dist >= 0 ? SIDE_FRONT : SIDE_BACK; + + if (prevside == SIDE_FRONT) + { + VectorCopy(prevpoint, out); + out += 3; + outpoints++; + if (side == SIDE_FRONT) + continue; + } + else if (side == SIDE_BACK) + continue; + + // generate a split point + dot = prevdist / (prevdist - dist); + out[0] = prevpoint[0] + dot * (in[0] - prevpoint[0]); + out[1] = prevpoint[1] + dot * (in[1] - prevpoint[1]); + out[2] = prevpoint[2] + dot * (in[2] - prevpoint[2]); + out += 3; + outpoints++; + } + + return outpoints; +} + +float tempverts[256][3]; +float tempverts2[256][3]; +float screenverts[256][3]; + +// LordHavoc: this code is based primarily on the ddjzsort code + +// Clips polygon to view frustum and nearclip, transforms polygon to viewspace, perspective projects polygon to screenspace, +// and adds polygon's edges to the global edge table. +void R_Clip_AddPolygon (vec_t *points, int numverts, int stride, int solid, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2, tinyplane_t *polyplane) +{ + float deltax, deltay, vx, vy, vz, fx; + int i, j, k, nextvert, temp, topy, bottomy, height, addededges; + clipedge_t *pedge; +// tinydoubleplane_t plane; + tinyplane_t localplane; +// tinyplane_t testplane; + float distinv; + +// if (!solid) +// return; + + if (polyplane == NULL) + { + polyplane = &localplane; + // calculate the plane for the polygon + if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), polyplane)) + { + for (i = 0;i < numverts;i++) + for (j = i + 1;j < numverts;j++) + for (k = j + 1;k < numverts;k++) + if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), polyplane)) + goto valid1; + return; // gave up + valid1:; + } + + // caller hasn't checked if this polygon faces the view, so we have to check + if (DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f)) + return; + } +#if 0 // debugging (validates planes passed in) + else + { + // calculate the plane for the polygon + if (!R_Clip_TriangleToPlane((float *) points, (float *) ((byte *)points + stride), (float *) ((byte *)points + 2 * stride), &localplane)) + { + for (i = 0;i < numverts;i++) + for (j = i + 1;j < numverts;j++) + for (k = j + 1;k < numverts;k++) + if (R_Clip_TriangleToPlane((float *) ((byte *)points + i * stride), (float *) ((byte *)points + j * stride), (float *) ((byte *)points + k * stride), &localplane)) + goto valid4; + return; // gave up + valid4:; + } + +// if ((DotProduct(r_origin, polyplane->normal) < (polyplane->dist + 0.5f)) != (DotProduct(r_origin, localplane.normal) < (localplane.dist + 0.5f))) + if (DotProduct(polyplane->normal, localplane.normal) < 0.9f) + { + Con_Printf("*\n"); + return; + } + } +#endif + + // for adaptive limits + needededges += numverts; + neededsurfs++; + + if (pavailsurf >= clipsurfsend) + return; + + // clip to view frustum and nearclip + if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(points , tempverts2[0], numverts, stride, &r_clip_viewplane[0]); + if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[1]); + if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[2]); + if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts2[0], tempverts[0], numverts, sizeof(float) * 3, &r_clip_viewplane[3]); + if (numverts < 3) return;numverts = R_Clip_ClipPolygonToPlane(tempverts[0], tempverts2[0], numverts, sizeof(float) * 3, &r_clip_viewplane[4]); + if (numverts < 3) + return; + if (numverts > 256) + Sys_Error("R_Clip_AddPolygon: polygon exceeded 256 vertex buffer\n"); + + // it survived the clipping, transform to viewspace and project to screenspace + + if (pavailedge + numverts > clipedgesend) + return; + +#if 1 + for (i = 0;i < numverts;i++) + { + vx = tempverts2[i][0] - r_origin[0]; + vy = tempverts2[i][1] - r_origin[1]; + vz = tempverts2[i][2] - r_origin[2]; + screenverts[i][2] = 1.0f / (r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz); + screenverts[i][0] = (r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz) * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx; + screenverts[i][1] = (r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz) * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery; + } + + /* + if (polyplane != NULL) + { + */ + /* + distinv = 1.0f / (polyplane->dist - DotProduct(r_origin, polyplane->normal)); + pavailsurf->wstepx = DotProduct(r_clip_viewmatrix[0], polyplane->normal) * xscaleinv * distinv; + pavailsurf->wstepy = DotProduct(r_clip_viewmatrix[1], polyplane->normal) * yscaleinv * distinv; + pavailsurf->w00 = DotProduct(r_clip_viewmatrix[2], polyplane->normal) * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy; + */ + /* + } + else + { + */ + // calculate the plane for the polygon + if (!R_Clip_TriangleToPlane(screenverts[0], screenverts[1], screenverts[2], &localplane)) + { + for (i = 0;i < numverts;i++) + for (j = i + 1;j < numverts;j++) + for (k = j + 1;k < numverts;k++) + if (R_Clip_TriangleToPlane(screenverts[i], screenverts[j], screenverts[k], &localplane)) + goto valid; + return; // gave up + valid:; + } + + // Set up the 1/z gradients from the polygon, calculating the + // base value at screen coordinate 0,0 so we can use screen + // coordinates directly when calculating 1/z from the gradients + distinv = 1.0f / localplane.normal[2]; + pavailsurf->wstepx = -(localplane.normal[0] * distinv); + pavailsurf->wstepy = -(localplane.normal[1] * distinv); + pavailsurf->w00 = localplane.dist * distinv; + /* + } + */ + // REMOVELATER + /* + prevdist = z1 * plane.normal[2] - plane.dist; + dist = z2 * plane.normal[2] - plane.dist; + d = prevdist / (prevdist - dist); + zc = z1 + d * (z2 - z1); + + prevdist = plane.normal[0] + z1 * plane.normal[2] - plane.dist; + dist = plane.normal[0] + z2 * plane.normal[2] - plane.dist; + d = prevdist / (prevdist - dist); + zx = (z1 + d * (z2 - z1)) - zc; + + prevdist = plane.normal[1] + z1 * plane.normal[2] - plane.dist; + dist = plane.normal[1] + z2 * plane.normal[2] - plane.dist; + d = prevdist / (prevdist - dist); + zy = (z1 + d * (z2 - z1)) - zc; + */ + + /* + zc = (-plane.dist) / ((-plane.dist) - (plane.normal[2] - plane.dist)); + zx = ((plane.normal[0] - plane.dist) / ((plane.normal[0] - plane.dist) - (plane.normal[0] + plane.normal[2] - plane.dist))) - zc; + zy = ((plane.normal[1] - plane.dist) / ((plane.normal[1] - plane.dist) - (plane.normal[1] + plane.normal[2] - plane.dist))) - zc; + */ + +// zc = (plane.dist / plane.normal[2]); +// zx = -(plane.normal[0] / plane.normal[2]); +// zy = -(plane.normal[1] / plane.normal[2]); +// zy = ((plane.normal[1] - plane.dist) / (-plane.normal[2])) + ((plane.dist) / (-plane.normal[2])); +#else // REMOVELATER + for (i = 0;i < numverts;i++) + { + vx = tempverts2[i][0] - r_origin[0]; + vy = tempverts2[i][1] - r_origin[1]; + vz = tempverts2[i][2] - r_origin[2]; + screenverts[i][0] = r_clip_viewmatrix[0][0] * vx + r_clip_viewmatrix[0][1] * vy + r_clip_viewmatrix[0][2] * vz; + screenverts[i][1] = r_clip_viewmatrix[1][0] * vx + r_clip_viewmatrix[1][1] * vy + r_clip_viewmatrix[1][2] * vz; + screenverts[i][2] = r_clip_viewmatrix[2][0] * vx + r_clip_viewmatrix[2][1] * vy + r_clip_viewmatrix[2][2] * vz; + } + + // REMOVELATER + // calculate the plane for the polygon + for (i = 0;i < numverts;i++) + for (j = i + 1;j < numverts;j++) + for (k = j + 1;k < numverts;k++) + if (R_Clip_TriangleToDoublePlane(screenverts[i], screenverts[j], screenverts[k], &plane)) + goto valid2; + return; // gave up +valid2:; + + distinv = 1.0f / plane.dist; + pavailsurf->d_zistepx = plane.normal[0] * xscaleinv * distinv; + pavailsurf->d_zistepy = -plane.normal[1] * yscaleinv * distinv; + pavailsurf->d_ziorigin = plane.normal[2] * distinv - r_clip_viewcenterx * pavailsurf->wstepx - r_clip_viewcentery * pavailsurf->wstepy; + + for (i = 0;i < numverts;i++) + { + screenverts[i][2] = 1.0f / (screenverts[i][2]); + screenverts[i][0] = screenverts[i][0] * r_clip_viewmulx * screenverts[i][2] + r_clip_viewcenterx; + screenverts[i][1] = screenverts[i][1] * r_clip_viewmuly * screenverts[i][2] + r_clip_viewcentery; + // REMOVELATER +// if (screenverts[i][0] < -0.5) +// screenverts[i][0] = -0.5; +// if (screenverts[i][0] > (clipwidth - 0.5)) +// screenverts[i][0] = clipwidth - 0.5; +// if (screenverts[i][1] < -0.5) +// screenverts[i][1] = -0.5; +// if (screenverts[i][1] > (clipheight - 0.5)) +// screenverts[i][1] = clipheight - 0.5; +// if (screenverts[i][2] <= 0.0) +// Con_Printf("R_Clip_AddPolygon: vertex z <= 0!\n"); + } +#endif + + addededges = false; + + // Add each edge in turn + for (i = 0;i < numverts;i++) + { + nextvert = i + 1; + if (nextvert >= numverts) + nextvert = 0; + + topy = (int)ceil(screenverts[i][1]); + bottomy = (int)ceil(screenverts[nextvert][1]); + height = bottomy - topy; + if (height == 0) + continue; // doesn't cross any scan lines + if (height < 0) + { + // Leading edge + temp = topy; + topy = bottomy; + bottomy = temp; + if (topy < 0) + topy = 0; + if (bottomy > clipheight) + bottomy = clipheight; + if (topy >= bottomy) + continue; + + pavailedge->leading = 1; + + deltax = screenverts[i][0] - screenverts[nextvert][0]; + deltay = screenverts[i][1] - screenverts[nextvert][1]; + + pavailedge->realxstep = deltax / deltay; + pavailedge->realx = screenverts[nextvert][0] + ((float)topy - screenverts[nextvert][1]) * pavailedge->realxstep; + } + else + { + // Trailing edge + if (topy < 0) + topy = 0; + if (bottomy > clipheight) + bottomy = clipheight; + if (topy >= bottomy) + continue; + + pavailedge->leading = 0; + + deltax = screenverts[nextvert][0] - screenverts[i][0]; + deltay = screenverts[nextvert][1] - screenverts[i][1]; + + pavailedge->realxstep = deltax / deltay; + pavailedge->realx = screenverts[i][0] + ((float)topy - screenverts[i][1]) * pavailedge->realxstep; + } + + // Put the edge on the list to be added on top scan + fx = pavailedge->x = bound(0.0f, pavailedge->realx, clipwidth - 0.5f); + pedge = &newedges[topy]; + while (fx > pedge->next->x) + pedge = pedge->next; + pavailedge->next = pedge->next; + pedge->next = pavailedge; + + // Put the edge on the list to be removed after final scan + pavailedge->nextremove = removeedges[bottomy - 1]; + removeedges[bottomy - 1] = pavailedge; + + // Associate the edge with the surface + pavailedge->psurf = pavailsurf; + + pavailedge++; + + addededges = true; + } + + if (!addededges) + return; + + // Create the surface, so we'll know how to sort and draw from the edges + pavailsurf->next = NULL; + pavailsurf->prev = NULL; + pavailsurf->state = 0; + pavailsurf->visible = false; + pavailsurf->callback = callback; + pavailsurf->nativedata = nativedata; + pavailsurf->nativedata2 = nativedata2; + pavailsurf->solid = solid; + pavailsurf->removed = false; + pavailsurf++; +} + +///////////////////////////////////////////////////////////////////// +// Scan all the edges in the global edge table into spans. +///////////////////////////////////////////////////////////////////// +void ScanEdges (void) +{ + int y, rescan; + float fx, fy, w, w2, clipwidthf = clipwidth - 0.5f; + clipedge_t *pedge, *pedge2, *ptemp; + clipsurf_t *psurf, *psurf2; +#if CLIPTEST + int x, x2; + float zi; + clippixel_t *cb; +#endif + float cx; + + // Set up the active edge list as initially empty, containing + // only the sentinels (which are also the background fill). Most + // of these fields could be set up just once at start-up + edgehead.next = &edgetail; + edgehead.prev = NULL; + edgehead.x = edgehead.realx = -0.9999f; // left edge of screen + edgehead.realxstep = 0; + edgehead.leading = 1; + edgehead.psurf = &surfstack; + + edgetail.next = NULL; // mark end of list + edgetail.prev = &edgehead; + edgetail.x = edgetail.realx = clipwidth + 0.5f; // right edge of screen + edgetail.realxstep = 0; + edgetail.leading = 0; + edgetail.psurf = &surfstack; + + // The background surface is the entire stack initially, and + // is infinitely far away, so everything sorts in front of it. + // This could be set just once at start-up + surfstack.solid = true; + surfstack.visible = true; // no callback + surfstack.next = surfstack.prev = &surfstack; + surfstack.wcurrent = surfstack.w00 = -999999.0; + surfstack.wstepx = surfstack.wstepy = 0.0; + surfstack.removed = false; + + // rescan causes the edges to be compared at the span level + // it is false if the scanline will be identical to the previous + rescan = true; + for (y = 0;y < clipheight;y++) + { + fy = y; +#if CLIPTEST + cb = clipbuffer + y * clipwidth; +#endif + + // Sort in any edges that start on this scan + if (newedges[y].next != &maxedge) + { + rescan = true; + pedge = newedges[y].next; + pedge2 = &edgehead; + while (pedge != &maxedge) + { + if (pedge->psurf->removed) + { + pedge = pedge->next; + continue; + } + + while (pedge->x > pedge2->next->x) + pedge2 = pedge2->next; + + ptemp = pedge->next; + pedge->next = pedge2->next; + pedge->prev = pedge2; + pedge2->next->prev = pedge; + pedge2->next = pedge; + + pedge2 = pedge; + pedge = ptemp; + } + } + + // Scan out the active edges into spans + + // Start out with the left background edge already inserted, and the surface stack containing only the background + surfstack.state = 1; + cx = 0; + + // must always rescan if rendering to wbuffer +#ifndef CLIPTEST +// if (rescan) +#endif + { + for (pedge = edgehead.next;pedge;pedge = pedge->next) + { + edgeremoved: + psurf = pedge->psurf; + if (psurf->removed) + { + pedge2 = pedge->next; + pedge->prev->next = pedge->next; + pedge->next->prev = pedge->prev; + pedge->next = pedge->prev = pedge; + pedge = pedge2; + if (pedge) + goto edgeremoved; + else + break; + } + + if (pedge->leading) + { + // It's a leading edge. Figure out where it is + // relative to the current surfaces and insert in + // the surface stack; if it's on top, emit the span + // for the current top. + // First, make sure the edges don't cross + if (++psurf->state == 1) + { + fx = pedge->x; + // Calculate the surface's 1/z value at this pixel, and cache the y depth for quick compares later + w = (psurf->wcurrent = psurf->w00 + psurf->wstepy * fy) + psurf->wstepx * fx; +// if (w < 0) +// w = 0; + + // See if that makes it a new top surface + psurf2 = surfstack.next; + w2 = psurf2->wcurrent + psurf2->wstepx * fx; +// if (w2 < 0 && psurf2 != &surfstack) +// w2 = 0; + + if (w >= w2) + { + // It's a new top surface + // emit the span for the current top + if (fx > cx && !psurf2->visible) + { + psurf2->visible = true; + psurf2->callback(psurf2->nativedata, psurf2->nativedata2); + } + +#if CLIPTEST + for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf2->wcurrent + psurf2->wstepx * x;x < x2;x++, zi += psurf2->wstepx) + cb[x].w = zi; +#endif + + cx = fx; + + // Add the edge to the stack + psurf->next = psurf2; + psurf2->prev = psurf; + surfstack.next = psurf; + psurf->prev = &surfstack; + } + else + { + // Not a new top; sort into the surface stack. + // Guaranteed to terminate due to sentinel background surface + do + { + psurf2 = psurf2->next; + w2 = psurf2->wcurrent + psurf2->wstepx * fx; +// if (w2 < 0 && psurf2 != &surfstack) +// w2 = 0; + } + while (w < w2); + + // Insert the surface into the stack + psurf->next = psurf2; + psurf->prev = psurf2->prev; + psurf2->prev->next = psurf; + psurf2->prev = psurf; + } + } + } + else + { + // It's a trailing edge; if this was the top surface, + // emit the span and remove it. + // First, make sure the edges didn't cross + if (--psurf->state == 0) + { + if (surfstack.next == psurf) + { + fx = pedge->x; + + // It's on top, emit the span + if (fx > cx && !psurf->visible) + { + psurf->visible = true; + psurf->callback(psurf->nativedata, psurf->nativedata2); + } + +#if CLIPTEST + fx = pedge->x; + for (x = ceil(cx), x2 = ceil(fx) >= clipwidth ? clipwidth : ceil(fx), zi = psurf->w00 + psurf->wstepx * x + psurf->wstepy * fy;x < x2;x++, zi += psurf->wstepx) + cb[x].w = zi; +#endif + + cx = fx; + } + + // Remove the surface from the stack + psurf->next->prev = psurf->prev; + psurf->prev->next = psurf->next; + } + } + + // mark and remove all non-solid surfaces that are ontop + while (!surfstack.next->solid) + { + psurf = surfstack.next; + if (!psurf->visible) + { + psurf->visible = true; + psurf->callback(psurf->nativedata, psurf->nativedata2); + } + psurf->removed = true; + psurf->next->prev = psurf->prev; + psurf->prev->next = psurf->next; + // isolate the surface + psurf->next = psurf->prev = psurf; + } + } + rescan = false; + } + + // Remove edges that are done + pedge = removeedges[y]; + if (pedge) + { + while (pedge) + { + if (!pedge->psurf->removed) + { + pedge->prev->next = pedge->next; + pedge->next->prev = pedge->prev; + if (pedge->psurf->visible) + rescan = true; + } + pedge = pedge->nextremove; + } + } + + // Step the remaining edges one scan line, and re-sort + for (pedge = edgehead.next;pedge != &edgetail;) + { + ptemp = pedge->next; + if (pedge->psurf->removed) + { + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + pedge->next = pedge->prev = pedge; + pedge = ptemp; + continue; + } + + // Step the edge + if (pedge->realxstep) + { + pedge->realx += pedge->realxstep; + pedge->x = bound(0.0f, pedge->realx, clipwidthf); + } + fx = pedge->x; + + // Move the edge back to the proper sorted location, if necessary + while (fx < pedge->prev->x) + { + if (!rescan && (pedge->psurf->solid || pedge->prev->psurf->solid)) + rescan = true; + pedge2 = pedge->prev; + pedge2->next = pedge->next; + pedge->next->prev = pedge2; + pedge2->prev->next = pedge; + pedge->prev = pedge2->prev; + pedge->next = pedge2; + pedge2->prev = pedge; + } + + pedge = ptemp; + } + } +} + +void R_Clip_DisplayBuffer(void) +{ +#if CLIPTEST + int i; + static int firstupload = true; + byte clipbuffertex[256*256], *b; + if (!r_render.value) + return; + if (clipwidth > 256 || clipheight > 256) + return; + glBlendFunc(GL_ONE, GL_ONE); + glBindTexture(GL_TEXTURE_2D, 8000); + if (firstupload) + { + memset(clipbuffertex, 0, sizeof(clipbuffertex)); + glTexImage2D(GL_TEXTURE_2D, 0, 1, 256, 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex); + } + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (lighthalf) + glColor3f(0.5, 0.5, 0.5); + else + glColor3f(1, 1, 1); + firstupload = false; + b = clipbuffertex; + for (i = 0;i < clipwidth*clipheight;i++) + { + if (clipbuffer[i].w > 0) + *b++ = bound(0, (int) (clipbuffer[i].w * 4096.0f), 255); + else + *b++ = 0; + } + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex); + glBegin (GL_QUADS); + glTexCoord2f (0 , 0 );glVertex2f (0 , 0 ); + glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.width, 0 ); + glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height); + glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.height); + glEnd (); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#endif +} + +float boxpoints[4*3]; + +#define R_Clip_MinsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \ +{\ + if (r_origin[(axis)] < ((axisvalue) - 0.5f))\ + {\ + (plane)->dist = -axisvalue;\ + boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\ + boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\ + boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\ + boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\ + R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\ + }\ +} + +#define R_Clip_MaxsBoxPolygon(axis, axisvalue, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, callback, nativedata, nativedata2, plane) \ +{\ + if (r_origin[(axis)] > ((axisvalue) + 0.5f))\ + {\ + (plane)->dist = axisvalue;\ + boxpoints[ 0] = x1;boxpoints[ 1] = y1;boxpoints[ 2] = z1;\ + boxpoints[ 3] = x2;boxpoints[ 4] = y2;boxpoints[ 5] = z2;\ + boxpoints[ 6] = x3;boxpoints[ 7] = y3;boxpoints[ 8] = z3;\ + boxpoints[ 9] = x4;boxpoints[10] = y4;boxpoints[11] = z4;\ + R_Clip_AddPolygon (boxpoints, 4, sizeof(float[3]), false, callback, nativedata, nativedata2, plane);\ + }\ +} + +tinyplane_t clipboxplane[6] = +{ + {{-1, 0, 0}, 0}, + {{ 1, 0, 0}, 0}, + {{ 0, -1, 0}, 0}, + {{ 0, 1, 0}, 0}, + {{ 0, 0, -1}, 0}, + {{ 0, 0, 1}, 0}, +}; + +void R_Clip_AddBox(float *a, float *b, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2) +{ + if (r_origin[0] >= (a[0] - 5.0f) && r_origin[0] < (b[0] + 5.0f) + && r_origin[1] >= (a[1] - 5.0f) && r_origin[1] < (b[1] + 5.0f) + && r_origin[2] >= (a[2] - 5.0f) && r_origin[2] < (b[2] + 5.0f)) + { + callback(nativedata, nativedata2); + return; + } + + if (R_CullBox(a, b)) + return; + + R_Clip_MinsBoxPolygon + ( + 0, a[0], + a[0], a[1], a[2], + a[0], b[1], a[2], + a[0], b[1], b[2], + a[0], a[1], b[2], + callback, nativedata, nativedata2, &clipboxplane[0] + ); + R_Clip_MaxsBoxPolygon + ( + 0, b[0], + b[0], b[1], a[2], + b[0], a[1], a[2], + b[0], a[1], b[2], + b[0], b[1], b[2], + callback, nativedata, nativedata2, &clipboxplane[1] + ); + R_Clip_MinsBoxPolygon + ( + 1, a[1], + b[0], a[1], a[2], + a[0], a[1], a[2], + a[0], a[1], b[2], + b[0], a[1], b[2], + callback, nativedata, nativedata2, &clipboxplane[2] + ); + R_Clip_MaxsBoxPolygon + ( + 1, b[1], + a[0], b[1], a[2], + b[0], b[1], a[2], + b[0], b[1], b[2], + a[0], b[1], b[2], + callback, nativedata, nativedata2, &clipboxplane[3] + ); + R_Clip_MinsBoxPolygon + ( + 2, a[2], + a[0], a[1], a[2], + b[0], a[1], a[2], + b[0], b[1], a[2], + a[0], b[1], a[2], + callback, nativedata, nativedata2, &clipboxplane[4] + ); + R_Clip_MaxsBoxPolygon + ( + 2, b[2], + b[0], a[1], b[2], + a[0], a[1], b[2], + a[0], b[1], b[2], + b[0], b[1], b[2], + callback, nativedata, nativedata2, &clipboxplane[5] + ); +} diff --git a/r_clip.h b/r_clip.h new file mode 100644 index 00000000..6c3c02fa --- /dev/null +++ b/r_clip.h @@ -0,0 +1,14 @@ + +void R_Clip_StartFrame(void); +void R_Clip_EndFrame(void); +//int R_Clip_Polygon(float *inv, int numpoints, int stride, int solid); +//int R_Clip_Portal(float *inv, int numpoints, int stride); +// This takes a polygon in the form of vec_t triplets, at a caller specified +// stride (structure size), it can be solid (obscures other geometry) or not, +// a callback and two parameters must be provided (will be called if it is +// determined visible), and a plane can be provided (this also indicates that +// the surface is not a backface, so if a plane is provided, the caller must +// check that it is not a backface, it is not likely to be fatal if the caller +// does not, but it is inadvisable) +void R_Clip_AddPolygon (vec_t *points, int numverts, int stride, int solid, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2, tinyplane_t *polyplane); +void R_Clip_AddBox(float *mins, float *maxs, void (*callback)(void *nativedata, void *nativedata2), void *nativedata, void *nativedata2); diff --git a/r_light.c b/r_light.c index 168efc5d..5e05081e 100644 --- a/r_light.c +++ b/r_light.c @@ -234,9 +234,9 @@ void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitind R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode); } -int lightframe = 0; void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model) { + static int lightframe = 0; mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); if (!r_dynamic.value) @@ -258,7 +258,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex lightframe++; - radius = light->radius * 2; + radius = light->radius * 3; // clamp radius to avoid exceeding 32768 entry division table if (radius > 2048) @@ -284,10 +284,10 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex if (c & (1<leafs[(k << 3)+i+1]; - if (leaf->visframe != r_framecount) - continue; - if (leaf->contents == CONTENTS_SOLID) - continue; +// if (leaf->visframe != r_framecount) +// continue; +// if (leaf->contents == CONTENTS_SOLID) +// continue; // if out of the light radius, skip if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0] || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1] @@ -305,14 +305,17 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex do { surf = *mark++; - if (surf->visframe != r_framecount || surf->lightframe == lightframe) + // if not visible in current frame, or already marked because it was in another leaf we passed, skip + if (surf->lightframe == lightframe) continue; surf->lightframe = lightframe; + if (surf->visframe != r_framecount) + continue; dist = PlaneDiff(lightorigin, surf->plane); if (surf->flags & SURF_PLANEBACK) dist = -dist; // LordHavoc: make sure it is infront of the surface and not too far away - if ((dist >= -0.25f || (surf->flags & SURF_LIGHTBOTHSIDES)) && dist < radius) + if (dist < radius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -radius))) { int d; float dist2, impact[3]; @@ -405,6 +408,8 @@ void R_PushDlights (void) // R_MarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel->nodes ); R_VisMarkLights (l->origin, l, 1<<(i&31), i >> 5, cl.worldmodel); } + + } @@ -645,6 +650,34 @@ loc0: lightmap += size3; } + /* + // LordHavoc: here's the readable version of the interpolation + // code, not quite as easy for the compiler to optimize... + + // dsfrac is the X position in the lightmap pixel, * 16 + // dtfrac is the Y position in the lightmap pixel, * 16 + // r00 is top left corner, r01 is top right corner + // r10 is bottom left corner, r11 is bottom right corner + // g and b are the same layout. + // r0 and r1 are the top and bottom intermediate results + + // first we interpolate the top two points, to get the top + // edge sample + r0 = (((r01-r00) * dsfrac) >> 4) + r00; + g0 = (((g01-g00) * dsfrac) >> 4) + g00; + b0 = (((b01-b00) * dsfrac) >> 4) + b00; + // then we interpolate the bottom two points, to get the + // bottom edge sample + r1 = (((r11-r10) * dsfrac) >> 4) + r10; + g1 = (((g11-g10) * dsfrac) >> 4) + g10; + b1 = (((b11-b10) * dsfrac) >> 4) + b10; + // then we interpolate the top and bottom samples to get the + // middle sample (the one which was requested) + r = (((r1-r0) * dtfrac) >> 4) + r0; + g = (((g1-g0) * dtfrac) >> 4) + g0; + b = (((b1-b0) * dtfrac) >> 4) + b0; + */ + color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f); color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f); color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f); diff --git a/r_part.c b/r_part.c index b5624af0..3256c3b5 100644 --- a/r_part.c +++ b/r_part.c @@ -1348,7 +1348,7 @@ void R_DrawParticles (void) float scale, scale2, minparticledist; byte *color24; vec3_t uprightangles, up2, right2, tempcolor, corner; - mleaf_t *leaf; +// mleaf_t *leaf; // LordHavoc: early out condition if ((!numparticles) || (!r_drawparticles.value)) @@ -1377,9 +1377,9 @@ void R_DrawParticles (void) continue; // LordHavoc: check if it's in a visible leaf - leaf = Mod_PointInLeaf(p->org, cl.worldmodel); - if (leaf->visframe != r_framecount) - continue; +// leaf = Mod_PointInLeaf(p->org, cl.worldmodel); +// if (leaf->visframe != r_framecount) +// continue; /* if (p->type == pt_decal) diff --git a/r_sprites.c b/r_sprites.c index bdc18f50..27da0a66 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -1,13 +1,82 @@ #include "quakedef.h" +void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, vec3_t origin, vec3_t up, vec3_t right) +{ + int i; + mspriteframe_t *frame; + vec3_t points[4]; + float fleft, fright, fdown, fup; + frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame; + fleft = frame->left; + fdown = frame->down; + fright = frame->right; + fup = frame->up; + for (i = 1;i < 4 && blend[i].lerp;i++) + { + frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[i].frame; + fleft = min(fleft , frame->left ); + fdown = min(fdown , frame->down ); + fright = max(fright, frame->right); + fup = max(fup , frame->up ); + } + points[0][0] = origin[0] + fdown * up[0] + fleft * right[0];points[0][1] = origin[1] + fdown * up[1] + fleft * right[1];points[0][2] = origin[2] + fdown * up[2] + fleft * right[2]; + points[1][0] = origin[0] + fup * up[0] + fleft * right[0];points[1][1] = origin[1] + fup * up[1] + fleft * right[1];points[1][2] = origin[2] + fup * up[2] + fleft * right[2]; + points[2][0] = origin[0] + fup * up[0] + fright * right[0];points[2][1] = origin[1] + fup * up[1] + fright * right[1];points[2][2] = origin[2] + fup * up[2] + fright * right[2]; + points[3][0] = origin[0] + fdown * up[0] + fright * right[0];points[3][1] = origin[1] + fdown * up[1] + fright * right[1];points[3][2] = origin[2] + fdown * up[2] + fright * right[2]; + R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, e, NULL, NULL); +} + +void R_ClipSprite (entity_t *e, frameblend_t *blend) +{ + vec3_t right, up, org; + msprite_t *psprite; + + if (!blend[0].lerp) + return; + + psprite = Mod_Extradata(e->render.model); + + if (psprite->type == SPR_ORIENTED) + { + // bullet marks on walls + vec3_t forward; + AngleVectors (e->render.angles, forward, right, up); + // nudge it toward the view, so it will be infront of the wall + VectorSubtract(e->render.origin, vpn, org); + // don't draw if it's a backface + if (DotProduct(r_origin, forward) < (DotProduct(org, forward) + 1.0f)) + return; + } + else + { + // normal sprite + VectorCopy(vup, up); + VectorCopy(vright, right); + VectorCopy(e->render.origin, org); + // don't draw if it's a backface + if (DotProduct(org, vpn) < (DotProduct(r_origin, vpn) + 1.0f)) + return; + } + + + if (e->render.scale != 1) + { + VectorScale(up, e->render.scale, up); + VectorScale(right, e->render.scale, right); + } + + // LordHavoc: interpolated sprite rendering + R_ClipSpriteImage(e, psprite, blend, org, up, right); +} + void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha) { byte alphaub; alphaub = bound(0, alpha, 255); transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); - transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub); - transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub); - transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub); transpolyvertub(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alphaub); transpolyend(); } @@ -15,20 +84,22 @@ void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t /* ================= R_DrawSpriteModel - ================= */ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) { - vec3_t right, up, org, color, mins, maxs; - byte colorub[4]; - msprite_t *psprite; + vec3_t right, up, org, color, mins, maxs; + byte colorub[4]; + msprite_t *psprite; + + if (!blend[0].lerp) + return; VectorAdd (e->render.origin, e->render.model->mins, mins); VectorAdd (e->render.origin, e->render.model->maxs, maxs); - if (R_VisibleCullBox (mins, maxs)) - return; +// if (R_CullBox (mins, maxs)) +// return; c_sprites++; @@ -37,8 +108,11 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - AngleVectors (e->render.angles, NULL, right, up); + vec3_t forward; + AngleVectors (e->render.angles, forward, right, up); VectorSubtract(e->render.origin, vpn, org); + if (DotProduct(r_origin, forward) < DotProduct(e->render.origin, forward)) + return; // backface } else { // normal sprite @@ -46,6 +120,7 @@ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) VectorCopy(vright, right); VectorCopy(e->render.origin, org); } + if (e->render.scale != 1) { VectorScale(up, e->render.scale, up); diff --git a/render.h b/render.h index 5d834267..b8f164f6 100644 --- a/render.h +++ b/render.h @@ -36,7 +36,7 @@ extern void SHOWLMP_clear(void); // render profiling stuff extern qboolean intimerefresh; extern cvar_t r_speeds2; -extern char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_speeds2_string4[81], r_speeds2_string5[81], r_speeds2_string6[81], r_speeds2_string7[81]; +extern char r_speeds2_string[1024]; // lighting stuff extern vec3_t lightspot; @@ -54,6 +54,9 @@ extern cvar_t r_novis; // model transform stuff extern cvar_t gl_transform; +// LordHavoc: 1.0f / N table +extern float ixtable[4096]; + #define TOP_RANGE 16 // soldier uniform colors #define BOTTOM_RANGE 96 @@ -124,7 +127,7 @@ void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); // called whene // LordHavoc: changed this for sake of GLQuake void R_InitSky (byte *src, int bytesperpixel); // called at level load -int R_VisibleCullBox (vec3_t mins, vec3_t maxs); +//int R_VisibleCullBox (vec3_t mins, vec3_t maxs); void R_NewMap (void); @@ -155,3 +158,47 @@ void R_DrawParticles (void); void R_MoveParticles (void); void R_DrawExplosions (void); void R_MoveExplosions (void); + +#include "r_clip.h" + +// LordHavoc: vertex transform +#include "transform.h" + +// LordHavoc: transparent polygon system +#include "gl_poly.h" + +#define gl_solid_format 3 +#define gl_alpha_format 4 + +//#define PARANOID + +// LordHavoc: was a major time waster +#define R_CullBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) == 2 || frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) == 2 || frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) == 2 || frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) == 2) +#define R_NotCulledBox(mins,maxs) (frustum[0].BoxOnPlaneSideFunc(mins, maxs, &frustum[0]) != 2 && frustum[1].BoxOnPlaneSideFunc(mins, maxs, &frustum[1]) != 2 && frustum[2].BoxOnPlaneSideFunc(mins, maxs, &frustum[2]) != 2 && frustum[3].BoxOnPlaneSideFunc(mins, maxs, &frustum[3]) != 2) + +extern qboolean fogenabled; +extern vec3_t fogcolor; +extern vec_t fogdensity; +//#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])*(((v)[0] - r_origin[0]) * vpn[0] + ((v)[1] - r_origin[1]) * vpn[1] + ((v)[2] - r_origin[2]) * vpn[2])))) +#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_origin[0])*((v)[0] - r_origin[0])+((v)[1] - r_origin[1])*((v)[1] - r_origin[1])+((v)[2] - r_origin[2])*((v)[2] - r_origin[2]))))) +#define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255))) + +#include "r_modules.h" + +extern qboolean lighthalf; + +#include "r_lerpanim.h" + +void GL_LockArray(int first, int count); +void GL_UnlockArray(void); + +void R_DrawBrushModel (entity_t *e); +void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap); +void R_DrawSpriteModel (entity_t *e, frameblend_t *blend); + +void R_ClipSprite (entity_t *e, frameblend_t *blend); +void R_Entity_Callback(void *data, void *junk); + +extern cvar_t r_render; +extern cvar_t r_upload; +#include "image.h" diff --git a/snd_alsa_0_5.c b/snd_alsa_0_5.c index d3551e04..ba04b5b1 100644 --- a/snd_alsa_0_5.c +++ b/snd_alsa_0_5.c @@ -320,7 +320,7 @@ void SNDDMA_Submit(void) switch (mmap_control->status.status) { case SND_PCM_STATUS_PREPARED: if ((rc=snd_pcm_channel_go(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) { - Qprintf(stderr, "unable to start playback. %s\n", + fprintf(stderr, "unable to start playback. %s\n", snd_strerror(rc)); exit(1); } @@ -329,7 +329,7 @@ void SNDDMA_Submit(void) break; case SND_PCM_STATUS_UNDERRUN: if ((rc=snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) { - Qprintf(stderr, "underrun: playback channel prepare error. %s\n", + fprintf(stderr, "underrun: playback channel prepare error. %s\n", snd_strerror(rc)); exit(1); } diff --git a/sv_main.c b/sv_main.c index ef29fbf2..783e6536 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1392,7 +1392,6 @@ void SV_SpawnServer (char *server) ent->v.modelindex = 1; // world model ent->v.solid = SOLID_BSP; ent->v.movetype = MOVETYPE_PUSH; - ent->v.angles[0] = ent->v.angles[1] = ent->v.angles[2] = 0; if (coop.value) pr_global_struct->coop = coop.value; @@ -1406,7 +1405,7 @@ void SV_SpawnServer (char *server) ED_LoadFromFile (sv.worldmodel->entities); // LordHavoc: clear world angles (to fix e3m3.bsp) - sv.edicts->v.angles[0] = sv.edicts->v.angles[1] = sv.edicts->v.angles[2] = 0; + VectorClear(sv.edicts->v.angles); sv.active = true; diff --git a/sv_user.c b/sv_user.c index 16405a07..9bf6c218 100644 --- a/sv_user.c +++ b/sv_user.c @@ -260,7 +260,7 @@ void SV_WaterMove (void) { int i; vec3_t wishvel; - float speed, newspeed, wishspeed, addspeed, accelspeed; + float speed, newspeed, wishspeed, addspeed, accelspeed, temp; // // user intentions @@ -278,7 +278,8 @@ void SV_WaterMove (void) wishspeed = Length(wishvel); if (wishspeed > sv_maxspeed.value) { - VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); + temp = sv_maxspeed.value/wishspeed; + VectorScale (wishvel, temp, wishvel); wishspeed = sv_maxspeed.value; } wishspeed *= 0.7; @@ -291,8 +292,9 @@ void SV_WaterMove (void) { newspeed = speed - sv.frametime * speed * sv_friction.value; if (newspeed < 0) - newspeed = 0; - VectorScale (velocity, newspeed/speed, velocity); + newspeed = 0; + temp = newspeed/speed; + VectorScale (velocity, temp, velocity); } else newspeed = 0; @@ -339,7 +341,7 @@ void SV_AirMove (void) { int i; vec3_t wishvel; - float fmove, smove; + float fmove, smove, temp; // LordHavoc: correct quake movement speed bug when looking up/down wishvel[0] = wishvel[2] = 0; @@ -366,7 +368,8 @@ void SV_AirMove (void) wishspeed = VectorNormalizeLength(wishdir); if (wishspeed > sv_maxspeed.value) { - VectorScale (wishvel, sv_maxspeed.value/wishspeed, wishvel); + temp = sv_maxspeed.value/wishspeed; + VectorScale (wishvel, temp, wishvel); wishspeed = sv_maxspeed.value; } diff --git a/sys_linux.c b/sys_linux.c index e886874f..6428c179 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -259,11 +259,13 @@ int Sys_FileOpenWrite (char *path) umask (0); - handle = open(path,O_RDWR | O_CREAT | O_TRUNC - , 0666); + handle = open(path,O_RDWR | O_CREAT | O_TRUNC, 0666); if (handle == -1) - Sys_Error ("Error opening %s: %s", path,strerror(errno)); + { + Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno)); + return 0; + } return handle; } diff --git a/sys_win.c b/sys_win.c index be6021c7..1327b35d 100644 --- a/sys_win.c +++ b/sys_win.c @@ -152,7 +152,10 @@ int Sys_FileOpenWrite (char *path) f = Qopen(path, "wb"); if (!f) - Host_Error ("Error opening %s: %s", path,strerror(errno)); + { + Con_Printf("Sys_FileOpenWrite: Error opening %s: %s", path, strerror(errno)); + return 0; + } sys_handles[i] = f; return i; @@ -338,7 +341,7 @@ double Sys_DoubleTime (void) static double oldtime = 0.0, basetime = 0.0, old = 0.0; double newtime, now; - now = (double) timeGetTime () - basetime; + now = (double) timeGetTime () + basetime; if (first) { @@ -350,7 +353,7 @@ double Sys_DoubleTime (void) if (now < old) { // wrapped - basetime -= (65536.0 * 65536.0); + basetime += (65536.0 * 65536.0); now += (65536.0 * 65536.0); } old = now; diff --git a/transform.c b/transform.c index b4945e19..9396bbe3 100644 --- a/transform.c +++ b/transform.c @@ -156,3 +156,9 @@ void softwaretransformforentity (entity_t *e) angles[2] = e->render.angles[2]; softwaretransformset(e->render.origin, angles, e->render.scale); } + +// brush entities are not backwards like models and sprites are +void softwaretransformforbrushentity (entity_t *e) +{ + softwaretransformset(e->render.origin, e->render.angles, e->render.scale); +} diff --git a/transform.h b/transform.h index 506e5ed2..6b0494ec 100644 --- a/transform.h +++ b/transform.h @@ -11,6 +11,7 @@ extern vec3_t softwaretransform_z; extern int softwaretransform_type; extern void softwaretransformforentity (entity_t *e); +extern void softwaretransformforbrushentity (entity_t *e); extern void softwaretransformidentity (void); extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale); extern void (*softwaretransform) (vec3_t in, vec3_t out); diff --git a/vid.h b/vid.h index 174e7813..f2757bbd 100644 --- a/vid.h +++ b/vid.h @@ -19,12 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // vid.h -- video driver defs -#define VID_CBITS 6 -#define VID_GRADES (1 << VID_CBITS) - -// a pixel can be one, two, or four bytes -typedef byte pixel_t; - typedef struct vrect_s { int x,y,width,height; @@ -33,12 +27,11 @@ typedef struct vrect_s typedef struct { - unsigned width; - unsigned height; - float aspect; // width / height -- < 0 is taller than wide - int recalc_refdef; // if true, recalc vid-based stuff - unsigned conwidth; - unsigned conheight; + int width; + int height; + int recalc_refdef; // if true, recalc vid-based stuff + int conwidth; + int conheight; } viddef_t; extern viddef_t vid; // global video state diff --git a/vid_3dfxsvga.c b/vid_3dfxsvga.c index 7136f042..6583d37d 100644 --- a/vid_3dfxsvga.c +++ b/vid_3dfxsvga.c @@ -363,8 +363,6 @@ void VID_Init(void) vid.width = vid.conwidth; vid.height = vid.conheight; - vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); - InitSig(); // trap evil signals GL_Init(); diff --git a/vid_glx.c b/vid_glx.c index 1938a0dd..69b8c61d 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -52,16 +52,15 @@ static GLXContext ctx = NULL; viddef_t vid; // global video state static qboolean mouse_avail = true; -static qboolean mouse_active = false; +static qboolean mouse_active = false, usingmouse = false; // static qboolean dga_active; static float mouse_x, mouse_y; static float old_mouse_x, old_mouse_y; static int p_mouse_x, p_mouse_y; -static cvar_t in_mouse = {"in_mouse", "1", false}; -static cvar_t in_dga = {"in_dga", "1", false}; -static cvar_t in_dga_mouseaccel = {"in_dga_mouseaccel", "1", false}; -static cvar_t m_filter = {"m_filter", "0"}; +cvar_t vid_dga = {"vid_dga", "1", true}; +cvar_t vid_dga_mouseaccel = {"vid_dga_mouseaccel", "1", false}; +cvar_t m_filter = {"m_filter", "0"}; qboolean vidmode_ext = false; @@ -93,7 +92,8 @@ XLateKey(XKeyEvent *ev/*, qboolean modified*/) keysym = XLookupKeysym(ev, 0); - switch(keysym) { + switch(keysym) + { case XK_KP_Page_Up: key = KP_PGUP; break; case XK_Page_Up: key = K_PGUP; break; @@ -176,12 +176,12 @@ XLateKey(XKeyEvent *ev/*, qboolean modified*/) case XK_F35: key = K_PGDN; break; default: - if (keysym < 128) { + if (keysym < 128) + { /* ASCII keys */ key = keysym; - if (/*!modified && */((key >= 'A') && (key <= 'Z'))) { + if (/*!modified && */((key >= 'A') && (key <= 'Z'))) key = key + ('a' - 'A'); - } } break; } @@ -191,58 +191,58 @@ XLateKey(XKeyEvent *ev/*, qboolean modified*/) static Cursor CreateNullCursor(Display *display, Window root) { - Pixmap cursormask; - XGCValues xgc; - GC gc; - XColor dummycolour; - Cursor cursor; - - cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); - xgc.function = GXclear; - gc = XCreateGC(display, cursormask, GCFunction, &xgc); - XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); - dummycolour.pixel = 0; - dummycolour.red = 0; - dummycolour.flags = 04; - cursor = XCreatePixmapCursor(display, cursormask, cursormask, - &dummycolour,&dummycolour, 0,0); - XFreePixmap(display,cursormask); - XFreeGC(display,gc); - return cursor; + Pixmap cursormask; + XGCValues xgc; + GC gc; + XColor dummycolour; + Cursor cursor; + + cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); + xgc.function = GXclear; + gc = XCreateGC(display, cursormask, GCFunction, &xgc); + XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); + dummycolour.pixel = 0; + dummycolour.red = 0; + dummycolour.flags = 04; + cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0); + XFreePixmap(display,cursormask); + XFreeGC(display,gc); + return cursor; } static void install_grabs(void) { - XWindowAttributes attribs_1; - XSetWindowAttributes attribs_2; + XWindowAttributes attribs_1; + XSetWindowAttributes attribs_2; - XGetWindowAttributes(dpy, win, &attribs_1); - attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK; - XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2); + XGetWindowAttributes(dpy, win, &attribs_1); + attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK; + XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2); // inviso cursor XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); - XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, - win, None, CurrentTime); + XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); - if (in_dga.value) { + if (vid_dga.value) + { int MajorVersion, MinorVersion; - if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { + if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) + { // unable to query, probalby not supported Con_Printf( "Failed to detect XF86DGA Mouse\n" ); - in_dga.value = 0; - } else { - in_dga.value = 1; + vid_dga.value = 0; + } + else + { + vid_dga.value = 1; XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); } - } else { - XWarpPointer(dpy, None, win, - 0, 0, 0, 0, - vid.width / 2, vid.height / 2); } + else + XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); @@ -257,9 +257,8 @@ static void uninstall_grabs(void) if (!dpy || !win) return; - if (in_dga.value == 1) { + if (vid_dga.value == 1) XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); - } XUngrabPointer(dpy, CurrentTime); XUngrabKeyboard(dpy, CurrentTime); @@ -274,70 +273,108 @@ static void HandleEvents(void) { XEvent event; // KeySym ks; - int b; qboolean dowarp = false; if (!dpy) return; - while (XPending(dpy)) { + while (XPending(dpy)) + { XNextEvent(dpy, &event); - switch (event.type) { + switch (event.type) + { case KeyPress: case KeyRelease: Key_Event(XLateKey(&event.xkey), event.type == KeyPress); break; case MotionNotify: - if (in_dga.value == 1) { - mouse_x += event.xmotion.x_root * in_dga_mouseaccel.value; - mouse_y += event.xmotion.y_root * in_dga_mouseaccel.value; - } else { - if (!p_mouse_x && !p_mouse_y) { - Con_Printf("event->xmotion.x: %d\n", event.xmotion.x); - Con_Printf("event->xmotion.y: %d\n", event.xmotion.y); + if (usingmouse) + { + if (vid_dga.value == 1) + { + mouse_x += event.xmotion.x_root * vid_dga_mouseaccel.value; + mouse_y += event.xmotion.y_root * vid_dga_mouseaccel.value; } - if (vid_fullscreen.value || vid_mouse.value) { - if (!event.xmotion.send_event) { + else + { + /* + if (!p_mouse_x && !p_mouse_y) + { + Con_Printf("event->xmotion.x: %d\n", event.xmotion.x); + Con_Printf("event->xmotion.y: %d\n", event.xmotion.y); + } + */ + //if (usingmouse) + { + if (!event.xmotion.send_event) + { + mouse_x += (event.xmotion.x - p_mouse_x); + mouse_y += (event.xmotion.y - p_mouse_y); + if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) + dowarp = true; + } + } + /* + else + { mouse_x += (event.xmotion.x - p_mouse_x); mouse_y += (event.xmotion.y - p_mouse_y); - if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 - || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) { - dowarp = true; - } } - } else { - mouse_x += (event.xmotion.x - p_mouse_x); - mouse_y += (event.xmotion.y - p_mouse_y); + */ + p_mouse_x = event.xmotion.x; + p_mouse_y = event.xmotion.y; } - p_mouse_x = event.xmotion.x; - p_mouse_y = event.xmotion.y; } break; case ButtonPress: - b=-1; - if (event.xbutton.button == 1) - b = 0; - else if (event.xbutton.button == 2) - b = 2; - else if (event.xbutton.button == 3) - b = 1; - if (b>=0) - Key_Event(K_MOUSE1 + b, true); + switch(event.xbutton.button) + { + case 1: + Key_Event(K_MOUSE1, true); + break; + case 2: + Key_Event(K_MOUSE3, true); + break; + case 3: + Key_Event(K_MOUSE2, true); + break; + case 4: + Key_Event(K_MWHEELUP, true); + break; + case 5: + Key_Event(K_MWHEELDOWN, true); + break; + default: + Con_Printf("HandleEvents: ButtonPress gave value %d, 1-5 expected\n", event.xbutton.button); + break; + } break; case ButtonRelease: - b=-1; - if (event.xbutton.button == 1) - b = 0; - else if (event.xbutton.button == 2) - b = 2; - else if (event.xbutton.button == 3) - b = 1; - if (b>=0) - Key_Event(K_MOUSE1 + b, false); + switch(event.xbutton.button) + { + case 1: + Key_Event(K_MOUSE1, false); + break; + case 2: + Key_Event(K_MOUSE3, false); + break; + case 3: + Key_Event(K_MOUSE2, false); + break; + case 4: + Key_Event(K_MWHEELUP, false); + break; + case 5: + Key_Event(K_MWHEELDOWN, false); + break; + default: + Con_Printf("HandleEvents: ButtonRelease gave value %d, 1-5 expected\n", event.xbutton.button); + break; + } break; case CreateNotify : @@ -352,7 +389,8 @@ static void HandleEvents(void) } } - if (dowarp) { + if (dowarp) + { /* move the mouse to the window center again */ p_mouse_x = vid.width / 2; p_mouse_y = vid.height / 2; @@ -361,23 +399,25 @@ static void HandleEvents(void) } -static void IN_DeactivateMouse( void ) +static void IN_DeactivateMouse( void ) { if (!mouse_avail || !dpy || !win) return; - if (mouse_active) { + if (mouse_active) + { uninstall_grabs(); mouse_active = false; } } -static void IN_ActivateMouse( void ) +static void IN_ActivateMouse( void ) { if (!mouse_avail || !dpy || !win) return; - if (!mouse_active) { + if (!mouse_active) + { mouse_x = mouse_y = 0; // don't spazz install_grabs(); mouse_active = true; @@ -390,7 +430,8 @@ void VID_Shutdown(void) if (!ctx || !dpy) return; - if (dpy) { + if (dpy) + { uninstall_grabs(); if (vidmode_active) @@ -430,7 +471,7 @@ void InitSig(void) signal(SIGTERM, signal_handler); } -void VID_CheckMultitexture(void) +void VID_CheckMultitexture(void) { void *prjobj; qglMTexCoord2f = NULL; @@ -512,10 +553,34 @@ void GL_BeginRendering (int *x, int *y, int *width, int *height) void GL_EndRendering (void) { + int usemouse; if (!r_render.value) return; glFlush(); glXSwapBuffers(dpy, win); + +// handle the mouse state when windowed if that's changed + usemouse = false; + if (vid_mouse.value && key_dest == key_game) + usemouse = true; + if (vidmode_active) + usemouse = true; + if (usemouse) + { + if (!usingmouse) + { + usingmouse = true; + IN_ActivateMouse (); + } + } + else + { + if (usingmouse) + { + usingmouse = false; + IN_DeactivateMouse (); + } + } } int VID_SetGamma(float prescale, float gamma, float scale, float base) @@ -526,7 +591,8 @@ int VID_SetGamma(float prescale, float gamma, float scale, float base) void VID_Init(void) { int i; - int attrib[] = { + int attrib[] = + { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, @@ -545,11 +611,11 @@ void VID_Init(void) int MajorVersion, MinorVersion; int actualWidth, actualHeight; - Cvar_RegisterVariable (&in_mouse); - Cvar_RegisterVariable (&in_dga); - Cvar_RegisterVariable (&in_dga_mouseaccel); + Cvar_RegisterVariable (&vid_mouse); + Cvar_RegisterVariable (&vid_dga); + Cvar_RegisterVariable (&vid_dga_mouseaccel); Cvar_RegisterVariable (&m_filter); - + // interpret command-line params // set vid parameters @@ -580,7 +646,8 @@ void VID_Init(void) if (vid.conheight < 200) vid.conheight = 200; - if (!(dpy = XOpenDisplay(NULL))) { + if (!(dpy = XOpenDisplay(NULL))) + { fprintf(stderr, "Error couldn't open the X display\n"); exit(1); } @@ -590,44 +657,50 @@ void VID_Init(void) // Get video mode list MajorVersion = MinorVersion = 0; - if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { + if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) vidmode_ext = false; - } else { + else + { Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion); vidmode_ext = true; } visinfo = glXChooseVisual(dpy, scrnum, attrib); - if (!visinfo) { + if (!visinfo) + { fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n"); exit(1); } - if (vidmode_ext) { + if (vidmode_ext) + { int best_fit, best_dist, dist, x, y; - + XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); // Are we going fullscreen? If so, let's change video mode - if (fullscreen) { + if (fullscreen) + { best_dist = 9999999; best_fit = -1; - for (i = 0; i < num_vidmodes; i++) { - if (width > vidmodes[i]->hdisplay || - height > vidmodes[i]->vdisplay) + for (i = 0; i < num_vidmodes; i++) + { + if (width > vidmodes[i]->hdisplay || height > vidmodes[i]->vdisplay) continue; x = width - vidmodes[i]->hdisplay; y = height - vidmodes[i]->vdisplay; dist = (x * x) + (y * y); - if (dist < best_dist) { + if (dist < best_dist) + { best_dist = dist; best_fit = i; } } - if (best_fit != -1) { + if (best_fit != -1) + { actualWidth = vidmodes[best_fit]->hdisplay; actualHeight = vidmodes[best_fit]->vdisplay; @@ -637,7 +710,8 @@ void VID_Init(void) // Move the viewport to top left XF86VidModeSetViewPort(dpy, scrnum, 0, 0); - } else + } + else fullscreen = 0; } } @@ -647,21 +721,22 @@ void VID_Init(void) attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = X_MASK; - if (vidmode_active) { - mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | - CWEventMask | CWOverrideRedirect; + if (vidmode_active) + { + mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | CWEventMask | CWOverrideRedirect; attr.override_redirect = True; attr.backing_store = NotUseful; attr.save_under = False; - } else + } + else mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - win = XCreateWindow(dpy, root, 0, 0, width, height, - 0, visinfo->depth, InputOutput, - visinfo->visual, mask, &attr); + win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); + XStoreName(dpy, win, "DarkPlaces-GLX"); XMapWindow(dpy, win); - if (vidmode_active) { + if (vidmode_active) + { XMoveWindow(dpy, win, 0, 0); XRaiseWindow(dpy, win); XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); @@ -686,17 +761,14 @@ void VID_Init(void) vid.width = vid.conwidth; vid.height = vid.conheight; - vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0); - InitSig(); // trap evil signals GL_Init(); Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); - vid.recalc_refdef = 1; // force a surface cache flush - - install_grabs(); + // force a surface cache flush + vid.recalc_refdef = 1; } void Sys_SendKeyEvents(void) @@ -724,13 +796,6 @@ IN_Commands */ void IN_Commands (void) { - if (!dpy || !win) - return; - - if (vidmode_active || key_dest == key_game) - IN_ActivateMouse(); - else - IN_DeactivateMouse (); } /* @@ -743,38 +808,39 @@ void IN_MouseMove (usercmd_t *cmd) if (!mouse_avail) return; - if (!mouse_avail) - return; - - if (m_filter.value) { - mouse_x = (mouse_x + old_mouse_x) * 0.5; - mouse_y = (mouse_y + old_mouse_y) * 0.5; - - old_mouse_x = mouse_x; - old_mouse_y = mouse_y; - } - - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; - - if (in_strafe.state & 1) - cmd->sidemove += m_side.value * mouse_x; - else - cl.viewangles[YAW] -= m_yaw.value * mouse_x; - -/* if (freelook)*/ - V_StopPitchDrift (); - - if (/*freelook && */!(in_strafe.state & 1)) { - cl.viewangles[PITCH] += m_pitch.value * mouse_y; - cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80); - } else { - if ((in_strafe.state & 1) && noclip_anglehack) - cmd->upmove -= m_forward.value * mouse_y; - else - cmd->forwardmove -= m_forward.value * mouse_y; - } - mouse_x = mouse_y = 0.0; + if (m_filter.value) + { + mouse_x = (mouse_x + old_mouse_x) * 0.5; + mouse_y = (mouse_y + old_mouse_y) * 0.5; + + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + } + + mouse_x *= sensitivity.value; + mouse_y *= sensitivity.value; + + if (in_strafe.state & 1) + cmd->sidemove += m_side.value * mouse_x; + else + cl.viewangles[YAW] -= m_yaw.value * mouse_x; + + //if (freelook) + V_StopPitchDrift (); + + if (/*freelook && */!(in_strafe.state & 1)) + { + cl.viewangles[PITCH] += m_pitch.value * mouse_y; + cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80); + } + else + { + if ((in_strafe.state & 1) && noclip_anglehack) + cmd->upmove -= m_forward.value * mouse_y; + else + cmd->forwardmove -= m_forward.value * mouse_y; + } + mouse_x = mouse_y = 0.0; } void IN_Move (usercmd_t *cmd) diff --git a/view.c b/view.c index 5b0da1ee..c14f9603 100644 --- a/view.c +++ b/view.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -742,99 +742,105 @@ void V_CalcRefdef (void) ent = &cl_entities[cl.viewentity]; // view is the weapon model (only visible from inside body) view = &cl.viewent; - -// transform the view offset by the model's matrix to get the offset from model origin for the view - if (!chase_active.value) // LordHavoc: get rid of angle problems in chase_active mode + + if (chase_active.value) { - ent->render.angles[YAW] = cl.viewangles[YAW]; // the model should face the view dir - ent->render.angles[PITCH] = -cl.viewangles[PITCH]; // the model should face the view dir + VectorCopy (ent->render.origin, r_refdef.vieworg); + VectorCopy (cl.viewangles, r_refdef.viewangles); + Chase_Update (); + V_AddIdle (); } - - - bob = V_CalcBob (); - -// refresh position - VectorCopy (ent->render.origin, r_refdef.vieworg); - r_refdef.vieworg[2] += cl.viewheight + bob; + else + { + // transform the view offset by the model's matrix to get the offset from model origin for the view + // if (!chase_active.value) // LordHavoc: get rid of angle problems in chase_active mode + // { + // ent->render.angles[YAW] = cl.viewangles[YAW]; // the model should face the view dir + // ent->render.angles[PITCH] = -cl.viewangles[PITCH]; // the model should face the view dir + // } - // LordHavoc: the protocol has changed... so this is an obsolete approach -// never let it sit exactly on a node line, because a water plane can -// dissapear when viewed with the eye exactly on it. -// the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis -// r_refdef.vieworg[0] += 1.0/32; -// r_refdef.vieworg[1] += 1.0/32; -// r_refdef.vieworg[2] += 1.0/32; + bob = V_CalcBob (); - if (!intimerefresh) - VectorCopy (cl.viewangles, r_refdef.viewangles); - V_CalcViewRoll (); - V_AddIdle (); + // refresh position + VectorCopy (ent->render.origin, r_refdef.vieworg); + r_refdef.vieworg[2] += cl.viewheight + bob; -// offsets - angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward - angles[YAW] = ent->render.angles[YAW]; - angles[ROLL] = ent->render.angles[ROLL]; + // LordHavoc: the protocol has changed... so this is an obsolete approach + // never let it sit exactly on a node line, because a water plane can + // dissapear when viewed with the eye exactly on it. + // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis + // r_refdef.vieworg[0] += 1.0/32; + // r_refdef.vieworg[1] += 1.0/32; + // r_refdef.vieworg[2] += 1.0/32; - AngleVectors (angles, forward, NULL, NULL); + if (!intimerefresh) + VectorCopy (cl.viewangles, r_refdef.viewangles); + V_CalcViewRoll (); + V_AddIdle (); - V_BoundOffsets (); - -// set up gun position - VectorCopy (cl.viewangles, view->render.angles); - - CalcGunAngle (); + // offsets + angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward + angles[YAW] = ent->render.angles[YAW]; + angles[ROLL] = ent->render.angles[ROLL]; - VectorCopy (ent->render.origin, view->render.origin); - view->render.origin[2] += cl.viewheight; + AngleVectors (angles, forward, NULL, NULL); - for (i=0 ; i<3 ; i++) - { - view->render.origin[i] += forward[i]*bob*0.4; -// view->render.origin[i] += right[i]*bob*0.4; -// view->render.origin[i] += up[i]*bob*0.8; - } - view->render.origin[2] += bob; + V_BoundOffsets (); - view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]]; - view->render.frame = cl.stats[STAT_WEAPONFRAME]; - view->render.colormap = -1; // no special coloring + // set up gun position + VectorCopy (cl.viewangles, view->render.angles); -// set up the refresh position + CalcGunAngle (); - // LordHavoc: this never looked all that good to begin with... - /* -// smooth out stair step ups -if (cl.onground && ent->render.origin[2] - oldz > 0) -{ - float steptime; - - steptime = cl.time - cl.oldtime; - if (steptime < 0) -//FIXME I_Error ("steptime < 0"); - steptime = 0; + VectorCopy (ent->render.origin, view->render.origin); + view->render.origin[2] += cl.viewheight; - oldz += steptime * 80; - if (oldz > ent->render.origin[2]) - oldz = ent->render.origin[2]; - if (ent->render.origin[2] - oldz > 12) - oldz = ent->render.origin[2] - 12; - r_refdef.vieworg[2] += oldz - ent->render.origin[2]; - view->render.origin[2] += oldz - ent->render.origin[2]; -} -else - oldz = ent->render.origin[2]; - */ + for (i=0 ; i<3 ; i++) + { + view->render.origin[i] += forward[i]*bob*0.4; + // view->render.origin[i] += right[i]*bob*0.4; + // view->render.origin[i] += up[i]*bob*0.8; + } + view->render.origin[2] += bob; + + view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]]; + view->render.frame = cl.stats[STAT_WEAPONFRAME]; + view->render.colormap = -1; // no special coloring -// LordHavoc: origin view kick added - if (!intimerefresh && v_punch.value) + // set up the refresh position + + // LordHavoc: this never looked all that good to begin with... + /* + // smooth out stair step ups + if (cl.onground && ent->render.origin[2] - oldz > 0) { - VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); - VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + float steptime; + + steptime = cl.time - cl.oldtime; + if (steptime < 0) + //FIXME I_Error ("steptime < 0"); + steptime = 0; + + oldz += steptime * 80; + if (oldz > ent->render.origin[2]) + oldz = ent->render.origin[2]; + if (ent->render.origin[2] - oldz > 12) + oldz = ent->render.origin[2] - 12; + r_refdef.vieworg[2] += oldz - ent->render.origin[2]; + view->render.origin[2] += oldz - ent->render.origin[2]; } + else + oldz = ent->render.origin[2]; + */ - if (chase_active.value) - Chase_Update (); + // LordHavoc: origin view kick added + if (!intimerefresh && v_punch.value) + { + VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); + VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + } + } } /* diff --git a/wad.c b/wad.c index 1a5ab0a1..241c065e 100644 --- a/wad.c +++ b/wad.c @@ -183,7 +183,7 @@ void W_LoadTextureWadFile (char *filename, int complain) QFile *file; int numlumps; - COM_FOpenFile (filename, &file, false, true); + COM_FOpenFile (filename, &file, false, false); if (!file) { if (complain) diff --git a/world.c b/world.c index 0409d61a..dba8fe9f 100644 --- a/world.c +++ b/world.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -29,6 +29,55 @@ line of sight checks trace->crosscontent, but bullets don't */ +/* +typedef struct link_s +{ + struct link_s *prev, *next; +} link_t; +*/ + + +void ClearLink (link_t *l); +void RemoveLink (link_t *l); +void InsertLinkBefore (link_t *l, link_t *before); +void InsertLinkAfter (link_t *l, link_t *after); + +// (type *)STRUCT_FROM_LINK(link_t *link, type, member) +// ent = STRUCT_FROM_LINK(link,entity_t,order) +// FIXME: remove this mess! +//#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) + +#define EDICT_FROM_AREA(l) ((edict_t *)((byte *)l - (int)&(((edict_t *)0)->area))) + +//============================================================================ + +// ClearLink is used for new headnodes +void ClearLink (link_t *l) +{ + l->prev = l->next = l; +} + +void RemoveLink (link_t *l) +{ + l->next->prev = l->prev; + l->prev->next = l->next; +} + +void InsertLinkBefore (link_t *l, link_t *before) +{ + l->next = before; + l->prev = before->prev; + l->prev->next = l; + l->next->prev = l; +} +void InsertLinkAfter (link_t *l, link_t *after) +{ + l->next = after->next; + l->prev = after; + l->prev->next = l; + l->next->prev = l; +} + typedef struct { @@ -183,7 +232,7 @@ hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) VectorSubtract (ent->v.mins, maxs, hullmins); VectorSubtract (ent->v.maxs, mins, hullmaxs); hull = SV_HullForBox (hullmins, hullmaxs); - + VectorCopy (ent->v.origin, offset); } @@ -231,28 +280,28 @@ areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) ClearLink (&anode->trigger_edicts); ClearLink (&anode->solid_edicts); - + if (depth == AREA_DEPTH) { anode->axis = -1; anode->children[0] = anode->children[1] = NULL; return anode; } - + VectorSubtract (maxs, mins, size); if (size[0] > size[1]) anode->axis = 0; else anode->axis = 1; - + anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]); - VectorCopy (mins, mins1); - VectorCopy (mins, mins2); - VectorCopy (maxs, maxs1); - VectorCopy (maxs, maxs2); - + VectorCopy (mins, mins1); + VectorCopy (mins, mins2); + VectorCopy (maxs, maxs1); + VectorCopy (maxs, maxs2); + maxs1[anode->axis] = mins2[anode->axis] = anode->dist; - + anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2); anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1); @@ -268,7 +317,7 @@ SV_ClearWorld void SV_ClearWorld (void) { SV_InitBoxHull (); - + memset (sv_areanodes, 0, sizeof(sv_areanodes)); sv_numareanodes = 0; SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); @@ -312,11 +361,11 @@ loc0: if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) continue; if (ent->v.absmin[0] > touch->v.absmax[0] - || ent->v.absmin[1] > touch->v.absmax[1] - || ent->v.absmin[2] > touch->v.absmax[2] - || ent->v.absmax[0] < touch->v.absmin[0] - || ent->v.absmax[1] < touch->v.absmin[1] - || ent->v.absmax[2] < touch->v.absmin[2] ) + || ent->v.absmin[1] > touch->v.absmax[1] + || ent->v.absmin[2] > touch->v.absmax[2] + || ent->v.absmax[0] < touch->v.absmin[0] + || ent->v.absmax[1] < touch->v.absmin[1] + || ent->v.absmax[2] < touch->v.absmin[2]) continue; old_self = pr_global_struct->self; old_other = pr_global_struct->other; @@ -329,11 +378,11 @@ loc0: pr_global_struct->self = old_self; pr_global_struct->other = old_other; } - + // recurse down both sides if (node->axis == -1) return; - + // LordHavoc: optimized recursion // if (ent->v.absmax[node->axis] > node->dist) SV_TouchLinks (ent, node->children[0]); // if (ent->v.absmin[node->axis] < node->dist) SV_TouchLinks (ent, node->children[1]); @@ -363,15 +412,10 @@ SV_FindTouchedLeafs */ void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) { - mplane_t *splitplane; - mleaf_t *leaf; - int sides; - int leafnum; - loc0: if (node->contents == CONTENTS_SOLID) return; - + // add an efrag if the node is a leaf if ( node->contents < 0) @@ -382,24 +426,18 @@ loc0: return; } - leaf = (mleaf_t *)node; - leafnum = leaf - sv.worldmodel->leafs - 1; - - ent->leafnums[ent->num_leafs] = leafnum; - ent->num_leafs++; + ent->leafnums[ent->num_leafs++] = (mleaf_t *)node - sv.worldmodel->leafs - 1; return; } - -// NODE_MIXED - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane); - // recurse down the contacted sides - // LordHavoc: optimized recursion + +// sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane); // if (sides & 1) SV_FindTouchedLeafs (ent, node->children[0]); // if (sides & 2) SV_FindTouchedLeafs (ent, node->children[1]); - switch (sides) + + // LordHavoc: optimized recursion + switch (BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, node->plane)) { case 1: node = node->children[0]; @@ -438,7 +476,8 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) // LordHavoc: enabling rotating bmodels if (ent->v.solid == SOLID_BSP && (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2])) - { // expand for rotation + { + // expand for rotation float max, v; int i; @@ -467,7 +506,7 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) } else { - VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); + VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin); VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax); } @@ -483,7 +522,8 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) ent->v.absmax[1] += 15; } else - { // because movement is clipped an epsilon away from an actual edge, + { + // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch ent->v.absmin[0] -= 1; ent->v.absmin[1] -= 1; @@ -515,13 +555,13 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) break; // crosses the node } -// link it in +// link it in if (ent->v.solid == SOLID_TRIGGER) InsertLinkBefore (&ent->area, &node->trigger_edicts); else InsertLinkBefore (&ent->area, &node->solid_edicts); - + // if touch_triggers, touch all entities at this node and descend for more if (touch_triggers) SV_TouchLinks ( ent, sv_areanodes ); @@ -547,7 +587,7 @@ int SV_HullPointContents (hull_t *hull, int num, vec3_t p) { while (num >= 0) num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist]; - + return num; } @@ -563,7 +603,7 @@ edict_t *SV_TestEntityPosition (edict_t *ent) trace_t trace; trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent); - + if (trace.startsolid) return sv.edicts; @@ -1031,14 +1071,14 @@ loc0: continue; if (clip->boxmins[0] > touch->v.absmax[0] - || clip->boxmins[1] > touch->v.absmax[1] - || clip->boxmins[2] > touch->v.absmax[2] - || clip->boxmaxs[0] < touch->v.absmin[0] - || clip->boxmaxs[1] < touch->v.absmin[1] - || clip->boxmaxs[2] < touch->v.absmin[2] ) + || clip->boxmins[1] > touch->v.absmax[1] + || clip->boxmins[2] > touch->v.absmax[2] + || clip->boxmaxs[0] < touch->v.absmin[0] + || clip->boxmaxs[1] < touch->v.absmin[1] + || clip->boxmaxs[2] < touch->v.absmin[2]) continue; - if (clip->passedict!=0 && clip->passedict->v.size[0] && !touch->v.size[0]) + if (clip->passedict != NULL && clip->passedict->v.size[0] && !touch->v.size[0]) continue; // points never interact // might intersect, so do an exact clip @@ -1075,7 +1115,7 @@ loc0: else if (trace.startsolid) clip->trace.startsolid = true; } - + // recurse down both sides if (node->axis == -1) return; -- 2.39.2