From d7035ef4229a2462ad59a67160494593fbd8f2e0 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Fri, 11 May 2001 08:27:05 +0000 Subject: [PATCH] ***map loader generates portals for the map*** (can you tell this is a big deal? :) increased build number to 100 (it's the truth) made loadingplaque work correctly disabled (commented out) loadingplaque removed efrags each model is checked against visible leafs (made efrags obsolete) put .active field into client entity states (more correct than checking modelindex) disabled all cachedir stuff (#if CACHEENABLE) removed scr_copytop and other no-longer-relevant variables removed Con_NotifyBox (wasn't used) cleaned up visframe stuff removed a lot of unnecessary fields from mnode_t and a few from mleaf_t clarified r_visframecount stuff (now referred to as r_vismarkframecount, and similarly visframe field in mnode_t/mleaf_t is now called vismarkframe) got rid of offsets[] array in texture_t rewrote r_notexture_mip related code (fixing black default texture) got rid of skyisvisible variable (check currentskypoly instead) got rid of gl_texsort simplified surface rendering process greatly (R_DrawSurfaces) surface rendering should now be totally sequential (good for caches) renamed r_newworldnode to r_leafworldnode (will be removed in next commit) disabled r_oldclip code (will be removed in next commit) renamed R_WorldNode to R_BSPWorldNode (will be removed in next commit) renamed R_NewWorldNode to R_LeafWorldNode (will be removed in next commit) made copy of R_WorldNode that ignores vis data, called R_NoVisWorldNode added R_PortalWorldNode, 3-80% speed gain depending on situation, improved culling of non-relevant leafs/surfaces added r_portalworldnode cvar to test new code (this will become the standard worldnode in next commit) minor optimization to wateralpha code minor redesign of R_TextureAnimation and animated texture stuff in texture_t cleaned up timing issues in water (now synced to cl.time, not realtime) and menu code (now synced to realtime, not host_time) removed host_time removed SCR_ModalMessage (this got rid of the 'are you sure?' question on newgame) changed quit messages got rid of SCR_BringDownConsole reorganized 2D screen drawing code (now draws console when loading plaque is displayed, etc) some cleanup on texture loading redesigned R_Decal to make use of BSP tree in finding nearest surfaces renamed and redesigned R_DrawDecals to GL_DrawDecals and no longer uses transpoly particles are now only rendered if inside a visible leaf sprites are now only rendered if touching a visible leaf ambient sounds no longer play after disconnecting fixed severe delta compressed entity bugs in client sped up MOVETYPE_NONE a bit git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@197 d7cf8633-e32d-0410-b094-e92efae38249 --- buildnumber.c | 2 +- cl_demo.c | 2 + cl_main.c | 51 ++- cl_parse.c | 15 +- client.h | 6 +- common.c | 31 +- console.c | 45 +-- console.h | 3 - gl_models.c | 2 +- gl_refrag.c | 247 ------------- gl_rmain.c | 61 +++- gl_rmisc.c | 44 +-- gl_rsurf.c | 723 ++++++++++++++++++++++---------------- gl_screen.c | 182 +++------- glquake.h | 3 - host.c | 9 +- host_cmd.c | 12 +- keys.c | 6 +- makefile | 2 +- menu.c | 69 ++-- model_brush.c | 936 +++++++++++++++++++++++++++++++++++++++++-------- model_brush.h | 74 ++-- model_shared.h | 6 + quakedef.h | 2 + r_decals.c | 293 +++++++++++----- r_decals.h | 2 +- r_light.c | 69 ++-- r_light.h | 2 - r_part.c | 6 + r_sprites.c | 9 +- render.h | 29 +- sbar.c | 13 - screen.h | 14 +- server.h | 2 - snd_dma.c | 17 +- sv_main.c | 51 ++- sv_phys.c | 8 +- sys.h | 2 + sys_linux.c | 15 +- sys_win.c | 5 +- sys_wind.c | 2 + view.c | 7 +- 42 files changed, 1833 insertions(+), 1246 deletions(-) delete mode 100644 gl_refrag.c diff --git a/buildnumber.c b/buildnumber.c index d3e52823..6bd87550 100644 --- a/buildnumber.c +++ b/buildnumber.c @@ -1,4 +1,4 @@ -#define BUILDNUMBER 79 +#define BUILDNUMBER 100 int buildnumber = BUILDNUMBER; diff --git a/cl_demo.c b/cl_demo.c index 85873db3..56b6dd76 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -286,6 +286,8 @@ void CL_PlayDemo_f (void) return; } +// SCR_BeginLoadingPlaque(); + // // disconnect from server // diff --git a/cl_main.c b/cl_main.c index e0db84a6..5f3d6cb0 100644 --- a/cl_main.c +++ b/cl_main.c @@ -45,7 +45,7 @@ cvar_t m_side = {"m_side","0.8", true}; client_static_t cls; client_state_t cl; // FIXME: put these on hunk? -efrag_t cl_efrags[MAX_EFRAGS]; +//efrag_t cl_efrags[MAX_EFRAGS]; entity_t cl_entities[MAX_EDICTS]; entity_t cl_static_entities[MAX_STATIC_ENTITIES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; @@ -73,7 +73,7 @@ void CL_ClearState (void) SZ_Clear (&cls.message); // clear other arrays - memset (cl_efrags, 0, sizeof(cl_efrags)); +// memset (cl_efrags, 0, sizeof(cl_efrags)); memset (cl_entities, 0, sizeof(cl_entities)); memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); @@ -89,13 +89,13 @@ void CL_ClearState (void) cl_entities[i].state_baseline.colormod = 255; } -// -// allocate the efrags and chain together into a free list -// - cl.free_efrags = cl_efrags; - for (i=0 ; i MAX_VISEDICTS) + Host_Error("CL_RelinkStaticEntities: cl.num_statics > MAX_VISEDICTS??\n"); + + ent = cl_static_entities; + endent = ent + cl.num_statics; + for (;ent < endent;ent++) + cl_visedicts[cl_numvisedicts++] = ent; +} /* =============== @@ -449,6 +464,8 @@ void CL_RelinkEntities (void) cl_numvisedicts = 0; + CL_RelinkStaticEntities(); + // // interpolate player info // @@ -476,12 +493,12 @@ void CL_RelinkEntities (void) for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++) { // if the object wasn't included in the latest packet, remove it - if (!ent->state_current.modelindex) + if (!ent->state_current.active) continue; VectorCopy (ent->render.origin, oldorg); - if (!ent->state_previous.modelindex) + if (!ent->state_previous.active) { // only one state available VectorCopy (ent->state_current.origin, ent->render.origin); @@ -598,7 +615,7 @@ void CL_RelinkEntities (void) // ent->render.origin[2] += bobjoffset; } // only do trails if present in the previous frame as well - if (ent->state_previous.modelindex) + if (ent->state_previous.active) { if (ent->render.model->flags & EF_GIB) R_RocketTrail (oldorg, ent->render.origin, 2, ent); diff --git a/cl_parse.c b/cl_parse.c index 942e2b34..c4a95074 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -459,6 +459,9 @@ void CL_ValidateState(entity_state_t *s) { model_t *model; + if (!s->active) + return; + if (s->modelindex >= MAX_MODELS) Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS); @@ -523,7 +526,7 @@ void CL_ParseUpdate (int bits) deltadie = false; if (bits & U_DELTA) { - if (!ent->state_current.modelindex) + if (!ent->state_current.active) deltadie = true; // was not present in previous frame, leave hidden until next full update } else @@ -532,6 +535,7 @@ void CL_ParseUpdate (int bits) ent->state_current.time = cl.mtime[0]; ent->state_current.flags = 0; + ent->state_current.active = true; if (bits & U_MODEL) ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte(); if (bits & U_FRAME) ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte(); if (bits & U_COLORMAP) ent->state_current.colormap = MSG_ReadByte(); @@ -577,14 +581,14 @@ void CL_ParseUpdate (int bits) if (deltadie) { // hide the entity - ent->state_current.modelindex = 0; + ent->state_current.active = false; } else { CL_ValidateState(&ent->state_current); /* - if (!ent->state_current.modelindex) + if (!ent->state_current.active) { if (bits & U_DELTA) { @@ -621,7 +625,7 @@ void CL_EntityUpdateEnd(int end) Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS); for (i = entityupdatestart;i < end;i++) if (entkill[i]) - cl_entities[i].state_current.modelindex = 0; + cl_entities[i].state_current.active = 0; } /* @@ -634,6 +638,7 @@ void CL_ParseBaseline (entity_t *ent, int largemodelindex) int i; memset(&ent->state_baseline, 0, sizeof(entity_state_t)); + ent->state_baseline.active = true; if (largemodelindex) ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort (); else @@ -770,7 +775,7 @@ void CL_ParseStatic (int largemodelindex) VectorCopy (ent->state_baseline.origin, ent->render.origin); VectorCopy (ent->state_baseline.angles, ent->render.angles); - R_AddEfrags (ent); +// R_AddEfrags (ent); } /* diff --git a/client.h b/client.h index 42845cda..cc6551d3 100644 --- a/client.h +++ b/client.h @@ -77,7 +77,7 @@ typedef struct beam_t; // LordHavoc: increased MAX_EFRAGS from 640 to 2048 -#define MAX_EFRAGS 2048 +//#define MAX_EFRAGS 2048 #define MAX_MAPSTRING 2048 #define MAX_DEMOS 8 @@ -207,7 +207,7 @@ typedef struct // refresh related state struct model_s *worldmodel; // cl_entitites[0].model - struct efrag_s *free_efrags; +// struct efrag_s *free_efrags; // int num_entities; // held in cl_entities array int num_statics; // held in cl_staticentities array entity_t viewent; // the gun model @@ -262,7 +262,7 @@ extern cvar_t m_side; extern client_state_t cl; // FIXME, allocate dynamically -extern efrag_t cl_efrags[MAX_EFRAGS]; +//extern efrag_t cl_efrags[MAX_EFRAGS]; extern entity_t cl_entities[MAX_EDICTS]; extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; diff --git a/common.c b/common.c index cc4bfd8b..71731726 100644 --- a/common.c +++ b/common.c @@ -1349,8 +1349,10 @@ typedef struct // LordHavoc: was 2048, increased to 16384 and changed info[MAX_PACK_FILES] to a temporary malloc to avoid stack overflows #define MAX_FILES_IN_PACK 16384 -char com_cachedir[MAX_OSPATH]; -char com_gamedir[MAX_OSPATH]; +#if CACHEENABLE +char com_cachedir[MAX_OSPATH]; +#endif +char com_gamedir[MAX_OSPATH]; typedef struct searchpath_s { @@ -1480,12 +1482,15 @@ Sets com_filesize and one of handle or file */ int COM_FindFile (char *filename, int *handle, FILE **file, qboolean quiet) { - searchpath_t *search; - char netpath[MAX_OSPATH]; - char cachepath[MAX_OSPATH]; - pack_t *pak; - int i; - int findtime, cachetime; + searchpath_t *search; + char netpath[MAX_OSPATH]; +#if CACHEENABLE + char cachepath[MAX_OSPATH]; + int cachetime; +#endif + pack_t *pak; + int i; + int findtime; if (file && handle) Sys_Error ("COM_FindFile: both handle and file set"); @@ -1544,10 +1549,9 @@ int COM_FindFile (char *filename, int *handle, FILE **file, qboolean quiet) if (findtime == -1) continue; - // see if the file needs to be updated in the cache - if (!com_cachedir[0]) - strcpy (cachepath, netpath); - else +#if CACHEENABLE + // see if the file needs to be updated in the cache + if (com_cachedir[0]) { #if defined(_WIN32) if ((strlen(netpath) < 2) || (netpath[1] != ':')) @@ -1564,6 +1568,7 @@ int COM_FindFile (char *filename, int *handle, FILE **file, qboolean quiet) COM_CopyFile (netpath, cachepath); strcpy (netpath, cachepath); } +#endif if (!quiet) Sys_Printf ("FindFile: %s\n",netpath); @@ -1870,6 +1875,7 @@ void COM_InitFilesystem (void) basedir[j-1] = 0; } +#if CACHEENABLE // // -cachedir // Overrides the system supplied cache directory (NULL or /qcache) @@ -1887,6 +1893,7 @@ void COM_InitFilesystem (void) strcpy (com_cachedir, host_parms.cachedir); else com_cachedir[0] = 0; +#endif // // start up with GAMENAME by default (id1) diff --git a/console.c b/console.c index 297bcb23..fe491066 100644 --- a/console.c +++ b/console.c @@ -93,7 +93,7 @@ void Con_ToggleConsole_f (void) else key_dest = key_console; - SCR_EndLoadingPlaque (); +// SCR_EndLoadingPlaque (); memset (con_times, 0, sizeof(con_times)); } @@ -387,7 +387,7 @@ void Con_Printf (char *fmt, ...) { va_list argptr; char msg[MAXPRINTMSG]; - static qboolean inupdate; +// static qboolean inupdate; va_start (argptr,fmt); vsprintf (msg,fmt,argptr); @@ -410,6 +410,8 @@ void Con_Printf (char *fmt, ...) Con_Print (msg); // update the screen if the console is displayed + // LordHavoc: I don't think there's a real need for this + /* // LordHavoc: don't print text while loading scripts if (cls.state != ca_disconnected) if (cls.signon != SIGNONS && !scr_disabled_for_loading ) @@ -423,6 +425,7 @@ void Con_Printf (char *fmt, ...) inupdate = false; } } + */ } /* @@ -553,7 +556,6 @@ void Con_DrawNotify (void) text = con_text + (i % con_totallines)*con_linewidth; clearnotify = 0; - scr_copytop = 1; // for (x = 0 ; x < con_linewidth ; x++) // Draw_Character ( (x+1)<<3, v, text[x]); @@ -567,7 +569,6 @@ void Con_DrawNotify (void) if (key_dest == key_message) { clearnotify = 0; - scr_copytop = 1; x = 0; @@ -645,39 +646,3 @@ void Con_DrawConsole (int lines, qboolean drawinput) if (drawinput) Con_DrawInput (); } - - -/* -================== -Con_NotifyBox -================== -*/ -void Con_NotifyBox (char *text) -{ - double t1, t2; - -// during startup for sound / cd warnings - Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"); - - Con_Printf (text); - - Con_Printf ("Press a key.\n"); - Con_Printf("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"); - - key_count = -2; // wait for a key down and up - key_dest = key_console; - - do - { - t1 = Sys_FloatTime (); - SCR_UpdateScreen (); - Sys_SendKeyEvents (); - t2 = Sys_FloatTime (); - realtime += t2-t1; // make the cursor blink - } while (key_count < 0); - - Con_Printf ("\n"); - key_dest = key_game; - realtime = 0; // put the cursor back to invisible -} - diff --git a/console.h b/console.h index ef01f008..58273125 100644 --- a/console.h +++ b/console.h @@ -41,6 +41,3 @@ void Con_Clear_f (void); void Con_DrawNotify (void); void Con_ClearNotify (void); void Con_ToggleConsole_f (void); - -void Con_NotifyBox (char *text); // during startup for sound / cd warnings - diff --git a/gl_models.c b/gl_models.c index 6065452e..10cfd759 100644 --- a/gl_models.c +++ b/gl_models.c @@ -952,7 +952,7 @@ 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_CullBox (mins, maxs)) + if (cull && R_VisibleCullBox (mins, maxs)) return; c_models++; diff --git a/gl_refrag.c b/gl_refrag.c deleted file mode 100644 index ce5ba79a..00000000 --- a/gl_refrag.c +++ /dev/null @@ -1,247 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_efrag.c - -#include "quakedef.h" - -mnode_t *r_pefragtopnode; - - -//=========================================================================== - -/* -=============================================================================== - - ENTITY FRAGMENT FUNCTIONS - -=============================================================================== -*/ - -efrag_t **lastlink; - -vec3_t r_emins, r_emaxs; - -entity_t *r_addent; - - -/* -================ -R_RemoveEfrags - -Call when removing an object from the world or moving it to another position -================ -*/ -void R_RemoveEfrags (entity_t *ent) -{ - efrag_t *ef, *old, *walk, **prev; - - ef = ent->render.efrag; - - while (ef) - { - prev = &ef->leaf->efrags; - while (1) - { - walk = *prev; - if (!walk) - break; - if (walk == ef) - { // remove this fragment - *prev = ef->leafnext; - break; - } - else - prev = &walk->leafnext; - } - - old = ef; - ef = ef->entnext; - - // put it on the free list - old->entnext = cl.free_efrags; - cl.free_efrags = old; - } - - ent->render.efrag = NULL; -} - -/* -=================== -R_SplitEntityOnNode -=================== -*/ -void R_SplitEntityOnNode (mnode_t *node) -{ - efrag_t *ef; - mplane_t *splitplane; - mleaf_t *leaf; - int sides; - -loc0: - if (node->contents == CONTENTS_SOLID) - { - return; - } - -// add an efrag if the node is a leaf - - if ( node->contents < 0) - { - if (!r_pefragtopnode) - r_pefragtopnode = node; - - leaf = (mleaf_t *)node; - -// grab an efrag off the free list - ef = cl.free_efrags; - if (!ef) - { - Con_Printf ("Too many efrags!\n"); - return; // no free fragments... - } - cl.free_efrags = cl.free_efrags->entnext; - - ef->entity = r_addent; - -// add the entity link - *lastlink = ef; - lastlink = &ef->entnext; - ef->entnext = NULL; - -// set the leaf links - ef->leaf = leaf; - ef->leafnext = leaf->efrags; - leaf->efrags = ef; - - return; - } - -// NODE_MIXED - - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); - - if (sides == 3) - { - // split on this plane - // if this is the first splitter of this bmodel, remember it - if (!r_pefragtopnode) - r_pefragtopnode = node; - } - -// recurse down the contacted sides - // LordHavoc: optimized recursion -// if (sides & 1) R_SplitEntityOnNode (node->children[0]); -// if (sides & 2) R_SplitEntityOnNode (node->children[1]); - if (sides & 1) - { - if (sides & 2) // 3 - { - R_SplitEntityOnNode (node->children[0]); - node = node->children[1]; - goto loc0; - } - else // 1 - { - node = node->children[0]; - goto loc0; - } - } - // 2 - node = node->children[1]; - goto loc0; -} - - - -/* -=========== -R_AddEfrags -=========== -*/ -void R_AddEfrags (entity_t *ent) -{ - model_t *entmodel; - int i; - - if (!ent->render.model) - return; - - r_addent = ent; - - lastlink = &ent->render.efrag; - r_pefragtopnode = NULL; - - entmodel = ent->render.model; - - for (i=0 ; i<3 ; i++) - { - r_emins[i] = ent->render.origin[i] + entmodel->mins[i]; - r_emaxs[i] = ent->render.origin[i] + entmodel->maxs[i]; - } - - R_SplitEntityOnNode (cl.worldmodel->nodes); - - ent->render.topnode = r_pefragtopnode; -} - - -/* -================ -R_StoreEfrags - -// FIXME: a lot of this goes away with edge-based -================ -*/ -void R_StoreEfrags (efrag_t **ppefrag) -{ - entity_t *pent; - model_t *clmodel; - efrag_t *pefrag; - - - while ((pefrag = *ppefrag) != NULL) - { - pent = pefrag->entity; - clmodel = pent->render.model; - - switch (clmodel->type) - { - case mod_alias: - case mod_brush: - case mod_sprite: - pent = pefrag->entity; - - if ((pent->render.visframe != r_framecount) && (cl_numvisedicts < MAX_VISEDICTS)) - { - cl_visedicts[cl_numvisedicts++] = pent; - pent->render.visframe = r_framecount; // render each entity only once per frame - } - - ppefrag = &pefrag->leafnext; - break; - - default: - Host_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); - } - } -} - - diff --git a/gl_rmain.c b/gl_rmain.c index d266859e..9a4d9333 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -28,7 +28,6 @@ qboolean r_cache_thrash; // compatability vec3_t modelorg, r_entorigin; entity_t *currententity; -int r_visframecount; // bumped when going to a new PVS int r_framecount; // used for dlight push checking mplane_t frustum[4]; @@ -59,8 +58,6 @@ refdef_t r_refdef; mleaf_t *r_viewleaf, *r_oldviewleaf; -texture_t *r_notexture_mip; - unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value @@ -75,7 +72,6 @@ cvar_t r_fullbright = {"r_fullbright","0"}; //cvar_t r_lightmap = {"r_lightmap","0"}; cvar_t r_wateralpha = {"r_wateralpha","1"}; cvar_t r_dynamic = {"r_dynamic","1"}; -cvar_t r_novis = {"r_novis","0"}; cvar_t r_waterripple = {"r_waterripple","0"}; cvar_t r_fullbrights = {"r_fullbrights", "1"}; @@ -94,6 +90,50 @@ 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) + return false; + if (!stack) + return true; + node = nodestack[--stack]; + goto loc0; + } + + sides = BOX_ON_PLANE_SIDE(mins, maxs, node->plane); + +// recurse down the contacted sides + if (sides & 1) + { + if (sides & 2) // 3 + { + // put second child on the stack for later examination + nodestack[stack++] = node->children[1]; + node = node->children[0]; + goto loc0; + } + else // 1 + { + node = node->children[0]; + goto loc0; + } + } + // 2 + node = node->children[1]; + goto loc0; +} + qboolean lighthalf; vec3_t fogcolor; @@ -238,7 +278,6 @@ void GL_Main_Init() Cvar_RegisterVariable (&r_fullbrights); Cvar_RegisterVariable (&r_wateralpha); Cvar_RegisterVariable (&r_dynamic); - Cvar_RegisterVariable (&r_novis); Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple if (nehahra) Cvar_SetValue("r_fullbrights", 0); @@ -784,7 +823,6 @@ r_refdef must be set before the first call ================ */ extern qboolean intimerefresh; -extern qboolean skyisvisible; extern void R_Sky(); extern void UploadLightmaps(); 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]; @@ -809,7 +847,6 @@ void R_RenderView (void) else starttime = currtime = 0; R_Clear(); - skyisvisible = false; TIMEREPORT(time_clear) // render normal view @@ -826,8 +863,7 @@ void R_RenderView (void) TIMEREPORT(time_setup) - R_MarkLeaves (); // done here so we know if we're in water - R_DrawWorld (); // adds static entities to the list + R_DrawWorld (); TIMEREPORT(time_world) R_DrawEntitiesOnList1 (); // BSP models TIMEREPORT(time_bmodels) @@ -837,13 +873,16 @@ void R_RenderView (void) skypolyrender(); // fogged sky polys, affects depth - if (skyname[0] && skyisvisible && !fogenabled) + if (skyname[0] && currentskypoly && !fogenabled) R_Sky(); // does not affect depth, draws over the sky polys TIMEREPORT(time_sky) wallpolyrender(); TIMEREPORT(time_wall) + GL_DrawDecals(); + TIMEREPORT(time_drawdecals) + if (!intimerefresh && !r_speeds2.value) S_ExtraUpdate (); // don't let sound get messed up if going slow @@ -859,8 +898,6 @@ void R_RenderView (void) TIMEREPORT(time_moveexplosions) R_DrawExplosions(); TIMEREPORT(time_drawexplosions) - R_DrawDecals(); - TIMEREPORT(time_drawdecals) transpolyrender(); TIMEREPORT(time_transpoly) diff --git a/gl_rmisc.c b/gl_rmisc.c index cfc884d0..6089fa1b 100644 --- a/gl_rmisc.c +++ b/gl_rmisc.c @@ -22,41 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" - -/* -================== -R_InitTextures -================== -*/ -void R_InitTextures (void) -{ - int x,y, m; - byte *dest; - -// create a simple checkerboard texture for the default - r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); - - r_notexture_mip->width = r_notexture_mip->height = 16; - r_notexture_mip->offsets[0] = sizeof(texture_t); - r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; - r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; - r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; - r_notexture_mip->transparent = false; - - for (m=0 ; m<4 ; m++) - { - dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; - for (y=0 ; y< (16>>m) ; y++) - for (x=0 ; x< (16>>m) ; x++) - { - if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) - *dest++ = 0; - else - *dest++ = 0xff; - } - } -} - /* =============== R_Envmap_f @@ -175,8 +140,8 @@ void R_NewMap (void) // clear out efrags in case the level hasn't been reloaded // FIXME: is this one short? - for (i=0 ; inumleafs ; i++) - cl.worldmodel->leafs[i].efrags = NULL; +// for (i=0 ; inumleafs ; i++) +// cl.worldmodel->leafs[i].efrags = NULL; r_viewleaf = NULL; R_Modules_NewMap(); @@ -191,7 +156,6 @@ void R_NewMap (void) continue; if (!strncmp(cl.worldmodel->textures[i]->name,"sky",3) ) skytexturenum = i; - cl.worldmodel->textures[i]->texturechain = NULL; } SHOWLMP_clear(); } @@ -212,9 +176,11 @@ void R_TimeRefresh_f (void) intimerefresh = 1; start = Sys_FloatTime (); - for (i=0 ; i<128 ; i++) + for (i = 0;i < 128;i++) { + r_refdef.viewangles[0] = 0; r_refdef.viewangles[1] = i/128.0*360.0; + r_refdef.viewangles[2] = 0; SCR_UpdateScreen(); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 3db22309..7a24a597 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -46,14 +46,18 @@ cvar_t gl_nosubimagefragments = {"gl_nosubimagefragments", "0"}; cvar_t gl_nosubimage = {"gl_nosubimage", "0"}; cvar_t r_ambient = {"r_ambient", "0"}; cvar_t gl_vertex = {"gl_vertex", "0"}; -cvar_t gl_texsort = {"gl_texsort", "1"}; -cvar_t r_newworldnode = {"r_newworldnode", "0"}; -cvar_t r_oldclip = {"r_oldclip", "1"}; +cvar_t r_leafworldnode = {"r_leafworldnode", "0"}; +cvar_t r_portalworldnode = {"r_portalworldnode", "0"}; +//cvar_t r_oldclip = {"r_oldclip", "1"}; cvar_t r_dlightmap = {"r_dlightmap", "1"}; +cvar_t r_drawportals = {"r_drawportals", "0"}; +cvar_t r_novis = {"r_novis","0"}; -qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible; +qboolean lightmaprgba, nosubimagefragments, nosubimage; int lightmapbytes; +int wateralpha; + void gl_surf_start() { } @@ -77,10 +81,12 @@ void GL_Surf_Init() Cvar_RegisterVariable(&gl_nosubimage); Cvar_RegisterVariable(&r_ambient); Cvar_RegisterVariable(&gl_vertex); - Cvar_RegisterVariable(&gl_texsort); - Cvar_RegisterVariable(&r_newworldnode); - Cvar_RegisterVariable(&r_oldclip); + Cvar_RegisterVariable(&r_leafworldnode); + Cvar_RegisterVariable(&r_portalworldnode); +// Cvar_RegisterVariable(&r_oldclip); Cvar_RegisterVariable(&r_dlightmap); + Cvar_RegisterVariable(&r_drawportals); + Cvar_RegisterVariable(&r_novis); R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } @@ -315,7 +321,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) *bl++ += *lightmap++ * scale; } } - if (r_dlightmap.value && surf->dlightframe == r_dlightframecount) + if (r_dlightmap.value && surf->dlightframe == r_framecount) if ((surf->cached_dlight = R_AddDynamicLights(surf))) c_light_polys++; } @@ -370,9 +376,9 @@ Returns the proper texture for a given time and base texture */ texture_t *R_TextureAnimation (texture_t *base) { - texture_t *original; - int relative; - int count; +// texture_t *original; +// int relative; +// int count; if (currententity->render.frame) { @@ -383,9 +389,12 @@ texture_t *R_TextureAnimation (texture_t *base) if (!base->anim_total) return base; + return base->anim_frames[(int)(cl.time*5) % base->anim_total]; + + /* original = base; - relative = (int)(cl.time*10) % base->anim_total; + relative = (int)(cl.time*5) % base->anim_total; count = 0; while (base->anim_min > relative || base->anim_max <= relative) @@ -404,6 +413,7 @@ texture_t *R_TextureAnimation (texture_t *base) } return base; + */ } @@ -465,11 +475,18 @@ void UploadLightmaps() float wvert[1024*6]; // used by the following functions +extern qboolean hlbsp; + void RSurf_DrawSky(msurface_t *s, int transform) { glpoly_t *p; int i; float *v; + + // LordHavoc: HalfLife maps have freaky skypolys... + if (hlbsp) + return; + for (p=s->polys ; p ; p=p->next) { if (currentskypoly < MAX_SKYPOLYS && currentskyvert + p->numverts <= MAX_SKYVERTS) @@ -547,12 +564,12 @@ int RSurf_Light(int *dlightbits, glpoly_t *polys) void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) { int i; - float os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(cl.time * TURBSCALE + 96.0) & 255]; + float os = turbsin[(int)(cl.time * TURBSCALE) & 255], ot = turbsin[(int)(cl.time * TURBSCALE + 96.0) & 255]; glpoly_t *p; float *v; // FIXME: make fog texture if water texture is transparent? - if (s->dlightframe != r_dlightframecount) + if (s->dlightframe != r_framecount) { vec3_t temp; // LordHavoc: fast path for no vertex lighting cases @@ -566,7 +583,7 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) { softwaretransform(v, temp); - transpolyvert(temp[0], temp[1], temp[2] + r_waterripple.value * turbsin[(int)((temp[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((temp[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + transpolyvert(temp[0], temp[1], temp[2] + r_waterripple.value * turbsin[(int)((temp[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((temp[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); } transpolyend(); } @@ -593,7 +610,7 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) { transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA); for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) - transpolyvert(v[0], v[1], v[2] + r_waterripple.value * turbsin[(int)((v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + transpolyvert(v[0], v[1], v[2] + r_waterripple.value * turbsin[(int)((v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); transpolyend(); } } @@ -622,12 +639,12 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) else VectorCopy(v, wv); if (r_waterripple.value) - wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f); + wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * (1.0f / 64.0f); wv[3] = wv[4] = wv[5] = 128.0f; wv += 6; } } - if (s->dlightframe == r_dlightframecount) + if (s->dlightframe == r_framecount) RSurf_Light(s->dlightbits, s->polys); wv = wvert; for (p=s->polys ; p ; p=p->next) @@ -650,7 +667,7 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) wallvertcolor_t *outcolor; // check for lightmap modification if (s->cached_dlight - || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_dlightframecount) + || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount) || r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf || (r_dynamic.value @@ -659,7 +676,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_dlightframecount) + if (r_dlightmap.value || s->dlightframe != r_framecount) { // LordHavoc: fast path version for no vertex lighting cases wp = &wallpoly[currentwallpoly]; @@ -726,7 +743,7 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) } if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS)) return; - if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount) + if ((!r_dlightmap.value) && s->dlightframe == r_framecount) lit = RSurf_Light(s->dlightbits, s->polys); wv = wvert; wp = &wallpoly[currentwallpoly]; @@ -816,7 +833,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod wv += 6; } } - if (s->dlightframe == r_dlightframecount) + if (s->dlightframe == r_framecount) RSurf_Light(s->dlightbits, s->polys); wv = wvert; if (isbmodel && (currententity->render.colormod[0] != 1 || currententity->render.colormod[1] != 1 || currententity->render.colormod[2] != 1)) @@ -843,76 +860,6 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod } } -/* -================ -DrawTextureChains -================ -*/ -extern qboolean hlbsp; -extern char skyname[]; -void R_DrawSurf(msurface_t *s, int isbmodel, int vertexlit) -{ - texture_t *t; - if (s->flags & SURF_DRAWSKY) - { - skyisvisible = true; - if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys... - RSurf_DrawSky(s, false); - return; - } - t = R_TextureAnimation (s->texinfo->texture); - if (s->flags & SURF_DRAWTURB) - { - RSurf_DrawWater(s, t, false, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f); - return; - } - if (vertexlit) - RSurf_DrawWallVertex(s, t, false, false); - else - RSurf_DrawWall(s, t, false); -} - -void DrawTextureChains (void) -{ - int n; - msurface_t *s; - texture_t *t; - - for (n = 0;n < cl.worldmodel->numtextures;n++) - { - if (!cl.worldmodel->textures[n] || !(s = cl.worldmodel->textures[n]->texturechain)) - continue; - cl.worldmodel->textures[n]->texturechain = NULL; -// for (;s;s = s->texturechain) -// R_DrawSurf(s, false, gl_vertex.value); - // LordHavoc: decide the render type only once, because the surface properties were determined by texture anyway - // sky - if (s->flags & SURF_DRAWSKY) - { - skyisvisible = true; - if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys... - for (;s;s = s->texturechain) - RSurf_DrawSky(s, false); - continue; - } - t = R_TextureAnimation (cl.worldmodel->textures[n]); - // subdivided water surface warp - if (s->flags & SURF_DRAWTURB) - { - int alpha = s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f; - for (;s;s = s->texturechain) - RSurf_DrawWater(s, t, false, alpha); - continue; - } - if (gl_vertex.value) - for (;s;s = s->texturechain) - RSurf_DrawWallVertex(s, t, false, false); - else - for (;s;s = s->texturechain) - RSurf_DrawWall(s, t, false); - } -} - void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model); /* @@ -927,7 +874,6 @@ void R_DrawBrushModel (entity_t *e) msurface_t *s; model_t *clmodel; int rotated, vertexlit = false; - texture_t *t; vec3_t org; currententity = e; @@ -950,7 +896,7 @@ void R_DrawBrushModel (entity_t *e) VectorAdd (e->render.origin, clmodel->maxs, maxs); } - if (R_CullBox (mins, maxs)) + if (R_VisibleCullBox (mins, maxs)) return; c_bmodels++; @@ -982,9 +928,9 @@ void R_DrawBrushModel (entity_t *e) } 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 + e->render.angles[0] = -e->render.angles[0]; // stupid quake bug softwaretransformforentity (e); -e->render.angles[0] = -e->render.angles[0]; // stupid quake bug + e->render.angles[0] = -e->render.angles[0]; // stupid quake bug // draw texture for (i = 0;i < clmodel->nummodelsurfaces;i++, s++) @@ -992,21 +938,22 @@ e->render.angles[0] = -e->render.angles[0]; // stupid quake bug if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0)) { // R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent); - if (s->flags & SURF_DRAWSKY) + if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) { - RSurf_DrawSky(s, true); - continue; + // sky and liquid don't need sorting (skypoly/transpoly) + if (s->flags & SURF_DRAWSKY) + RSurf_DrawSky(s, true); + else + RSurf_DrawWater(s, R_TextureAnimation(s->texinfo->texture), true, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); } - t = R_TextureAnimation (s->texinfo->texture); - if (s->flags & SURF_DRAWTURB) + else { - RSurf_DrawWater(s, t, true, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f); - continue; + texture_t *t = R_TextureAnimation(s->texinfo->texture); + if (vertexlit || s->texinfo->texture->transparent) + RSurf_DrawWallVertex(s, t, true, true); + else + RSurf_DrawWall(s, t, true); } - if (vertexlit || s->texinfo->texture->transparent) - RSurf_DrawWallVertex(s, t, true, true); - else - RSurf_DrawWall(s, t, true); } } UploadLightmaps(); @@ -1020,26 +967,58 @@ e->render.angles[0] = -e->render.angles[0]; // stupid quake bug ============================================================= */ -void R_StoreEfrags (efrag_t **ppefrag); +int r_vismarkframecount; // bumped when going to a new PVS -void R_NewWorldNode () +void R_MarkLeaves (void) { - int l, texsort = gl_texsort.value, vertex = gl_vertex.value; + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewleaf == r_viewleaf) + return; + + r_vismarkframecount++; + r_oldviewleaf = r_viewleaf; + + vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + + for (i = 0;i < cl.worldmodel->numleafs;i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *)&cl.worldmodel->leafs[i+1]; + do + { + if (node->vismarkframe == r_vismarkframecount) + break; + node->vismarkframe = r_vismarkframecount; + node = node->parent; + } while (node); + } + } +} + +void R_LeafWorldNode () +{ + int l; mleaf_t *leaf; msurface_t *surf, **mark, **endmark; for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++) { - if ((leaf->visframe == r_visframecount) && (leaf->efrags || leaf->nummarksurfaces)) + if ((leaf->vismarkframe == r_vismarkframecount) && (/*leaf->efrags || */leaf->nummarksurfaces)) { - if (R_CullBox(leaf->minmaxs, leaf->minmaxs+3)) + if (R_CullBox(leaf->mins, leaf->maxs)) continue; c_leafs++; + leaf->visframe = r_framecount; + // deal with model fragments in this leaf - if (leaf->efrags) - R_StoreEfrags (&leaf->efrags); +// if (leaf->efrags) +// R_StoreEfrags (&leaf->efrags); if (leaf->nummarksurfaces) { @@ -1054,33 +1033,13 @@ void R_NewWorldNode () 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; - c_faces++; - if (texsort) - { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - else - R_DrawSurf(surf, false, vertex); - } } else { if (!(surf->flags & SURF_PLANEBACK)) - { surf->visframe = r_framecount; - c_faces++; - if (texsort) - { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - else - R_DrawSurf(surf, false, vertex); - } } } while (mark < endmark); @@ -1089,90 +1048,211 @@ void R_NewWorldNode () } } -struct nodestack_s +typedef struct nodestack_s { - int side; + unsigned short side, clip; mnode_t *node; - int noclipping; -} nodestack[8192]; +} +nodestack_t; -/* -================ -R_WorldNode -================ -*/ -void R_WorldNode () +void R_NoVisWorldNode () { - int side, texsort = gl_texsort.value, vertex = gl_vertex.value, ca, cb, cc, cd, noclipping = false, oldclip = r_oldclip.value; - struct nodestack_s *nstack; + int side, c, clip; + nodestack_t *nstack, nodestack[8192]; mnode_t *node; mleaf_t *pleaf; msurface_t *surf, *endsurf, **mark, **endmark; nstack = nodestack; - if (!(node = cl.worldmodel->nodes)) + node = cl.worldmodel->nodes; + + if (!node) return; + clip = true; while(1) { - if (oldclip) + if (node->contents < 0) { - if (R_CullBox(node->minmaxs, node->minmaxs+3)) + if (node->contents != CONTENTS_SOLID && R_NotCulledBox(node->mins, node->maxs)) { -backupstack: - if (nstack <= nodestack) - break; - nstack--; - node = nstack->node; - side = nstack->side; - noclipping = nstack->noclipping; - goto loc0; + // mark surfaces as being visible for processing by code later + pleaf = (mleaf_t *)node; + + c_leafs++; + + pleaf->visframe = r_framecount; + + if (pleaf->nummarksurfaces) + { + mark = pleaf->firstmarksurface; + endmark = mark + pleaf->nummarksurfaces; + do + (*mark++)->visframe = r_framecount; + while (mark < endmark); + } + + // deal with model fragments in this leaf +// if (pleaf->efrags) +// R_StoreEfrags (&pleaf->efrags); } + +culled: + if (nstack <= nodestack) + break; + nstack--; + node = nstack->node; + side = nstack->side; + clip = nstack->clip; + goto loc0; } - else - if (!noclipping) + else if (clip) { - ca = frustum[0].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[0]);if (ca == 2) goto backupstack; // completely clipped away - cb = frustum[1].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[1]);if (cb == 2) goto backupstack; // completely clipped away - cc = frustum[2].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[2]);if (cc == 2) goto backupstack; // completely clipped away - cd = frustum[3].BoxOnPlaneSideFunc(node->minmaxs, node->minmaxs+3, &frustum[3]);if (cd == 2) goto backupstack; // completely clipped away - if (ca == 0 && cb == 0 && cc == 0 && cd == 0) - noclipping = true; // not clipped at all, no need to clip any children of this node + // for easier reading, the values are: + // 1 = not culled at all (very uncommon in large nodes, uncommon in medium nodes, common in small nodes) + // 2 = completely culled (uncommon in large nodes, common in medium nodes, uncommon in small nodes) + // 3 = partially culled (common in large nodes, common in medium nodes, uncommon in small nodes) + if ((c = frustum[0].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[0])) == 3) goto cull1;else if (c == 2) goto culled;// else 1 + if ((c = frustum[1].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[1])) == 3) goto cull2;else if (c == 2) goto culled;// else 1 + if ((c = frustum[2].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[2])) == 3) goto cull3;else if (c == 2) goto culled;// else 1 + if ((c = frustum[3].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[3])) == 3) goto cull4;else if (c == 2) goto culled;// else 1 + // completely onscreen, no need to cull children + clip = false; + goto cull4; // partially clipped node +cull1: if (frustum[1].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[1]) == 2) goto culled;// else 1 or 3 +cull2: if (frustum[2].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[2]) == 2) goto culled;// else 1 or 3 +cull3: if (frustum[3].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[3]) == 2) goto culled;// else 1 or 3 +cull4: ; } - // if a leaf node, draw stuff + + c_nodes++; + + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + side = PlaneDist(modelorg, node->plane) < node->plane->dist; + + // recurse down the children, front side first + nstack->node = node; + nstack->side = !side; // go down back side when we come back up + nstack->clip = clip; + nstack++; + node = node->children[side]; + continue; +loc0: + + // draw stuff + if (node->numsurfaces) + { + surf = cl.worldmodel->surfaces + node->firstsurface; + endsurf = surf + node->numsurfaces; + + if (side) + { + for (;surf < endsurf;surf++) + if (surf->flags & SURF_PLANEBACK) + surf->visframe = -1; + } + else + { + for (;surf < endsurf;surf++) + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = -1; + } + } + + // recurse down the back side + node = node->children[side]; + continue; + } +} + +void R_BSPWorldNode () +{ + int side, c, clip/*, oldclip = r_oldclip.value*/; + nodestack_t *nstack, nodestack[8192]; + mnode_t *node; + mleaf_t *pleaf; + msurface_t *surf, *endsurf, **mark, **endmark; + nstack = nodestack; + + node = cl.worldmodel->nodes; + + if (!node) + return; + + clip = true; + while(1) + { if (node->contents < 0) { - if (node->contents != CONTENTS_SOLID) + if (node->contents != CONTENTS_SOLID && R_NotCulledBox(node->mins, node->maxs)) { + // mark surfaces as being visible for processing by code later pleaf = (mleaf_t *)node; c_leafs++; + + pleaf->visframe = r_framecount; + if (pleaf->nummarksurfaces) { mark = pleaf->firstmarksurface; endmark = mark + pleaf->nummarksurfaces; do - { - (*mark)->visframe = r_framecount; - mark++; - } + (*mark++)->visframe = r_framecount; while (mark < endmark); } // deal with model fragments in this leaf - if (pleaf->efrags) - R_StoreEfrags (&pleaf->efrags); +// if (pleaf->efrags) +// R_StoreEfrags (&pleaf->efrags); } +culled: if (nstack <= nodestack) break; nstack--; node = nstack->node; side = nstack->side; - noclipping = nstack->noclipping; + clip = nstack->clip; goto loc0; } + /* + else if (oldclip) + { + if (R_CullBox(node->mins, node->maxs)) + { + if (nstack <= nodestack) + break; + nstack--; + node = nstack->node; + side = nstack->side; + clip = nstack->clip; + goto loc0; + } + } + */ + else if (clip) + { + // for easier reading, the values are: + // 1 = not culled at all (very uncommon in large nodes, uncommon in medium nodes, common in small nodes) + // 2 = completely culled (uncommon in large nodes, common in medium nodes, uncommon in small nodes) + // 3 = partially culled (common in large nodes, common in medium nodes, uncommon in small nodes) + if ((c = frustum[0].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[0])) == 3) goto cull1;else if (c == 2) goto culled;// else 1 + if ((c = frustum[1].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[1])) == 3) goto cull2;else if (c == 2) goto culled;// else 1 + if ((c = frustum[2].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[2])) == 3) goto cull3;else if (c == 2) goto culled;// else 1 + if ((c = frustum[3].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[3])) == 3) goto cull4;else if (c == 2) goto culled;// else 1 + // completely onscreen, no need to cull children + clip = false; + goto cull4; + // partially clipped node +cull1: if (frustum[1].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[1]) == 2) goto culled;// else 1 or 3 +cull2: if (frustum[2].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[2]) == 2) goto culled;// else 1 or 3 +cull3: if (frustum[3].BoxOnPlaneSideFunc(node->mins, node->maxs, &frustum[3]) == 2) goto culled;// else 1 or 3 +cull4: ; + } c_nodes++; @@ -1182,11 +1262,11 @@ backupstack: side = PlaneDist(modelorg, node->plane) < node->plane->dist; // recurse down the children, front side first - if (node->children[side]->visframe == r_visframecount) + if (node->children[side]->vismarkframe == r_vismarkframecount) { nstack->node = node; nstack->side = !side; // go down back side when we come back up - nstack->noclipping = noclipping; + nstack->clip = clip; nstack++; node = node->children[side]; continue; @@ -1194,84 +1274,28 @@ backupstack: side = !side; loc0: - // draw stuff + // draw stuff if (node->numsurfaces) { surf = cl.worldmodel->surfaces + node->firstsurface; endsurf = surf + node->numsurfaces; - if (texsort) + if (side) { - if (side) - { - do - { - if (surf->visframe == r_framecount && !(surf->flags & SURF_PLANEBACK)) - { - c_faces++; - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - else - surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it - surf++; - } - while (surf < endsurf); - } - else - { - do - { - if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK)) - { - c_faces++; - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - else - surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it - surf++; - } - while (surf < endsurf); - } + for (;surf < endsurf;surf++) + if (surf->flags & SURF_PLANEBACK) + surf->visframe = -1; } else { - if (side) - { - do - { - if (surf->visframe == r_framecount && !(surf->flags & SURF_PLANEBACK)) - { - c_faces++; - R_DrawSurf(surf, false, vertex); - } - else - surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it - surf++; - } - while (surf < endsurf); - } - else - { - do - { - if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK)) - { - c_faces++; - R_DrawSurf(surf, false, vertex); - } - else - surf->visframe = -1; // LordHavoc: mark as not visible, so lighting will not touch it - surf++; - } - while (surf < endsurf); - } + for (;surf < endsurf;surf++) + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = -1; } } - // recurse down the back side - if (node->children[side]->visframe == r_visframecount) + // recurse down the back side + if (node->children[side]->vismarkframe == r_vismarkframecount) { node = node->children[side]; continue; @@ -1282,11 +1306,143 @@ loc0: nstack--; node = nstack->node; side = nstack->side; - noclipping = nstack->noclipping; + clip = nstack->clip; goto loc0; } } +void R_PortalWorldNode () +{ + int portalstack; + mportal_t *p, *pstack[8192]; + msurface_t *surf, **mark, **endmark; + mleaf_t *leaf; + + leaf = r_viewleaf; + portalstack = 0; +loc0: + c_leafs++; + + leaf->visframe = r_framecount; + + // deal with model fragments in this leaf +// if (leaf->efrags) +// R_StoreEfrags (&leaf->efrags); + + 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) + surf->visframe = r_framecount; + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = r_framecount; + } + } + while (mark < endmark); + } + + // follow portals into other leafs + for (p = leaf->portals;p;p = p->next) + { + if (p->past->worldnodeframe != r_framecount) + { + leaf = p->past; + leaf->worldnodeframe = r_framecount; + if (leaf->contents != CONTENTS_SOLID && leaf->vismarkframe == r_vismarkframecount && R_NotCulledBox(leaf->mins, leaf->maxs)) + { + pstack[portalstack++] = p; + goto loc0; +loc1:; + } + } + } + + if (portalstack) + { + p = pstack[--portalstack]; + goto loc1; + } +} + +void R_DrawSurfaces (void) +{ + msurface_t *surf, *endsurf; + texture_t *t; + int vertex = gl_vertex.value; + + surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; + endsurf = surf + cl.worldmodel->nummodelsurfaces; + for (;surf < endsurf;surf++) + { + if (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 (vertex) + RSurf_DrawWallVertex(surf, t, false, false); + else + RSurf_DrawWall(surf, t, false); + } + } + } +} + +void R_DrawPortals() +{ + int drawportals, i, r, g, b; + mleaf_t *leaf, *endleaf; + mportal_t *portal; + 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++) + { + if (leaf->visframe == r_framecount && leaf->portals) + { + i = leaf - cl.worldmodel->leafs; + r = (i & 0x0007) << 5; + g = (i & 0x0038) << 2; + b = (i & 0x01C0) >> 1; + portal = leaf->portals; + while (portal) + { + transpolybegin(0, 0, 0, TPOLYTYPE_ALPHA); + point = portal->points; + endpoint = point + portal->numpoints; + for (;point < endpoint;point++) + transpolyvertub(point->position[0], point->position[1], point->position[2], 0, 0, r, g, b, 32); + transpolyend(); + portal = portal->next; + } + } + } +} /* ============= @@ -1297,6 +1453,8 @@ void R_DrawWorld (void) { entity_t ent; + wateralpha = bound(0, r_wateralpha.value*255.0f, 255); + memset (&ent, 0, sizeof(ent)); ent.render.model = cl.worldmodel; ent.render.colormod[0] = ent.render.colormod[1] = ent.render.colormod[2] = 1; @@ -1311,72 +1469,27 @@ void R_DrawWorld (void) if (cl.worldmodel) { - if (r_newworldnode.value) - R_NewWorldNode (); + if (r_novis.value || !r_viewleaf->compressed_vis) + R_NoVisWorldNode (); else - R_WorldNode (); + { + R_MarkLeaves (); + if (r_portalworldnode.value) + R_PortalWorldNode (); + else if (r_leafworldnode.value) + R_LeafWorldNode (); + else + R_BSPWorldNode (); + } } R_PushDlights (); // now mark the lit surfaces - DrawTextureChains (); -} - + R_DrawSurfaces (); -/* -=============== -R_MarkLeaves -=============== -*/ -void R_MarkLeaves (void) -{ - byte *vis; - mnode_t *node; - int i; - - if (r_oldviewleaf == r_viewleaf && !r_novis.value) - return; - - r_visframecount++; - r_oldviewleaf = r_viewleaf; - - if (r_novis.value) - { - for (i=0 ; inumleafs ; i++) - { - node = (mnode_t *)&cl.worldmodel->leafs[i+1]; - do - { - if (node->visframe == r_visframecount) - break; - node->visframe = r_visframecount; - node = node->parent; - } while (node); - } - } - else - { - vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - - for (i=0 ; inumleafs ; i++) - { - if (vis[i>>3] & (1<<(i&7))) - { - node = (mnode_t *)&cl.worldmodel->leafs[i+1]; - do - { - if (node->visframe == r_visframecount) - break; - node->visframe = r_visframecount; - node = node->parent; - } while (node); - } - } - } + R_DrawPortals (); } - - /* ============================================================================= @@ -1392,11 +1505,11 @@ int AllocBlock (int w, int h, short *x, short *y) int best, best2; int texnum; - for (texnum=0 ; texnum scr_erase_lines) scr_erase_lines = scr_center_lines; @@ -267,7 +260,6 @@ static void SCR_CalcRefdef (void) qboolean full = false; - scr_fullupdate = 0; // force a background redraw vid.recalc_refdef = 0; //======================================== @@ -501,6 +493,7 @@ void SCR_DrawPause (void) SCR_DrawLoading ============== */ +/* void SCR_DrawLoading (void) { qpic_t *pic; @@ -512,6 +505,7 @@ void SCR_DrawLoading (void) Draw_Pic ( (vid.width - pic->width)/2, (vid.height - 48 - pic->height)/2, pic); } +*/ @@ -567,7 +561,6 @@ void SCR_DrawConsole (void) { if (scr_con_current) { - scr_copyeverything = 1; Con_DrawConsole (scr_con_current, true); clearconsole = 0; } @@ -637,29 +630,28 @@ SCR_BeginLoadingPlaque ================ */ +/* void SCR_BeginLoadingPlaque (void) { S_StopAllSounds (true); - if (cls.state != ca_connected) - return; - if (cls.signon != SIGNONS) - return; +// if (cls.state != ca_connected) +// return; +// if (cls.signon != SIGNONS) +// return; // redraw with no console and the loading plaque - Con_ClearNotify (); - scr_centertime_off = 0; - scr_con_current = 0; +// Con_ClearNotify (); +// scr_centertime_off = 0; +// scr_con_current = 0; scr_drawloading = true; - scr_fullupdate = 0; SCR_UpdateScreen (); - scr_drawloading = false; - scr_disabled_for_loading = true; - scr_disabled_time = realtime; - scr_fullupdate = 0; +// scr_disabled_for_loading = true; +// scr_disabled_time = realtime; } +*/ /* =============== @@ -667,17 +659,18 @@ SCR_EndLoadingPlaque ================ */ +/* void SCR_EndLoadingPlaque (void) { - scr_disabled_for_loading = false; - scr_fullupdate = 0; +// scr_disabled_for_loading = false; + scr_drawloading = false; Con_ClearNotify (); } +*/ //============================================================================= char *scr_notifystring; -qboolean scr_drawdialog; void SCR_DrawNotifyString (void) { @@ -712,63 +705,8 @@ void SCR_DrawNotifyString (void) } while (1); } -/* -================== -SCR_ModalMessage - -Displays a text string in the center of the screen and waits for a Y or N -keypress. -================== -*/ -int SCR_ModalMessage (char *text) -{ - if (cls.state == ca_dedicated) - return true; - - scr_notifystring = text; - -// draw a fresh screen - scr_fullupdate = 0; - scr_drawdialog = true; - SCR_UpdateScreen (); - scr_drawdialog = false; - - S_ClearBuffer (); // so dma doesn't loop current sound - - do - { - key_count = -1; // wait for a key down and up - Sys_SendKeyEvents (); - } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE); - - scr_fullupdate = 0; - SCR_UpdateScreen (); - - return key_lastpress == 'y'; -} - - //============================================================================= -/* -=============== -SCR_BringDownConsole - -Brings the console down and fades the blends back to normal -================ -*/ -void SCR_BringDownConsole (void) -{ - int i; - - scr_centertime_off = 0; - - for (i=0 ; i<20 && scr_conlines != scr_con_current ; i++) - SCR_UpdateScreen (); - - cl.cshifts[0].percent = 0; // no area contents blend on next frame -} - void DrawCrosshair(int num); void GL_Set2D (void); @@ -785,7 +723,9 @@ void GL_BrightenScreen() return; glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); - f = brightness.value = bound(1.0f, brightness.value, 5.0f); + f = bound(1.0f, brightness.value, 5.0f); + if (f != brightness.value) + Cvar_SetValue("brightness", f); if (f >= 1.01f) { glBlendFunc (GL_DST_COLOR, GL_ONE); @@ -804,7 +744,9 @@ void GL_BrightenScreen() glEnd (); } glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - contrast.value = bound(0.2, contrast.value, 1.0); + f = bound(0.2f, contrast.value, 1.0f); + if (f != contrast.value) + Cvar_SetValue("contrast", f); if (contrast.value < 0.99f) { glBegin (GL_TRIANGLES); @@ -839,17 +781,16 @@ void SCR_UpdateScreen (void) if (r_speeds.value) time1 = Sys_FloatTime (); - scr_copytop = 0; - scr_copyeverything = 0; - if (scr_disabled_for_loading) { + /* if (realtime - scr_disabled_time > 60) { scr_disabled_for_loading = false; Con_Printf ("load failed.\n"); } else + */ return; } @@ -875,59 +816,44 @@ void SCR_UpdateScreen (void) } if (vid.recalc_refdef) - SCR_CalcRefdef (); + SCR_CalcRefdef(); if (r_render.value) { glClearColor(0,0,0,0); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) } // // do 3D refresh drawing, and then update the screen // - SCR_SetUpToDrawConsole (); + SCR_SetUpToDrawConsole(); - V_RenderView (); + V_RenderView(); - GL_Set2D (); + GL_Set2D(); - if (scr_drawdialog) - { - Sbar_Draw (); -// Draw_FadeScreen (); - SCR_DrawNotifyString (); - scr_copyeverything = true; - } - else if (scr_drawloading) - { - SCR_DrawLoading (); - Sbar_Draw (); - } - else if (cl.intermission == 1 && key_dest == key_game) - { - Sbar_IntermissionOverlay (); - } - else if (cl.intermission == 2 && key_dest == key_game) - { - Sbar_FinaleOverlay (); - SCR_CheckDrawCenterString (); - } - else - { - if (crosshair.value) - DrawCrosshair(crosshair.value - 1); - - SCR_DrawRam (); - SCR_DrawNet (); - SCR_DrawTurtle (); - SCR_DrawPause (); - SCR_CheckDrawCenterString (); - Sbar_Draw (); - SHOWLMP_drawall(); - SCR_DrawConsole (); - M_Draw (); - } + SCR_DrawRam(); + SCR_DrawNet(); + SCR_DrawTurtle(); + SCR_DrawPause(); + SCR_CheckDrawCenterString(); + Sbar_Draw(); + SHOWLMP_drawall(); + + if (crosshair.value) + DrawCrosshair(crosshair.value - 1); + + if (cl.intermission == 1) + Sbar_IntermissionOverlay(); + else if (cl.intermission == 2) + Sbar_FinaleOverlay(); + + SCR_DrawConsole(); + M_Draw(); + +// if (scr_drawloading) +// SCR_DrawLoading(); if (showfps.value) { @@ -954,7 +880,7 @@ void SCR_UpdateScreen (void) Draw_String(0, vid.height - sb_lines - 8, r_speeds2_string7, 80); } - V_UpdateBlends (); + V_UpdateBlends(); GL_BrightenScreen(); diff --git a/glquake.h b/glquake.h index c9e0e039..2b3e9cca 100644 --- a/glquake.h +++ b/glquake.h @@ -77,7 +77,6 @@ extern entity_t r_worldentity; extern qboolean r_cache_thrash; // compatability extern vec3_t modelorg, r_entorigin; extern entity_t *currententity; -extern int r_visframecount; // ??? what difs? extern int r_framecount; extern mplane_t frustum[4]; extern int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; @@ -96,7 +95,6 @@ extern vec3_t r_origin; // extern refdef_t r_refdef; extern mleaf_t *r_viewleaf, *r_oldviewleaf; -extern texture_t *r_notexture_mip; extern unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value extern qboolean envmap; @@ -109,7 +107,6 @@ extern cvar_t r_speeds; extern cvar_t r_fullbright; extern cvar_t r_wateralpha; extern cvar_t r_dynamic; -extern cvar_t r_novis; extern cvar_t r_waterripple; extern float r_world_matrix[16]; diff --git a/host.c b/host.c index e32d0a75..c4aa4090 100644 --- a/host.c +++ b/host.c @@ -39,7 +39,6 @@ qboolean hostloopactive = 0; // LordHavoc: used to turn Host_Error into Sys_Err double host_frametime; double host_realframetime; // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling) -double host_time; double realtime; // without any filtering or bounding double oldrealtime; // last frame run int host_framecount; @@ -146,7 +145,7 @@ void Host_Error (char *error, ...) } inerror = true; - SCR_EndLoadingPlaque (); // reenable screen updates +// SCR_EndLoadingPlaque (); // reenable screen updates va_start (argptr,error); vsprintf (hosterrorstring,error,argptr); @@ -255,8 +254,6 @@ void Host_InitLocal (void) Cvar_RegisterVariable (&timeformat); Host_FindMaxClients (); - - host_time = 1.0; // so a think at time 0 won't get called } @@ -691,8 +688,6 @@ void _Host_Frame (float time) if (!sv.active) CL_SendCmd (); - host_time += host_frametime; - // fetch results from server if (cls.state == ca_connected) CL_ReadFromServer (); @@ -831,8 +826,6 @@ void Host_Init () Con_Printf ("Exe: "__TIME__" "__DATE__"\n"); Con_Printf ("%4.1f megabyte heap\n",host_parms.memsize/(1024*1024.0)); - R_InitTextures (); // needed even for dedicated servers - if (cls.state != ca_dedicated) { Palette_Init("gfx/palette.lmp"); diff --git a/host_cmd.c b/host_cmd.c index f9f32256..7510ee75 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -268,11 +268,12 @@ void Host_Map_f (void) cls.demonum = -1; // stop demo loop in case this fails +// SCR_BeginLoadingPlaque (); + CL_Disconnect (); Host_ShutdownServer(false); key_dest = key_game; // remove console or menu - SCR_BeginLoadingPlaque (); cls.mapstring[0] = 0; for (i=0 ; i 1) - { return; // ignore most autorepeats - } if (key >= 200 && !keybindings[key]) Con_Printf ("%s is unbound, hit F4 to set.\n", Key_KeynumToString (key) ); @@ -660,7 +656,7 @@ void Key_Event (int key, qboolean down) // key up events only generate commands if the game key binding is // a button command (leading + sign). These will occur even in console mode, // to keep the character from continuing an action started before a console -// switch. Button commands include the kenum as a parameter, so multiple +// switch. Button commands include the keynum as a parameter, so multiple // downs can be matched with ups // if (!down) diff --git a/makefile b/makefile index 7cbbad77..e1f07787 100644 --- a/makefile +++ b/makefile @@ -7,7 +7,7 @@ SND=snd_alsa_0_9.o #if you use the kernel sound driver or OSS #SND=snd_oss.o -OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o +OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o OPTIMIZATIONS= -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations diff --git a/menu.c b/menu.c index dbb8addc..e3795323 100644 --- a/menu.c +++ b/menu.c @@ -87,7 +87,7 @@ void M_ServerList_Key (int key); qboolean m_entersound; // play after drawing a frame, so caching // won't disrupt the sound -qboolean m_recursiveDraw; +//qboolean m_recursiveDraw; int m_return_state; qboolean m_return_onerror; @@ -388,7 +388,7 @@ void M_Demo_Key (int k) S_LocalSound ("misc/menu2.wav"); m_state = m_none; key_dest = key_game; - SCR_BeginLoadingPlaque (); +// SCR_BeginLoadingPlaque (); Cbuf_AddText (va ("playdemo %s\n", Demos[demo_cursor].name)); return; @@ -464,7 +464,7 @@ void M_Main_Draw (void) else M_DrawPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp")); - f = (int)(host_time * 10)%6; + f = (int)(realtime * 10)%6; M_DrawPic (54, 32 + m_main_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); } @@ -637,7 +637,7 @@ void M_SinglePlayer_Draw (void) M_DrawPic ( (320-p->width)/2, 4, p); M_DrawPic (72, 32, Draw_CachePic ("gfx/sp_menu.lmp") ); - f = (int)(host_time * 10)%6; + f = (int)(realtime * 10)%6; M_DrawPic (54, 32 + m_singleplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); } @@ -669,9 +669,6 @@ void M_SinglePlayer_Key (int key) switch (m_singleplayer_cursor) { case 0: - if (sv.active) - if (!SCR_ModalMessage("Are you sure you want to\nstart a new game?\n")) - break; key_dest = key_game; if (sv.active) Cbuf_AddText ("disconnect\n"); @@ -801,11 +798,12 @@ void M_Load_Key (int k) m_state = m_none; key_dest = key_game; - // Host_Loadgame_f can't bring up the loading plaque because too much - // stack space has been used, so do it now - SCR_BeginLoadingPlaque (); + // LordHavoc: made SCR_UpdateScreen use a great deal less stack space, no longer an issue + //// Host_Loadgame_f can't bring up the loading plaque because too much + //// stack space has been used, so do it now +//// SCR_BeginLoadingPlaque (); - // issue the load command + // issue the load command Cbuf_AddText (va ("load s%i\n", load_cursor) ); return; @@ -885,7 +883,7 @@ void M_MultiPlayer_Draw (void) M_DrawPic ( (320-p->width)/2, 4, p); M_DrawPic (72, 32, Draw_CachePic ("gfx/mp_menu.lmp") ); - f = (int)(host_time * 10)%6; + f = (int)(realtime * 10)%6; M_DrawPic (54, 32 + m_multiplayer_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); @@ -1182,7 +1180,7 @@ void M_Net_Draw (void) M_Print (f, 142, net_helpMessage[m_net_cursor*4+0]); M_Print (f, 150, net_helpMessage[m_net_cursor*4+1]); - f = (int)(host_time * 10)%6; + f = (int)(realtime * 10)%6; M_DrawPic (54, 32 + m_net_cursor * 20,Draw_CachePic( va("gfx/menudot%i.lmp", f+1 ) ) ); } @@ -1780,10 +1778,11 @@ int msgNumber; int m_quit_prevstate; qboolean wasInMenus; -#ifndef _WIN32 +//#ifndef _WIN32 char *quitMessage [] = { /* .........1.........2.... */ +/* " Are you gonna quit ", " this game just like ", " everything else? ", @@ -1823,8 +1822,30 @@ char *quitMessage [] = " throw a blanket-party ", " for you next time! ", " " + */ + +/* .........1.........2.... */ + " ", + " Tired of fragging ", + " already? ", + " ", + + " ", + " Quit now and forfeit ", + " your bodycount? ", + " ", + + " ", + " Are you sure you ", + " want to quit? ", + " ", + + " ", + " Off to do something ", + " constructive? ", + " ", }; -#endif +//#endif void M_Menu_Quit_f (void) { @@ -1835,7 +1856,7 @@ void M_Menu_Quit_f (void) m_quit_prevstate = m_state; m_state = m_quit; m_entersound = true; - msgNumber = rand()&7; + msgNumber = rand()&3; //&7; } @@ -1876,11 +1897,12 @@ void M_Quit_Draw (void) if (wasInMenus) { m_state = m_quit_prevstate; - m_recursiveDraw = true; +// m_recursiveDraw = true; M_Draw (); m_state = m_quit; } +/* #ifdef _WIN32 M_DrawTextBox (0, 0, 38, 23); M_PrintWhite (16, 12, " Quake version 1.09 by id Software\n\n"); @@ -1905,12 +1927,13 @@ void M_Quit_Draw (void) M_PrintWhite (16, 172, "Nothing Interactive, Inc. All rights\n"); M_PrintWhite (16, 180, "reserved. Press y to exit\n"); #else +*/ M_DrawTextBox (56, 76, 24, 4); M_Print (64, 84, quitMessage[msgNumber*4+0]); M_Print (64, 92, quitMessage[msgNumber*4+1]); M_Print (64, 100, quitMessage[msgNumber*4+2]); M_Print (64, 108, quitMessage[msgNumber*4+3]); -#endif +//#endif } //============================================================================= @@ -2616,7 +2639,7 @@ void M_GameOptions_Key (int key) Cbuf_AddText ("disconnect\n"); Cbuf_AddText ("listen 0\n"); // so host_netport will be re-examined Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) ); - SCR_BeginLoadingPlaque (); +// SCR_BeginLoadingPlaque (); if (hipnotic) Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) ); @@ -2855,24 +2878,20 @@ void M_Draw (void) if (m_state == m_none || key_dest != key_menu) return; + /* if (!m_recursiveDraw) { - scr_copyeverything = 1; - if (scr_con_current) { Draw_ConsoleBackground (vid.height); S_ExtraUpdate (); } -// else -// Draw_FadeScreen (); - - scr_fullupdate = 0; } else { m_recursiveDraw = false; } + */ switch (m_state) { diff --git a/model_brush.c b/model_brush.c index 8604c43b..f1f87b8c 100644 --- a/model_brush.c +++ b/model_brush.c @@ -146,6 +146,47 @@ extern byte *mod_base; extern cvar_t r_fullbrights; +rtexture_t *r_notexture; +texture_t r_notexture_mip; + +void Mod_SetupNoTexture() +{ + int x, y; + byte pix[16][16][4]; + + // create a simple checkerboard texture for the default + // LordHavoc: redesigned this to remove reliance on the palette and texture_t + for (y = 0;y < 16;y++) + { + for (x = 0;x < 16;x++) + { + if ((y < 8) ^ (x < 8)) + { + pix[y][x][0] = 128; + pix[y][x][1] = 128; + pix[y][x][2] = 128; + pix[y][x][3] = 255; + } + else + { + pix[y][x][0] = 64; + pix[y][x][1] = 64; + pix[y][x][2] = 64; + pix[y][x][3] = 255; + } + } + } + + r_notexture = R_LoadTexture("notexture", 16, 16, &pix[0][0][0], TEXF_MIPMAP | TEXF_RGBA); + + strcpy(r_notexture_mip.name, "notexture"); + r_notexture_mip.width = 16; + r_notexture_mip.height = 16; + r_notexture_mip.transparent = false; + r_notexture_mip.texture = r_notexture; + r_notexture_mip.glowtexture = NULL; +} + /* ================= Mod_LoadTextures @@ -153,14 +194,11 @@ Mod_LoadTextures */ void Mod_LoadTextures (lump_t *l) { - int i, j, num, max, altmax; - miptex_t *mt; - texture_t *tx, *tx2; - texture_t *anims[10]; - texture_t *altanims[10]; - dmiptexlump_t *m; - byte *data; - int *dofs; + int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs; + miptex_t *dmiptex; + texture_t *tx, *tx2, *anims[10], *altanims[10]; + dmiptexlump_t *m; + byte *data, *mtdata; if (!l->filelen) { @@ -177,44 +215,49 @@ void Mod_LoadTextures (lump_t *l) // just to work around bounds checking when debugging with it (array index out of bounds error thing) dofs = m->dataofs; - for (i=0 ; inummiptex ; i++) + for (i = 0;i < m->nummiptex;i++) { dofs[i] = LittleLong(dofs[i]); if (dofs[i] == -1) continue; - mt = (miptex_t *)((byte *)m + dofs[i]); - mt->width = LittleLong (mt->width); - mt->height = LittleLong (mt->height); - for (j=0 ; joffsets[j] = LittleLong (mt->offsets[j]); + dmiptex = (miptex_t *)((byte *)m + dofs[i]); + mtwidth = LittleLong (dmiptex->width); + mtheight = LittleLong (dmiptex->height); + mtdata = NULL; + j = LittleLong (dmiptex->offsets[0]); + if (j) + { + // texture included + if (j < 40 || j + mtwidth * mtheight > l->filelen) + Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name); + mtdata = (byte *)dmiptex + j; + } - if ( (mt->width & 15) || (mt->height & 15) ) - Host_Error ("Texture %s is not 16 aligned", mt->name); + if ((mtwidth & 15) || (mtheight & 15)) + Host_Error ("Texture %s is not 16 aligned", dmiptex->name); // LordHavoc: rewriting the map texture loader for GLQuake tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname)); loadmodel->textures[i] = tx; // LordHavoc: force all names to lowercase and make sure they are terminated while copying - for (j = 0;mt->name[j] && j < 15;j++) + for (j = 0;dmiptex->name[j] && j < 15;j++) { - if (mt->name[j] >= 'A' && mt->name[j] <= 'Z') - tx->name[j] = mt->name[j] + ('a' - 'A'); + if (dmiptex->name[j] >= 'A' && dmiptex->name[j] <= 'Z') + tx->name[j] = dmiptex->name[j] + ('a' - 'A'); else - tx->name[j] = mt->name[j]; + tx->name[j] = dmiptex->name[j]; } for (;j < 16;j++) tx->name[j] = 0; - for (j=0 ; joffsets[j] = 0; tx->transparent = false; data = loadimagepixels(tx->name, false, 0, 0); if (data) { if (!hlbsp && !strncmp(tx->name,"sky",3) && image_width == 256 && image_height == 128) // LordHavoc: HL sky textures are entirely unrelated { - tx->width = image_width; - tx->height = image_height; + tx->width = 0; + tx->height = 0; tx->transparent = false; tx->texture = NULL; tx->glowtexture = NULL; @@ -222,8 +265,8 @@ void Mod_LoadTextures (lump_t *l) } else { - tx->width = mt->width; - tx->height = mt->height; + tx->width = mtwidth; + tx->height = mtheight; tx->transparent = Image_CheckAlpha(data, image_width * image_height, true); tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE); tx->glowtexture = NULL; @@ -232,63 +275,63 @@ void Mod_LoadTextures (lump_t *l) } else { - if (!hlbsp && !strncmp(tx->name,"sky",3) && mt->width == 256 && mt->height == 128) // LordHavoc: HL sky textures are entirely unrelated + if (hlbsp) { - tx->width = mt->width; - tx->height = mt->height; - tx->transparent = false; - tx->texture = NULL; - tx->glowtexture = NULL; - R_InitSky ((byte *)((int) mt + mt->offsets[0]), 1); - } - else - { - if (hlbsp) + if (mtdata) // texture included { - if (mt->offsets[0]) // texture included - { - data = W_ConvertWAD3Texture(mt); - if (data) - { - tx->width = mt->width; - tx->height = mt->height; - tx->transparent = Image_CheckAlpha(data, mt->width * mt->height, true); - tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE); - tx->glowtexture = NULL; - qfree(data); - } - } - if (!data) + data = W_ConvertWAD3Texture(dmiptex); + if (data) { - data = W_GetTexture(mt->name); - // get the size from the wad texture - if (data) - { - tx->width = image_width; - tx->height = image_height; - tx->transparent = Image_CheckAlpha(data, image_width * image_height, true); - tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE); - tx->glowtexture = NULL; - qfree(data); - } + tx->width = mtwidth; + tx->height = mtheight; + tx->transparent = Image_CheckAlpha(data, mtwidth * mtheight, true); + tx->texture = R_LoadTexture (tx->name, mtwidth, mtheight, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE); + tx->glowtexture = NULL; + qfree(data); } - if (!data) + } + if (!data) + { + data = W_GetTexture(tx->name); + // get the size from the wad texture + if (data) { - tx->width = r_notexture_mip->width; - tx->height = r_notexture_mip->height; - tx->transparent = false; - tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE); + tx->width = image_width; + tx->height = image_height; + tx->transparent = Image_CheckAlpha(data, image_width * image_height, true); + tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | (tx->transparent ? TEXF_ALPHA : 0) | TEXF_RGBA | TEXF_PRECACHE); tx->glowtexture = NULL; + qfree(data); } } + if (!data) + { + tx->width = 16; + tx->height = 16; + tx->transparent = false; + tx->texture = r_notexture; + tx->glowtexture = NULL; + } + } + else + { + if (!strncmp(tx->name,"sky",3) && mtwidth == 256 && mtheight == 128) + { + tx->width = mtwidth; + tx->height = mtheight; + tx->transparent = false; + tx->texture = NULL; + tx->glowtexture = NULL; + R_InitSky (mtdata, 1); + } else { - if (mt->offsets[0]) // texture included + if (mtdata) // texture included { int fullbrights; - data = (byte *)((int) mt + mt->offsets[0]); - tx->width = mt->width; - tx->height = mt->height; + data = mtdata; + tx->width = mtwidth; + tx->height = mtheight; tx->transparent = false; fullbrights = false; if (r_fullbrights.value && tx->name[0] != '*') @@ -325,10 +368,10 @@ void Mod_LoadTextures (lump_t *l) } else // no texture, and no external replacement texture was found { - tx->width = r_notexture_mip->width; - tx->height = r_notexture_mip->height; + tx->width = 16; + tx->height = 16; tx->transparent = false; - tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE); + tx->texture = r_notexture; tx->glowtexture = NULL; } } @@ -339,22 +382,20 @@ void Mod_LoadTextures (lump_t *l) // // sequence the animations // - for (i=0 ; inummiptex ; i++) + for (i = 0;i < m->nummiptex;i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; - if (tx->anim_next) + if (tx->anim_total) continue; // already sequenced - // find the number of frames in the animation + // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; - if (max >= 'a' && max <= 'z') - max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; @@ -362,9 +403,9 @@ void Mod_LoadTextures (lump_t *l) anims[max] = tx; max++; } - else if (max >= 'A' && max <= 'J') + else if (max >= 'a' && max <= 'j') { - altmax = max - 'A'; + altmax = max - 'a'; max = 0; altanims[altmax] = tx; altmax++; @@ -372,7 +413,7 @@ void Mod_LoadTextures (lump_t *l) else Host_Error ("Bad animating texture %s", tx->name); - for (j=i+1 ; jnummiptex ; j++) + for (j = i + 1;j < m->nummiptex;j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') @@ -381,8 +422,6 @@ void Mod_LoadTextures (lump_t *l) continue; num = tx2->name[1]; - if (num >= 'a' && num <= 'z') - num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; @@ -390,9 +429,9 @@ void Mod_LoadTextures (lump_t *l) if (num+1 > max) max = num + 1; } - else if (num >= 'A' && num <= 'J') + else if (num >= 'a' && num <= 'j') { - num = num - 'A'; + num = num - 'a'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; @@ -400,32 +439,29 @@ void Mod_LoadTextures (lump_t *l) else Host_Error ("Bad animating texture %s", tx->name); } - -#define ANIM_CYCLE 2 - // link them all together - for (j=0 ; jname); - tx2->anim_total = max * ANIM_CYCLE; - tx2->anim_min = j * ANIM_CYCLE; - tx2->anim_max = (j+1) * ANIM_CYCLE; - tx2->anim_next = anims[ (j+1)%max ]; + Host_Error ("Missing frame %i of %s", j, tx->name); + tx2->anim_total = max; if (altmax) tx2->alternate_anims = altanims[0]; + for (k = 0;k < 10;k++) + tx2->anim_frames[k] = anims[j]; } - for (j=0 ; jname); - tx2->anim_total = altmax * ANIM_CYCLE; - tx2->anim_min = j * ANIM_CYCLE; - tx2->anim_max = (j+1) * ANIM_CYCLE; - tx2->anim_next = altanims[ (j+1)%altmax ]; + Host_Error ("Missing frame %i of %s", j, tx->name); + tx2->anim_total = altmax; if (max) tx2->alternate_anims = anims[0]; + for (k = 0;k < 10;k++) + tx2->anim_frames[k] = altanims[j]; } } } @@ -631,7 +667,6 @@ void Mod_LoadTexinfo (lump_t *l) mtexinfo_t *out; int i, j, k, count; int miptex; - float len1, len2; in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) @@ -647,32 +682,14 @@ void Mod_LoadTexinfo (lump_t *l) for (k=0 ; k<2 ; k++) for (j=0 ; j<4 ; j++) out->vecs[k][j] = LittleFloat (in->vecs[k][j]); - len1 = Length (out->vecs[0]); - len2 = Length (out->vecs[1]); - len1 = (len1 + len2)/2; - if (len1 < 0.32) - out->mipadjust = 4; - else if (len1 < 0.49) - out->mipadjust = 3; - else if (len1 < 0.99) - out->mipadjust = 2; - else - out->mipadjust = 1; -#if 0 - if (len1 + len2 < 0.001) - out->mipadjust = 1; // don't crash - else - out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); -#endif miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); if (!loadmodel->textures) { - out->texture = r_notexture_mip; // checkerboard texture + out->texture = &r_notexture_mip; // checkerboard texture out->flags = 0; - out->texture->transparent = false; } else { @@ -681,9 +698,8 @@ void Mod_LoadTexinfo (lump_t *l) out->texture = loadmodel->textures[miptex]; if (!out->texture) { - out->texture = r_notexture_mip; // texture not found + out->texture = &r_notexture_mip; // checkerboard texture out->flags = 0; - out->texture->transparent = false; } } } @@ -871,8 +887,8 @@ void Mod_LoadNodes (lump_t *l) { for (j=0 ; j<3 ; j++) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + out->mins[j] = LittleShort (in->mins[j]); + out->maxs[j] = LittleShort (in->maxs[j]); } p = LittleLong(in->planenum); @@ -918,8 +934,8 @@ void Mod_LoadLeafs (lump_t *l) { for (j=0 ; j<3 ; j++) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + out->mins[j] = LittleShort (in->mins[j]); + out->maxs[j] = LittleShort (in->maxs[j]); } p = LittleLong(in->contents); @@ -934,7 +950,7 @@ void Mod_LoadLeafs (lump_t *l) out->compressed_vis = NULL; else out->compressed_vis = loadmodel->visdata + p; - out->efrags = NULL; +// out->efrags = NULL; for (j=0 ; j<4 ; j++) out->ambient_sound_level[j] = in->ambient_level[j]; @@ -1055,9 +1071,9 @@ Duplicate the drawing hull structure as a clipping hull */ void Mod_MakeHull0 (void) { - mnode_t *in, *child; + mnode_t *in; dclipnode_t *out; - int i, j, count; + int i, count; hull_t *hull; hull = &loadmodel->hulls[0]; @@ -1068,20 +1084,14 @@ void Mod_MakeHull0 (void) hull->clipnodes = out; hull->firstclipnode = 0; - hull->lastclipnode = count-1; + hull->lastclipnode = count - 1; hull->planes = loadmodel->planes; - for (i=0 ; iplanenum = in->plane - loadmodel->planes; - for (j=0 ; j<2 ; j++) - { - child = in->children[j]; - if (child->contents < 0) - out->children[j] = child->contents; - else - out->children[j] = child - loadmodel->nodes; - } + out->children[0] = in->children[0]->contents < 0 ? in->children[0]->contents : in->children[0] - loadmodel->nodes; + out->children[1] = in->children[1]->contents < 0 ? in->children[1]->contents : in->children[1] - loadmodel->nodes; } } @@ -1177,6 +1187,644 @@ void Mod_LoadPlanes (lump_t *l) } } +#define MAX_POINTS_ON_WINDING 64 + +typedef struct +{ + int numpoints; + vec3_t points[8]; // variable sized +} +winding_t; + +/* +================== +NewWinding +================== +*/ +winding_t *NewWinding (int points) +{ + winding_t *w; + int size; + + if (points > MAX_POINTS_ON_WINDING) + Host_Error("NewWinding: too many points\n"); + + size = (int)((winding_t *)0)->points[points]; + w = malloc (size); + memset (w, 0, size); + + return w; +} + +void FreeWinding (winding_t *w) +{ + free (w); +} + +/* +================= +BaseWindingForPlane +================= +*/ +winding_t *BaseWindingForPlane (mplane_t *p) +{ + vec3_t org, vright, vup; + winding_t *w; + + VectorVectors(p->normal, vright, vup); + + VectorScale (vup, 65536, vup); + VectorScale (vright, 65536, vright); + + // project a really big axis aligned box onto the plane + w = NewWinding (4); + + VectorScale (p->normal, p->dist, org); + + VectorSubtract (org, vright, w->points[0]); + VectorAdd (w->points[0], vup, w->points[0]); + + VectorAdd (org, vright, w->points[1]); + VectorAdd (w->points[1], vup, w->points[1]); + + VectorAdd (org, vright, w->points[2]); + VectorSubtract (w->points[2], vup, w->points[2]); + + VectorSubtract (org, vright, w->points[3]); + VectorSubtract (w->points[3], vup, w->points[3]); + + w->numpoints = 4; + + return w; +} + +/* +================== +ClipWinding + +Clips the winding to the plane, returning the new winding on the positive side +Frees the input winding. +If keepon is true, an exactly on-plane winding will be saved, otherwise +it will be clipped away. +================== +*/ +winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) +{ + vec_t dists[MAX_POINTS_ON_WINDING + 1]; + int sides[MAX_POINTS_ON_WINDING + 1]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *neww; + int maxpts; + + counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; + + // determine sides for each point + for (i = 0;i < in->numpoints;i++) + { + dists[i] = dot = DotProduct (in->points[i], split->normal) - split->dist; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + sides[i] = SIDE_ON; + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (keepon && !counts[0] && !counts[1]) + return in; + + if (!counts[0]) + { + FreeWinding (in); + return NULL; + } + if (!counts[1]) + return in; + + maxpts = in->numpoints+4; // can't use counts[0]+2 because of fp grouping errors + neww = NewWinding (maxpts); + + for (i = 0;i < in->numpoints;i++) + { + p1 = in->points[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, neww->points[neww->numpoints]); + neww->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->points[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j = 0;j < 3;j++) + { // avoid round off error when possible + if (split->normal[j] == 1) + mid[j] = split->dist; + else if (split->normal[j] == -1) + mid[j] = -split->dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, neww->points[neww->numpoints]); + neww->numpoints++; + } + + if (neww->numpoints > maxpts) + Host_Error ("ClipWinding: points exceeded estimate"); + + // free the original winding + FreeWinding (in); + + return neww; +} + + +/* +================== +DivideWinding + +Divides a winding by a plane, producing one or two windings. The +original winding is not damaged or freed. If only on one side, the +returned winding will be the input winding. If on both sides, two +new windings will be created. +================== +*/ +void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING + 1]; + int sides[MAX_POINTS_ON_WINDING + 1]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f, *b; + int maxpts; + + counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; + + // determine sides for each point + for (i = 0;i < in->numpoints;i++) + { + dot = DotProduct (in->points[i], split->normal); + dot -= split->dist; + dists[i] = dot; + if (dot > ON_EPSILON) sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) sides[i] = SIDE_BACK; + else sides[i] = SIDE_ON; + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) + { + *back = in; + return; + } + if (!counts[1]) + { + *front = in; + return; + } + + maxpts = in->numpoints+4; // can't use counts[0]+2 because of fp grouping errors + + *front = f = NewWinding (maxpts); + *back = b = NewWinding (maxpts); + + for (i = 0;i < in->numpoints;i++) + { + p1 = in->points[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->points[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->points[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->points[f->numpoints]); + f->numpoints++; + } + else if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->points[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->points[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j = 0;j < 3;j++) + { // avoid round off error when possible + if (split->normal[j] == 1) + mid[j] = split->dist; + else if (split->normal[j] == -1) + mid[j] = -split->dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->points[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->points[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Host_Error ("DivideWinding: points exceeded estimate"); +} + +typedef struct portal_s +{ + mplane_t plane; + mnode_t *nodes[2]; // [0] = front side of plane + struct portal_s *next[2]; + winding_t *winding; + struct portal_s *chain; // all portals are linked into a list +} +portal_t; + +static portal_t *portalchain; + +/* +=========== +AllocPortal +=========== +*/ +portal_t *AllocPortal (void) +{ + portal_t *p; + p = malloc(sizeof(portal_t)); + memset(p, 0, sizeof(portal_t)); + p->chain = portalchain; + portalchain = p; + return p; +} + +void Mod_FinalizePortals() +{ + int i, j, numportals, numpoints; + portal_t *p, *pnext; + mportal_t *portal; + mvertex_t *point; + p = portalchain; + numportals = 0; + numpoints = 0; + while(p) + { + if (p->winding && p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID) + { + numportals += 2; + numpoints += p->winding->numpoints * 2; + } + p = p->chain; + } + loadmodel->portals = Hunk_AllocName(numportals * sizeof(mportal_t), va("%s portals", loadmodel->name)); + loadmodel->numportals = numportals; + loadmodel->portalpoints = Hunk_AllocName(numpoints * sizeof(mvertex_t), va("%s portals", loadmodel->name)); + loadmodel->numportalpoints = numpoints; + // clear all leaf portal chains + for (i = 0;i < loadmodel->numleafs;i++) + loadmodel->leafs[i].portals = NULL; + // process all portals in the global portal chain, while freeing them + portal = loadmodel->portals; + point = loadmodel->portalpoints; + p = portalchain; + portalchain = NULL; + while (p) + { + pnext = p->chain; + + if (p->winding) + { + // the nodes[0] != nodes[1] check is because leaf 0 is the shared solid leaf, it can have many portals inside with leaf 0 on both sides + if (p->nodes[0] != p->nodes[1] && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID) + { + // first make the back to front portal (forward portal) + portal->points = point; + portal->numpoints = p->winding->numpoints; + portal->plane.dist = p->plane.dist; + VectorCopy(p->plane.normal, portal->plane.normal); + portal->here = (mleaf_t *)p->nodes[1]; + portal->past = (mleaf_t *)p->nodes[0]; + // copy points + for (j = 0;j < portal->numpoints;j++) + { + VectorCopy(p->winding->points[j], point->position); + point++; + } + + // link into leaf's portal chain + portal->next = portal->here->portals; + portal->here->portals = portal; + + // advance to next portal + portal++; + + // then make the front to back portal (backward portal) + portal->points = point; + portal->numpoints = p->winding->numpoints; + portal->plane.dist = -p->plane.dist; + VectorNegate(p->plane.normal, portal->plane.normal); + portal->here = (mleaf_t *)p->nodes[0]; + portal->past = (mleaf_t *)p->nodes[1]; + // copy points + for (j = portal->numpoints - 1;j >= 0;j--) + { + VectorCopy(p->winding->points[j], point->position); + point++; + } + + // link into leaf's portal chain + portal->next = portal->here->portals; + portal->here->portals = portal; + + // advance to next portal + portal++; + } + FreeWinding(p->winding); + } + free(p); + p = pnext; + } +} + +/* +============= +AddPortalToNodes +============= +*/ +void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back) +{ + if (!front) + Host_Error ("AddPortalToNodes: NULL front node"); + if (!back) + Host_Error ("AddPortalToNodes: NULL back node"); + if (p->nodes[0] || p->nodes[1]) + Host_Error ("AddPortalToNodes: already included"); + // note: front == back is handled gracefully, because leaf 0 is the shared solid leaf, it can often have portals with the same leaf on both sides + + p->nodes[0] = front; + p->next[0] = (portal_t *)front->portals; + front->portals = (mportal_t *)p; + + p->nodes[1] = back; + p->next[1] = (portal_t *)back->portals; + back->portals = (mportal_t *)p; +} + +/* +============= +RemovePortalFromNode +============= +*/ +void RemovePortalFromNodes(portal_t *portal) +{ + int i; + mnode_t *node; + void **portalpointer; + portal_t *t; + for (i = 0;i < 2;i++) + { + node = portal->nodes[i]; + + portalpointer = &node->portals; + while (1) + { + t = *portalpointer; + if (!t) + Host_Error ("RemovePortalFromNodes: portal not in leaf"); + + if (t == portal) + { + if (portal->nodes[0] == node) + { + *portalpointer = portal->next[0]; + portal->nodes[0] = NULL; + } + else if (portal->nodes[1] == node) + { + *portalpointer = portal->next[1]; + portal->nodes[1] = NULL; + } + else + Host_Error ("RemovePortalFromNodes: portal not bounding leaf"); + break; + } + + if (t->nodes[0] == node) + portalpointer = &t->next[0]; + else if (t->nodes[1] == node) + portalpointer = &t->next[1]; + else + Host_Error ("RemovePortalFromNodes: portal not bounding leaf"); + } + } +} + +void Mod_RecursiveNodePortals (mnode_t *node) +{ + int side; + mnode_t *front, *back, *other_node; + mplane_t clipplane, *plane; + portal_t *portal, *nextportal, *nodeportal, *splitportal, *temp; + winding_t *nodeportalwinding, *frontwinding, *backwinding; + + // CheckLeafPortalConsistancy (node); + + // if a leaf, we're done + if (node->contents) + return; + + plane = node->plane; + + front = node->children[0]; + back = node->children[1]; + if (front == back) + Host_Error("Mod_RecursiveNodePortals: corrupt node hierarchy"); + + // create the new portal by generating a polygon for the node plane, + // and clipping it by all of the other portals (which came from nodes above this one) + nodeportal = AllocPortal (); + nodeportal->plane = *node->plane; + + nodeportalwinding = BaseWindingForPlane (node->plane); + side = 0; // shut up compiler warning + for (portal = (portal_t *)node->portals;portal;portal = portal->next[side]) + { + clipplane = portal->plane; + if (portal->nodes[0] == portal->nodes[1]) + Host_Error("Mod_RecursiveNodePortals: portal has same node on both sides (1)"); + if (portal->nodes[0] == node) + side = 0; + else if (portal->nodes[1] == node) + { + clipplane.dist = -clipplane.dist; + VectorNegate (clipplane.normal, clipplane.normal); + side = 1; + } + else + Host_Error ("Mod_RecursiveNodePortals: mislinked portal"); + + nodeportalwinding = ClipWinding (nodeportalwinding, &clipplane, true); + if (!nodeportalwinding) + { + printf ("Mod_RecursiveNodePortals: WARNING: new portal was clipped away\n"); + break; + } + } + + if (nodeportalwinding) + { + // if the plane was not clipped on all sides, there was an error + nodeportal->winding = nodeportalwinding; + AddPortalToNodes (nodeportal, front, back); + } + + // split the portals of this node along this node's plane and assign them to the children of this node + // (migrating the portals downward through the tree) + for (portal = (portal_t *)node->portals;portal;portal = nextportal) + { + if (portal->nodes[0] == portal->nodes[1]) + Host_Error("Mod_RecursiveNodePortals: portal has same node on both sides (2)"); + if (portal->nodes[0] == node) + side = 0; + else if (portal->nodes[1] == node) + side = 1; + else + Host_Error ("Mod_RecursiveNodePortals: mislinked portal"); + nextportal = portal->next[side]; + + other_node = portal->nodes[!side]; + RemovePortalFromNodes (portal); + + // cut the portal into two portals, one on each side of the node plane + DivideWinding (portal->winding, plane, &frontwinding, &backwinding); + + if (!frontwinding) + { + if (side == 0) + AddPortalToNodes (portal, back, other_node); + else + AddPortalToNodes (portal, other_node, back); + continue; + } + if (!backwinding) + { + if (side == 0) + AddPortalToNodes (portal, front, other_node); + else + AddPortalToNodes (portal, other_node, front); + continue; + } + + // the winding is split + splitportal = AllocPortal (); + temp = splitportal->chain; + *splitportal = *portal; + splitportal->chain = temp; + splitportal->winding = backwinding; + FreeWinding (portal->winding); + portal->winding = frontwinding; + + if (side == 0) + { + AddPortalToNodes (portal, front, other_node); + AddPortalToNodes (splitportal, back, other_node); + } + else + { + AddPortalToNodes (portal, other_node, front); + AddPortalToNodes (splitportal, other_node, back); + } + } + + Mod_RecursiveNodePortals(front); + Mod_RecursiveNodePortals(back); +} + +/* +void Mod_MakeOutsidePortals(mnode_t *node) +{ + int i, j; + portal_t *p, *portals[6]; + mnode_t *outside_node; + + outside_node = Hunk_AllocName(sizeof(mnode_t), loadmodel->name); + outside_node->contents = CONTENTS_SOLID; + outside_node->portals = NULL; + + for (i = 0;i < 3;i++) + { + for (j = 0;j < 2;j++) + { + portals[j*3 + i] = p = AllocPortal (); + memset (&p->plane, 0, sizeof(mplane_t)); + p->plane.normal[i] = j ? -1 : 1; + p->plane.dist = -65536; + p->winding = BaseWindingForPlane (&p->plane); + if (j) + AddPortalToNodes (p, outside_node, node); + else + AddPortalToNodes (p, node, outside_node); + } + } + + // clip the basewindings by all the other planes + for (i = 0;i < 6;i++) + { + for (j = 0;j < 6;j++) + { + if (j == i) + continue; + portals[i]->winding = ClipWinding (portals[i]->winding, &portals[j]->plane, true); + } + } +} +*/ + +void Mod_MakePortals() +{ +// Con_Printf("building portals for %s\n", loadmodel->name); + + portalchain = NULL; +// Mod_MakeOutsidePortals (loadmodel->nodes); + Mod_RecursiveNodePortals (loadmodel->nodes); + Mod_FinalizePortals(); +} + /* ================= Mod_LoadBrushModel @@ -1226,13 +1874,15 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); Mod_MakeHull0 (); + + Mod_MakePortals(); mod->numframes = 2; // regular and alternate animation // // set up the submodels (FIXME: this is confusing) // - for (i=0 ; inumsubmodels ; i++) + for (i = 0;i < mod->numsubmodels;i++) { bm = &mod->submodels[i]; @@ -1240,7 +1890,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) for (j=1 ; jhulls[j].firstclipnode = bm->headnode[j]; - mod->hulls[j].lastclipnode = mod->numclipnodes-1; + mod->hulls[j].lastclipnode = mod->numclipnodes - 1; } mod->firstmodelsurface = bm->firstface; @@ -1253,7 +1903,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod->numleafs = bm->visleafs; - if (isworldmodel && i < (mod->numsubmodels-1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels) + if (isworldmodel && i < (mod->numsubmodels - 1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels) { // duplicate the basic information char name[10]; diff --git a/model_brush.h b/model_brush.h index 33b05069..c88f1095 100644 --- a/model_brush.h +++ b/model_brush.h @@ -30,7 +30,6 @@ BRUSH MODELS // // in memory representation // -// !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vec3_t position; @@ -46,24 +45,21 @@ typedef struct mplane_s { vec3_t normal; float dist; - byte type; // for texture axis selection and fast side tests - byte pad[3]; + int type; // for texture axis selection and fast side tests + // LordHavoc: faster than id's signbits system int (*BoxOnPlaneSideFunc) (vec3_t emins, vec3_t emaxs, struct mplane_s *p); } mplane_t; typedef struct texture_s { - char name[16]; - unsigned width, height; - rtexture_t *texture; - rtexture_t *glowtexture; // LordHavoc: fullbrights on walls - struct msurface_s *texturechain; // for gl_texsort drawing - int anim_total; // total tenths in sequence ( 0 = no) - int anim_min, anim_max; // time for this frame min <=time< max - struct texture_s *anim_next; // in the animation sequence - struct texture_s *alternate_anims; // bmodels in frame 1 use these - unsigned offsets[MIPLEVELS]; // four mip maps stored - int transparent; // LordHavoc: transparent texture support + char name[16]; + unsigned width, height; + rtexture_t *texture; + rtexture_t *glowtexture; // LordHavoc: fullbrights on walls + int anim_total; // total frames in sequence (0 = not animated) + struct texture_s *anim_frames[10]; // LordHavoc: direct pointers to each of the frames in the sequence + struct texture_s *alternate_anims; // bmodels in frame 1 use these + int transparent; // LordHavoc: transparent texture support } texture_t; @@ -80,17 +76,14 @@ typedef struct texture_s // LordHavoc: light both sides #define SURF_LIGHTBOTHSIDES 0x400 -// !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { unsigned short v[2]; - unsigned int cachededgeoffset; } medge_t; typedef struct { float vecs[2][4]; - float mipadjust; texture_t *texture; int flags; } mtexinfo_t; @@ -123,7 +116,6 @@ typedef struct msurface_s short light_s, light_t; // gl lightmap coordinates glpoly_t *polys; // multiple if warped - struct msurface_s *texturechain; mtexinfo_t *texinfo; @@ -148,16 +140,14 @@ typedef struct mnode_s { // common with leaf int contents; // 0, to differentiate from leafs - int visframe; // node needs to be traversed if current - int lightframe; // LordHavoc: to avoid redundent parent chasing in R_VisMarkLights - - float minmaxs[6]; // for bounding box culling + int vismarkframe; // node needs to be traversed if current (r_vismarkframecount) - struct mnode_s *parent; + // for bounding box culling + vec3_t mins; + vec3_t maxs; - // LordHavoc: node based dynamic lighting - int dlightbits[8]; - int dlightframe; + struct mnode_s *parent; + struct mportal_s *portals; // node specific mplane_t *plane; @@ -173,24 +163,28 @@ typedef struct mleaf_s { // common with node int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current - int lightframe; // LordHavoc: to avoid redundent parent chasing in R_VisMarkLights + int vismarkframe; // node needs to be traversed if current (r_vismarkframecount) - float minmaxs[6]; // for bounding box culling + // for bounding box culling + vec3_t mins; + vec3_t maxs; struct mnode_s *parent; + struct mportal_s *portals; - // LordHavoc: node based dynamic lighting +// 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 + + // LordHavoc: leaf based dynamic lighting int dlightbits[8]; int dlightframe; -// leaf specific byte *compressed_vis; - efrag_t *efrags; +// efrag_t *efrags; msurface_t **firstmarksurface; int nummarksurfaces; - int key; // BSP sequence number for leaf's contents byte ambient_sound_level[NUM_AMBIENTS]; } mleaf_t; @@ -203,3 +197,17 @@ typedef struct vec3_t clip_mins; vec3_t clip_maxs; } hull_t; + +typedef struct mportal_s +{ + struct mportal_s *next; // the next portal on this leaf + mleaf_t *here; // the leaf this portal is on + mleaf_t *past; // the leaf through this portal (infront) + mvertex_t *points; + int numpoints; + mplane_t plane; +} +mportal_t; + +extern rtexture_t *r_notexture; +extern texture_t r_notexture_mip; diff --git a/model_shared.h b/model_shared.h index 1d50a07b..d5af37ad 100644 --- a/model_shared.h +++ b/model_shared.h @@ -118,6 +118,12 @@ typedef struct model_s byte *lightdata; char *entities; + int numportals; + mportal_t *portals; + + int numportalpoints; + mvertex_t *portalpoints; + // LordHavoc: useful for sprites and models int numtris; int numskins; diff --git a/quakedef.h b/quakedef.h index 7b67999a..f698972a 100644 --- a/quakedef.h +++ b/quakedef.h @@ -225,7 +225,9 @@ extern int buildnumber; typedef struct { char *basedir; +#if CACHEENABLE char *cachedir; // for development over ISDN lines +#endif int argc; char **argv; void *membase; diff --git a/r_decals.c b/r_decals.c index cea29fdb..9cfe99fd 100644 --- a/r_decals.c +++ b/r_decals.c @@ -67,49 +67,55 @@ void R_Decals_Init() R_RegisterModule("R_Decals", r_decals_start, r_decals_shutdown, r_decals_newmap); } -void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha) +// these are static globals only to avoid putting unnecessary things on the stack +static vec3_t decalorg; +static float decalbestdist; +static msurface_t *decalbestsurf; +static int decalbestlightmapofs; +void R_RecursiveDecalSurface (mnode_t *node) { - int i, ds, dt, bestlightmapofs; - float bestdist, dist; - vec3_t impact, right, up; - decal_t *decal; -// mleaf_t *leaf; - msurface_t *surf/*, **mark, **endmark*/, *bestsurf; - - if (alpha < 1) + // these are static because only one occurance of them need exist at once, so avoid putting them on the stack + static float ndist, dist; + static msurface_t *surf, *endsurf; + static vec3_t impact; + static int ds, dt; + +loc0: + if (node->contents < 0) return; -// leaf = Mod_PointInLeaf(org, cl.worldmodel); -// if (!leaf->nummarksurfaces) -// return; - -// mark = leaf->firstmarksurface; -// endmark = mark + leaf->nummarksurfaces; + ndist = PlaneDiff(decalorg, node->plane); + + if (ndist > 16) + { + node = node->children[0]; + goto loc0; + } + if (ndist < -16) + { + node = node->children[1]; + goto loc0; + } - // find the best surface to place the decal on - bestsurf = NULL; - bestdist = 16; - bestlightmapofs = 0; -// while(mark < endmark) -// { -// surf = *mark++; - surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; - for (i = 0;i < cl.worldmodel->nummodelsurfaces;i++, surf++) +// mark the polygons + surf = cl.worldmodel->surfaces + node->firstsurface; + endsurf = surf + node->numsurfaces; + for (;surf < endsurf;surf++) { if (surf->flags & SURF_DRAWTILED) continue; // no lightmaps - dist = PlaneDiff(org, surf->plane); + dist = PlaneDiff(decalorg, surf->plane); if (surf->flags & SURF_PLANEBACK) dist = -dist; if (dist < 0) continue; - if (dist >= bestdist) + if (dist >= decalbestdist) continue; - impact[0] = org[0] - surf->plane->normal[0] * dist; - impact[1] = org[1] - surf->plane->normal[1] * dist; - impact[2] = org[2] - surf->plane->normal[2] * dist; + impact[0] = decalorg[0] - surf->plane->normal[0] * dist; + impact[1] = decalorg[1] - surf->plane->normal[1] * dist; + impact[2] = decalorg[2] - surf->plane->normal[2] * dist; ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]); dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]); @@ -123,12 +129,50 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int if (ds > surf->extents[0] || dt > surf->extents[1]) continue; - bestsurf = surf; - bestdist = dist; - bestlightmapofs = (dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4); + decalbestsurf = surf; + decalbestdist = dist; + decalbestlightmapofs = (dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4); + } + + if (node->children[0]->contents >= 0) + { + if (node->children[1]->contents >= 0) + { + R_RecursiveDecalSurface (node->children[0]); + node = node->children[1]; + goto loc0; + } + else + { + node = node->children[0]; + goto loc0; + } + } + else if (node->children[1]->contents >= 0) + { + node = node->children[1]; + goto loc0; } +} + +void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha) +{ + vec3_t center, right, up; + decal_t *decal; + + if (alpha < 1) + return; + + // find the best surface to place the decal on + decalbestsurf = NULL; + decalbestdist = 16; + decalbestlightmapofs = 0; + VectorCopy(org, decalorg); + + R_RecursiveDecalSurface (cl.worldmodel->nodes); + // abort if no suitable surface was found - if (bestsurf == NULL) + if (decalbestsurf == NULL) return; // grab a decal from the array and advance to the next decal to replace, wrapping to replace an old decal if necessary @@ -137,53 +181,49 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int if (currentdecal >= MAX_DECALS) currentdecal = 0; decal->tex = tex; + VectorCopy(decalbestsurf->plane->normal, decal->direction); // reverse direction - if (bestsurf->flags & SURF_PLANEBACK) - { - VectorCopy(bestsurf->plane->normal, decal->direction); - } - else - { - VectorNegate(bestsurf->plane->normal, decal->direction); - } - // - 0.25 to push it off the surface a bit - decal->org[0] = impact[0] = org[0] + decal->direction[0] * (bestdist - 0.25f); - decal->org[1] = impact[1] = org[1] + decal->direction[1] * (bestdist - 0.25f); - decal->org[2] = impact[2] = org[2] + decal->direction[2] * (bestdist - 0.25f); + if (decalbestsurf->flags & SURF_PLANEBACK) + VectorNegate(decal->direction, decal->direction); + VectorNegate(decal->direction, decal->direction); + // 0.25 to push it off the surface a bit + decalbestdist -= 0.25f; + decal->org[0] = center[0] = org[0] + decal->direction[0] * decalbestdist; + decal->org[1] = center[1] = org[1] + decal->direction[1] * decalbestdist; + decal->org[2] = center[2] = org[2] + decal->direction[2] * decalbestdist; // set up the 4 corners scale *= 0.5f; VectorVectors(decal->direction, right, up); - decal->vert[0][0] = impact[0] - up[0] * scale - right[0] * scale; - decal->vert[0][1] = impact[1] - up[1] * scale - right[1] * scale; - decal->vert[0][2] = impact[2] - up[2] * scale - right[2] * scale; - decal->vert[1][0] = impact[0] + up[0] * scale - right[0] * scale; - decal->vert[1][1] = impact[1] + up[1] * scale - right[1] * scale; - decal->vert[1][2] = impact[2] + up[2] * scale - right[2] * scale; - decal->vert[2][0] = impact[0] + up[0] * scale + right[0] * scale; - decal->vert[2][1] = impact[1] + up[1] * scale + right[1] * scale; - decal->vert[2][2] = impact[2] + up[2] * scale + right[2] * scale; - decal->vert[3][0] = impact[0] - up[0] * scale + right[0] * scale; - decal->vert[3][1] = impact[1] - up[1] * scale + right[1] * scale; - decal->vert[3][2] = impact[2] - up[2] * scale + right[2] * scale; + decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; // texcoords 0 1 + decal->vert[0][1] = center[1] - right[1] * scale - up[1] * scale; + decal->vert[0][2] = center[2] - right[2] * scale - up[2] * scale; + decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale; // texcoords 0 0 + decal->vert[1][1] = center[1] - right[1] * scale + up[1] * scale; + decal->vert[1][2] = center[2] - right[2] * scale + up[2] * scale; + decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale; // texcoords 1 0 + decal->vert[2][1] = center[1] + right[1] * scale + up[1] * scale; + decal->vert[2][2] = center[2] + right[2] * scale + up[2] * scale; + decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale; // texcoords 1 1 + decal->vert[3][1] = center[1] + right[1] * scale - up[1] * scale; + decal->vert[3][2] = center[2] + right[2] * scale - up[2] * scale; // store the color decal->color[0] = (byte) bound(0, cred, 255); decal->color[1] = (byte) bound(0, cgreen, 255); decal->color[2] = (byte) bound(0, cblue, 255); decal->color[3] = (byte) bound(0, alpha, 255); // store the surface information for lighting - decal->surface = bestsurf; - decal->lightmapstep = ((bestsurf->extents[0]>>4)+1) * ((bestsurf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting - if (bestsurf->samples) - decal->lightmapaddress = bestsurf->samples + bestlightmapofs * 3; // LordHavoc: *3 for colored lighitng + decal->surface = decalbestsurf; + decal->lightmapstep = ((decalbestsurf->extents[0]>>4)+1) * ((decalbestsurf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting + if (decalbestsurf->samples) + decal->lightmapaddress = decalbestsurf->samples + decalbestlightmapofs * 3; // LordHavoc: *3 for colored lighitng else decal->lightmapaddress = NULL; } -void R_DrawDecals (void) +void GL_DrawDecals (void) { decal_t *p; - int i, j, k, dynamiclight, ir, ig, ib, maps, bits; - byte br, bg, bb, ba; + int i, j, k, dynamiclight, bits, texnum; float scale, fr, fg, fb, dist, rad, mindist; byte *lightmap; vec3_t v; @@ -197,10 +237,24 @@ void R_DrawDecals (void) mindist = DotProduct(r_refdef.vieworg, vpn) + 4.0f; + if (r_render.value) + { + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnable(GL_BLEND); + glShadeModel(GL_FLAT); + glDepthMask(0); // disable zbuffer updates + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + texnum = -1; + for (i = 0, p = decals;i < MAX_DECALS;i++, p++) { if (p->tex == NULL) break; + // skip decals on surfaces that aren't visible in this frame + if (p->surface->visframe != r_framecount) + continue; // do not render if the decal is behind the view if (DotProduct(p->org, vpn) < mindist) @@ -217,22 +271,52 @@ void R_DrawDecals (void) fr = fg = fb = 0.0f; if (lightmap) { - for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) + if (surf->styles[0] != 255) + { + scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f); + fr += lightmap[0] * scale; + fg += lightmap[1] * scale; + fb += lightmap[2] * scale; + if (surf->styles[1] != 255) + { + lightmap += p->lightmapstep; + scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f); + fr += lightmap[0] * scale; + fg += lightmap[1] * scale; + fb += lightmap[2] * scale; + if (surf->styles[2] != 255) + { + lightmap += p->lightmapstep; + scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f); + fr += lightmap[0] * scale; + fg += lightmap[1] * scale; + fb += lightmap[2] * scale; + if (surf->styles[3] != 255) + { + lightmap += p->lightmapstep; + scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f); + fr += lightmap[0] * scale; + fg += lightmap[1] * scale; + fb += lightmap[2] * scale; + } + } + } + } + /* + for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++) { - scale = d_lightstylevalue[surf->styles[maps]]; + scale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f); fr += lightmap[0] * scale; fg += lightmap[1] * scale; fb += lightmap[2] * scale; lightmap += p->lightmapstep; } + */ } - fr *= (1.0f / 256.0f); - fg *= (1.0f / 256.0f); - fb *= (1.0f / 256.0f); // dynamic lighting if (dynamiclight) { - if (surf->dlightframe == r_dlightframecount) + if (surf->dlightframe == r_framecount) { for (j = 0;j < 8;j++) { @@ -260,21 +344,58 @@ void R_DrawDecals (void) } } } - // apply color to lighting - ir = (int) (fr * p->color[0] * (1.0f / 128.0f)); - ig = (int) (fg * p->color[1] * (1.0f / 128.0f)); - ib = (int) (fb * p->color[2] * (1.0f / 128.0f)); - // compute byte color - br = (byte) min(ir, 255); - bg = (byte) min(ig, 255); - bb = (byte) min(ib, 255); - ba = p->color[3]; - // put into transpoly system for sorted drawing later - transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), TPOLYTYPE_ALPHA); - transpolyvertub(p->vert[0][0], p->vert[0][1], p->vert[0][2], 0,1,br,bg,bb,ba); - transpolyvertub(p->vert[1][0], p->vert[1][1], p->vert[1][2], 0,0,br,bg,bb,ba); - transpolyvertub(p->vert[2][0], p->vert[2][1], p->vert[2][2], 1,0,br,bg,bb,ba); - transpolyvertub(p->vert[3][0], p->vert[3][1], p->vert[3][2], 1,1,br,bg,bb,ba); - transpolyend(); + /* + { + int ir, ig, ib; + byte br, bg, bb, ba; + // apply color to lighting + ir = (int) (fr * p->color[0] * (1.0f / 128.0f)); + ig = (int) (fg * p->color[1] * (1.0f / 128.0f)); + ib = (int) (fb * p->color[2] * (1.0f / 128.0f)); + // compute byte color + br = (byte) min(ir, 255); + bg = (byte) min(ig, 255); + bb = (byte) min(ib, 255); + ba = p->color[3]; + // put into transpoly system for sorted drawing later + transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), TPOLYTYPE_ALPHA); + transpolyvertub(p->vert[0][0], p->vert[0][1], p->vert[0][2], 0,1,br,bg,bb,ba); + transpolyvertub(p->vert[1][0], p->vert[1][1], p->vert[1][2], 0,0,br,bg,bb,ba); + transpolyvertub(p->vert[2][0], p->vert[2][1], p->vert[2][2], 1,0,br,bg,bb,ba); + transpolyvertub(p->vert[3][0], p->vert[3][1], p->vert[3][2], 1,1,br,bg,bb,ba); + transpolyend(); + } + */ + if (r_render.value) + { + j = R_GetTexture(p->tex); + if (texnum != j) + { + glEnd(); + texnum = j; + glBindTexture(GL_TEXTURE_2D, texnum); + glBegin(GL_QUADS); + } + if (lighthalf) + glColor4f(fr * p->color[0] * (1.0f / 255.0f / 256.0f), fg * p->color[1] * (1.0f / 255.0f / 256.0f), fb * p->color[2] * (1.0f / 255.0f / 256.0f), p->color[3] * (1.0f / 255.0f)); + else + glColor4f(fr * p->color[0] * (1.0f / 255.0f / 128.0f), fg * p->color[1] * (1.0f / 255.0f / 128.0f), fb * p->color[2] * (1.0f / 255.0f / 128.0f), p->color[3] * (1.0f / 255.0f)); + glTexCoord2f(0, 1); + glVertex3fv(p->vert[0]); + glTexCoord2f(0, 0); + glVertex3fv(p->vert[1]); + glTexCoord2f(1, 0); + glVertex3fv(p->vert[2]); + glTexCoord2f(1, 1); + glVertex3fv(p->vert[3]); + } + } + + if (r_render.value) + { + glEnd(); + + glDepthMask(1); // enable zbuffer updates + glDisable(GL_ALPHA_TEST); } } diff --git a/r_decals.h b/r_decals.h index d0aedc5b..8a54e8d9 100644 --- a/r_decals.h +++ b/r_decals.h @@ -1,6 +1,6 @@ void R_Decals_Init(); -void R_DrawDecals(); +void GL_DrawDecals(); void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha); diff --git a/r_light.c b/r_light.c index 2c4d2d0d..8f7b9837 100644 --- a/r_light.c +++ b/r_light.c @@ -43,8 +43,6 @@ void R_Light_Init() R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap); } -int r_dlightframecount; - /* ================== R_AnimateLight @@ -89,6 +87,7 @@ void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex { float ndist, maxdist; msurface_t *surf; + mleaf_t *leaf; int i; if (!r_dynamic.value) @@ -103,35 +102,32 @@ void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex loc0: if (node->contents < 0) + { + if (node->contents != CONTENTS_SOLID) + { + leaf = (mleaf_t *)node; + if (leaf->dlightframe != r_framecount) // not dynamic until now + { + leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0; + leaf->dlightframe = r_framecount; + } + leaf->dlightbits[bitindex] |= bit; + } return; + } ndist = PlaneDiff(lightorigin, node->plane); if (ndist > light->radius) { - if (node->children[0]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame - { - node = node->children[0]; - goto loc0; - } - return; + node = node->children[0]; + goto loc0; } if (ndist < -light->radius) { - if (node->children[1]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame - { - node = node->children[1]; - goto loc0; - } - return; - } - - if (node->dlightframe != r_dlightframecount) // not dynamic until now - { - node->dlightbits[0] = node->dlightbits[1] = node->dlightbits[2] = node->dlightbits[3] = node->dlightbits[4] = node->dlightbits[5] = node->dlightbits[6] = node->dlightbits[7] = 0; - node->dlightframe = r_dlightframecount; + node = node->children[1]; + goto loc0; } - node->dlightbits[bitindex] |= bit; // mark the polygons surf = cl.worldmodel->surfaces + node->firstsurface; @@ -139,6 +135,8 @@ loc0: { int d; float dist, dist2, impact[3]; + if (surf->visframe != r_framecount) + continue; dist = ndist; if (surf->flags & SURF_PLANEBACK) dist = -dist; @@ -192,20 +190,20 @@ loc0: } } - if (surf->dlightframe != r_dlightframecount) // not dynamic until now + if (surf->dlightframe != r_framecount) // not dynamic until now { surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; - surf->dlightframe = r_dlightframecount; + surf->dlightframe = r_framecount; } surf->dlightbits[bitindex] |= bit; /* if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist)) { - if (surf->dlightframe != r_dlightframecount) // not dynamic until now + if (surf->dlightframe != r_framecount) // not dynamic until now { surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; - surf->dlightframe = r_dlightframecount; + surf->dlightframe = r_framecount; } surf->dlightbits[bitindex] |= bit; } @@ -288,20 +286,19 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex if (c & (1<leafs[(k << 3)+i+1]; - leaf->lightframe = lightframe; - if (leaf->visframe != r_visframecount) + if (leaf->visframe != r_framecount) continue; if (leaf->contents == CONTENTS_SOLID) continue; // if out of the light radius, skip - if (leaf->minmaxs[0] > high[0] || leaf->minmaxs[3] < low[0] - || leaf->minmaxs[1] > high[1] || leaf->minmaxs[4] < low[1] - || leaf->minmaxs[2] > high[2] || leaf->minmaxs[5] < low[2]) + if (leaf->mins[0] > high[0] || leaf->maxs[0] < low[0] + || leaf->mins[1] > high[1] || leaf->maxs[1] < low[1] + || leaf->mins[2] > high[2] || leaf->maxs[2] < low[2]) continue; - if (leaf->dlightframe != r_dlightframecount) // not dynamic until now + if (leaf->dlightframe != r_framecount) // not dynamic until now { leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0; - leaf->dlightframe = r_dlightframecount; + leaf->dlightframe = r_framecount; } leaf->dlightbits[bitindex] |= bit; if ((m = leaf->nummarksurfaces)) @@ -366,10 +363,10 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex } } - if (surf->dlightframe != r_dlightframecount) // not dynamic until now + if (surf->dlightframe != r_framecount) // not dynamic until now { surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0; - surf->dlightframe = r_dlightframecount; + surf->dlightframe = r_framecount; } surf->dlightbits[bitindex] |= bit; } @@ -398,8 +395,6 @@ void R_PushDlights (void) int i; dlight_t *l; - r_dlightframecount = r_framecount + 1; // because the count hasn't advanced yet for this frame - if (!r_dynamic.value) return; @@ -750,7 +745,7 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) color[0] = color[1] = color[2] = r_ambient.value * 2.0f; RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); - if (leaf->dlightframe == r_dlightframecount) + if (leaf->dlightframe == r_framecount) { dlightbits[0] = leaf->dlightbits[0]; dlightbits[1] = leaf->dlightbits[1]; diff --git a/r_light.h b/r_light.h index df11b53b..6e29e589 100644 --- a/r_light.h +++ b/r_light.h @@ -18,5 +18,3 @@ extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic); extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits); extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org); extern void R_LightPoint (vec3_t color, vec3_t p); - -extern int r_dlightframecount; diff --git a/r_part.c b/r_part.c index ed53ba2c..fff8f378 100644 --- a/r_part.c +++ b/r_part.c @@ -1350,6 +1350,7 @@ void R_DrawParticles (void) float scale, scale2, minparticledist; byte *color24; vec3_t uprightangles, up2, right2, tempcolor, corner; + mleaf_t *leaf; // LordHavoc: early out condition if ((!numparticles) || (!r_drawparticles.value)) @@ -1377,6 +1378,11 @@ void R_DrawParticles (void) if (DotProduct(p->org, vpn) < minparticledist) continue; + // LordHavoc: check if it's in a visible leaf + 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 95facc3c..bdc18f50 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -20,12 +20,15 @@ R_DrawSpriteModel */ void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) { - vec3_t right, up, org, color; + vec3_t right, up, org, color, mins, maxs; byte colorub[4]; msprite_t *psprite; - // don't even bother culling, because it's just a single - // polygon without a surface cache + VectorAdd (e->render.origin, e->render.model->mins, mins); + VectorAdd (e->render.origin, e->render.model->maxs, maxs); + + if (R_VisibleCullBox (mins, maxs)) + return; c_sprites++; diff --git a/render.h b/render.h index d67134d3..933a765d 100644 --- a/render.h +++ b/render.h @@ -56,6 +56,7 @@ typedef struct byte glowcolor; byte colormod; byte flags; + byte active; } entity_state_t; typedef struct entity_s @@ -79,7 +80,7 @@ typedef struct entity_s struct model_s *model; // NULL = no model int frame; // current desired frame (usually identical to frame2, but frame2 is not always used) - struct efrag_s *efrag; // linked list of efrags +// struct efrag_s *efrag; // linked list of efrags int colormap; int effects; // light, particles, etc int skinnum; // for Alias models @@ -101,14 +102,11 @@ typedef struct entity_s float trail_time; // FIXME: could turn these into a union // int trivial_accept; - struct mnode_s *topnode; // for bmodels, first world node - // that splits bmodel, or NULL if - // not split +// struct mnode_s *topnode; // for bmodels, first world node that splits bmodel, or NULL if not split } render; } entity_t; -// !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vrect_t vrect; // subwindow in video for refresh @@ -150,20 +148,19 @@ typedef struct extern refdef_t r_refdef; extern vec3_t r_origin, vpn, vright, vup; -extern struct texture_s *r_notexture_mip; - void R_Init (void); -void R_InitTextures (void); -void R_InitEfrags (void); -void R_RenderView (void); // must set r_refdef first -void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); - // called whenever r_refdef or vid change +void R_RenderView (void); // must set r_refdef first +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); // called whenever r_refdef or vid change + // LordHavoc: changed this for sake of GLQuake -void R_InitSky (byte *src, int bytesperpixel); // called at level load -//void R_InitSky (struct texture_s *mt); // called at level load +void R_InitSky (byte *src, int bytesperpixel); // called at level load + +//void R_InitEfrags (void); +//void R_AddEfrags (entity_t *ent); +//void R_RemoveEfrags (entity_t *ent); +//void R_StoreEfrags (efrag_t **ppefrag); -void R_AddEfrags (entity_t *ent); -void R_RemoveEfrags (entity_t *ent); +int R_VisibleCullBox (vec3_t mins, vec3_t maxs); void R_NewMap (void); diff --git a/sbar.c b/sbar.c index 32e1db6d..73e51ca7 100644 --- a/sbar.c +++ b/sbar.c @@ -807,8 +807,6 @@ void Sbar_Draw (void) if (scr_con_current == vid.height) return; // console is full screen - scr_copyeverything = 1; - // sb_updates++; if (sb_lines > 24) @@ -963,9 +961,6 @@ void Sbar_DeathmatchOverlay (void) char num[128]; scoreboard_t *s; - scr_copyeverything = 1; - scr_fullupdate = 0; - pic = Draw_CachePic ("gfx/ranking.lmp"); M_DrawPic ((320-pic->width)/2, 8, pic); @@ -1024,9 +1019,6 @@ void Sbar_MiniDeathmatchOverlay (void) if (vid.width < 512 || !sb_lines) return; - scr_copyeverything = 1; - scr_fullupdate = 0; - // scores Sbar_SortFrags (); @@ -1091,9 +1083,6 @@ void Sbar_IntermissionOverlay (void) int dig; int num; - scr_copyeverything = 1; - scr_fullupdate = 0; - if (cl.gametype == GAME_DEATHMATCH) { Sbar_DeathmatchOverlay (); @@ -1135,8 +1124,6 @@ void Sbar_FinaleOverlay (void) { qpic_t *pic; - scr_copyeverything = 1; - pic = Draw_CachePic ("gfx/finale.lmp"); Draw_Pic ( (vid.width-pic->width)/2, 16, pic); } diff --git a/screen.h b/screen.h index 64e0bc36..58281617 100644 --- a/screen.h +++ b/screen.h @@ -26,18 +26,14 @@ void SCR_UpdateScreen (void); void SCR_SizeUp (void); void SCR_SizeDown (void); -void SCR_BringDownConsole (void); void SCR_CenterPrint (char *str); -void SCR_BeginLoadingPlaque (void); -void SCR_EndLoadingPlaque (void); - -int SCR_ModalMessage (char *text); +//void SCR_BeginLoadingPlaque (void); +//void SCR_EndLoadingPlaque (void); extern float scr_con_current; extern float scr_conlines; // lines of console to display -extern int scr_fullupdate; // set to 0 to force full redraw extern int sb_lines; extern int clearnotify; // set to 0 whenever notify text is drawn @@ -47,9 +43,3 @@ extern qboolean scr_skipupdate; extern cvar_t scr_viewsize; extern cvar_t scr_viewsize; - -// only the refresh window will be updated unless these variables are flagged -extern int scr_copytop; -extern int scr_copyeverything; - -void SCR_UpdateWholeScreen (void); diff --git a/server.h b/server.h index 4eada814..426291af 100644 --- a/server.h +++ b/server.h @@ -197,8 +197,6 @@ extern client_t *host_client; extern jmp_buf host_abortserver; -extern double host_time; - extern edict_t *sv_player; //=========================================================== diff --git a/snd_dma.c b/snd_dma.c index 4f760acc..d8001f4f 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -680,26 +680,23 @@ void S_UpdateAmbientSounds (void) int ambient_channel; channel_t *chan; - if (!snd_ambient) - return; + // LordHavoc: kill ambient sounds until proven otherwise + for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++) + channels[ambient_channel].sfx = NULL; -// calc ambient sound levels - if (!cl.worldmodel) + if (!snd_ambient || !cl.worldmodel || ambient_level.value <= 0) return; l = Mod_PointInLeaf (listener_origin, cl.worldmodel); - if (!l || !ambient_level.value) - { - for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) - channels[ambient_channel].sfx = NULL; + if (!l) return; - } +// calc ambient sound levels for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { chan = &channels[ambient_channel]; chan->sfx = ambient_sfx[ambient_channel]; - + vol = ambient_level.value * l->ambient_sound_level[ambient_channel]; if (vol < 8) vol = 0; diff --git a/sv_main.c b/sv_main.c index 59da2be2..92276c2b 100644 --- a/sv_main.c +++ b/sv_main.c @@ -463,10 +463,10 @@ SV_WriteEntitiesToClient */ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) { - int e, i, clentnum, bits, alpha, glowcolor, glowsize, scale, colormod, modred, modgreen, modblue, dodelta, effects; + int e, i, clentnum, bits, alpha, glowcolor, glowsize, scale, colormod, modred, modgreen, modblue, effects; byte *pvs; vec3_t org, origin, angles; - float movelerp, moveilerp; + float movelerp, moveilerp, nextfullupdate; edict_t *ent; eval_t *val; entity_state_t *baseline; // LordHavoc: delta or startup baseline @@ -489,15 +489,23 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes // send over all entities (except the client) that touch the pvs ent = NEXT_EDICT(sv.edicts); - for (e=1 ; enextfullupdate[e]; + client->nextfullupdate[e] = -1; + if (ent != clent) // LordHavoc: always send player { if ((val = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict) { if (val->edict != clentnum) - continue; // don't show to anyone else + { + // don't show to anyone else + continue; + } else bits |= U_VIEWMODEL; // show relative to the view } @@ -509,12 +517,15 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum) continue; // ignore if not touching a PV leaf - for (i=0 ; i < ent->num_leafs ; i++) + for (i = 0;i < ent->num_leafs;i++) if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i]&7) )) break; if (i == ent->num_leafs) - continue; // not visible + { + // not visible + continue; + } } } @@ -582,29 +593,35 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (msg->maxsize - msg->cursize < 32) // LordHavoc: increased check from 16 to 32 { Con_Printf ("packet overflow\n"); + // mark the rest of the entities so they can't be delta compressed against this frame + for (;e < sv.num_edicts;e++) + client->nextfullupdate[e] = -1; return; } // send an update - bits = 0; + baseline = &ent->baseline; - dodelta = false; if ((int)ent->v.effects & EF_DELTA) - dodelta = realtime < client->nextfullupdate[e]; // every half second a full update is forced - - if (dodelta) { - bits |= U_DELTA; - baseline = &ent->deltabaseline; + // every half second a full update is forced + if (realtime < client->nextfullupdate[e]) + { + bits |= U_DELTA; + baseline = &ent->deltabaseline; + } + else + nextfullupdate = realtime + 0.5f; } else - { - client->nextfullupdate[e] = realtime + 0.5; - baseline = &ent->baseline; - } + nextfullupdate = realtime + 0.5f; + + // restore nextfullupdate since this is being sent + client->nextfullupdate[e] = nextfullupdate; if (e >= 256) bits |= U_LONGENTITY; + if (ent->v.movetype == MOVETYPE_STEP) bits |= U_STEP; diff --git a/sv_phys.c b/sv_phys.c index 06ed1185..7d647953 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -1154,11 +1154,14 @@ SV_Physics_None Non moving objects can only think ============= */ +// LordHavoc: inlined manually because it was a real time waster +/* void SV_Physics_None (edict_t *ent) { // regular thinking SV_RunThink (ent); } +*/ /* ============= @@ -1431,7 +1434,10 @@ void SV_Physics (void) SV_Physics_Pusher (ent); break; case MOVETYPE_NONE: - SV_Physics_None (ent); +// SV_Physics_None (ent); + // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects + if (ent->v.nextthink > 0 && ent->v.nextthink <= sv.time + sv.frametime) + SV_RunThink (ent); break; case MOVETYPE_FOLLOW: SV_Physics_Follow (ent); diff --git a/sys.h b/sys.h index 958037fe..0df1b9b6 100644 --- a/sys.h +++ b/sys.h @@ -39,7 +39,9 @@ void Sys_mkdir (char *path); // // memory protection // +#if NOTUSED void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length); +#endif // // system IO diff --git a/sys_linux.c b/sys_linux.c index 4f611f98..d01fcf70 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -26,9 +26,13 @@ qboolean isDedicated; int nostdout = 0; char *basedir = "."; +#if CACHEENABLE char *cachedir = "/tmp"; +#endif +#if NOTUSED cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display +#endif extern cvar_t timestamps; extern cvar_t timeformat; @@ -307,6 +311,7 @@ void Sys_DebugLog(char *file, char *fmt, ...) close(fd); } +#if NOTUSED void Sys_EditFile(char *filename) { @@ -327,8 +332,8 @@ void Sys_EditFile(char *filename) sprintf(cmd, "xterm -e %s %s", editor, filename); system(cmd); } - } +#endif double Sys_FloatTime (void) { @@ -358,9 +363,11 @@ void alarm_handler(int x) oktogo=1; } +#if NOTUSED void Sys_LineRefresh(void) { } +#endif void floating_point_exception_handler(int whatever) { @@ -417,8 +424,6 @@ int main (int c, char **v) host_parms.memsize = DEFAULTMEM * 1024*1024; host_parms.basedir = basedir; -// caching is disabled by default, use -cachedir to enable -// host_parms.cachedir = cachedir; fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); @@ -458,14 +463,17 @@ int main (int c, char **v) Host_Frame (time); +#if NOTUSED // graphic debugging aids if (sys_linerefresh.value) Sys_LineRefresh (); +#endif } return 0; } +#if NOTUSED /* ================ Sys_MakeCodeWriteable @@ -489,4 +497,5 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) Sys_Error("Protection change failed\n"); } +#endif diff --git a/sys_win.c b/sys_win.c index 8452c9ae..a7f21401 100644 --- a/sys_win.c +++ b/sys_win.c @@ -212,6 +212,7 @@ SYSTEM IO =============================================================================== */ +#if NOTUSED /* ================ Sys_MakeCodeWriteable @@ -224,6 +225,7 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect)) Sys_Error("Protection change failed\n"); } +#endif /* @@ -643,8 +645,9 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (cwd[strlen(cwd)-1] == '/') cwd[strlen(cwd)-1] = 0; + memset(&host_parms, 0, sizeof(host_parms)); + host_parms.basedir = cwd; - host_parms.cachedir = NULL; host_parms.argc = 1; argv[0] = empty_string; diff --git a/sys_wind.c b/sys_wind.c index 8c15013c..beb27dbd 100644 --- a/sys_wind.c +++ b/sys_wind.c @@ -149,9 +149,11 @@ SYSTEM IO =============================================================================== */ +#if NOTUSED void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) { } +#endif void Sys_DebugLog(char *file, char *fmt, ...) diff --git a/view.c b/view.c index 793fec63..355a8e6e 100644 --- a/view.c +++ b/view.c @@ -855,14 +855,9 @@ void V_RenderView (void) return; if (cl.intermission) - { // intermission / finale rendering V_CalcIntermissionRefdef (); - } else - { - if (!cl.paused /* && (sv.maxclients > 1 || key_dest == key_game) */ ) - V_CalcRefdef (); - } + V_CalcRefdef (); R_RenderView (); } -- 2.39.2