***map loader generates portals for the map*** (can you tell this is a big deal? :)
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 11 May 2001 08:27:05 +0000 (08:27 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 11 May 2001 08:27:05 +0000 (08:27 +0000)
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

42 files changed:
buildnumber.c
cl_demo.c
cl_main.c
cl_parse.c
client.h
common.c
console.c
console.h
gl_models.c
gl_refrag.c [deleted file]
gl_rmain.c
gl_rmisc.c
gl_rsurf.c
gl_screen.c
glquake.h
host.c
host_cmd.c
keys.c
makefile
menu.c
model_brush.c
model_brush.h
model_shared.h
quakedef.h
r_decals.c
r_decals.h
r_light.c
r_light.h
r_part.c
r_sprites.c
render.h
sbar.c
screen.h
server.h
snd_dma.c
sv_main.c
sv_phys.c
sys.h
sys_linux.c
sys_win.c
sys_wind.c
view.c

index d3e5282..6bd8755 100644 (file)
@@ -1,4 +1,4 @@
 
-#define BUILDNUMBER 79
+#define BUILDNUMBER 100
 
 int buildnumber = BUILDNUMBER;
index 85873db..56b6dd7 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -286,6 +286,8 @@ void CL_PlayDemo_f (void)
                return;
        }
 
+//     SCR_BeginLoadingPlaque();
+
 //
 // disconnect from server
 //
index e0db84a..5f3d6cb 100644 (file)
--- 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_EFRAGS-1 ; i++)
-               cl.free_efrags[i].entnext = &cl.free_efrags[i+1];
-       cl.free_efrags[i].entnext = NULL;
+////
+//// allocate the efrags and chain together into a free list
+////
+//     cl.free_efrags = cl_efrags;
+//     for (i=0 ; i<MAX_EFRAGS-1 ; i++)
+//             cl.free_efrags[i].entnext = &cl.free_efrags[i+1];
+//     cl.free_efrags[i].entnext = NULL;
 }
 
 /*
@@ -110,9 +110,12 @@ void CL_Disconnect (void)
 {
 // stop sounds (especially looping!)
        S_StopAllSounds (true);
-       
-// bring the console down and fade the colors back to normal
-//     SCR_BringDownConsole ();
+
+       // clear contents blends
+       cl.cshifts[0].percent = 0;
+       cl.cshifts[1].percent = 0;
+       cl.cshifts[2].percent = 0;
+       cl.cshifts[3].percent = 0;
 
 // if running a local server, shut it down
        if (cls.demoplayback)
@@ -220,7 +223,8 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
                break;
                
        case 4:
-               SCR_EndLoadingPlaque ();                // allow normal screen updates
+//             SCR_EndLoadingPlaque ();                // allow normal screen updates
+               Con_ClearNotify();
                break;
        }
 }
@@ -239,7 +243,7 @@ void CL_NextDemo (void)
        if (cls.demonum == -1)
                return;         // don't play demos
 
-       SCR_BeginLoadingPlaque ();
+//     SCR_BeginLoadingPlaque ();
 
        if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
        {
@@ -427,6 +431,17 @@ float CL_EntityLerpPoint (entity_t *ent)
        return bound(0, f, 1);
 }
 
+void CL_RelinkStaticEntities()
+{
+       entity_t *ent, *endent;
+       if (cl.num_statics > 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);
index 942e2b3..c4a9507 100644 (file)
@@ -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);
 }
 
 /*
index 42845cd..cc6551d 100644 (file)
--- 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];
index cc4bfd8..7173172 100644 (file)
--- 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 <path>
 // 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)
index 297bcb2..fe49106 100644 (file)
--- 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
-}
-
index ef01f00..5827312 100644 (file)
--- 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
-
index 6065452..10cfd75 100644 (file)
@@ -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 (file)
index ce5ba79..0000000
+++ /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);
-               }
-       }
-}
-
-
index d266859..9a4d933 100644 (file)
@@ -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)
index cfc884d..6089fa1 100644 (file)
@@ -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 ; i<cl.worldmodel->numleafs ; i++)
-               cl.worldmodel->leafs[i].efrags = NULL;
+//     for (i=0 ; i<cl.worldmodel->numleafs ; 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();
        }
 
index 3db2230..7a24a59 100644 (file)
@@ -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 ; i<cl.worldmodel->numleafs ; 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 ; i<cl.worldmodel->numleafs ; i++)
-               {
-                       if (vis[i>>3] & (1<<(i&7)))
-                       {
-                               node = (mnode_t *)&cl.worldmodel->leafs[i+1];
-                               do
-                               {
-                                       if (node->visframe == r_visframecount)
-                                               break;
-                                       node->visframe = r_visframecount;
-                                       node = node->parent;
-                               } while (node);
-                       }
-               }
-       }
+       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<MAX_LIGHTMAPS ; texnum++)
+       for (texnum = 0;texnum < MAX_LIGHTMAPS;texnum++)
        {
                best = BLOCK_HEIGHT;
 
-               for (i=0 ; i<BLOCK_WIDTH-w ; i+=lightmapalign) // LordHavoc: NVIDIA has broken subimage, so align the lightmaps
+               for (i = 0;i < BLOCK_WIDTH - w;i += lightmapalign) // LordHavoc: NVIDIA has broken subimage, so align the lightmaps
                {
                        best2 = 0;
 
@@ -1442,7 +1555,7 @@ int AllocBlock (int w, int h, short *x, short *y)
                        }
                }
 
-               for (i=0 ; i<w ; i++)
+               for (i = 0;i < w;i++)
                        allocated[texnum][*x + i] = best + h;
 
                return texnum;
index b19aa68..eb7a176 100644 (file)
@@ -72,10 +72,6 @@ console is:
 
 int                    glx, gly, glwidth, glheight;
 
-// only the refresh window will be updated unless these variables are flagged 
-int                    scr_copytop;
-int                    scr_copyeverything;
-
 float          scr_con_current;
 float          scr_conlines;           // lines of console to display
 
@@ -99,8 +95,6 @@ qpic_t                *scr_ram;
 qpic_t         *scr_net;
 qpic_t         *scr_turtle;
 
-int                    scr_fullupdate;
-
 int                    clearconsole;
 int                    clearnotify;
 
@@ -109,8 +103,8 @@ extern int                     sb_lines;
 extern viddef_t        vid;                            // global video state
 
 qboolean       scr_disabled_for_loading;
-qboolean       scr_drawloading;
-float          scr_disabled_time;
+//qboolean     scr_drawloading;
+//float                scr_disabled_time;
 
 void SCR_ScreenShot_f (void);
 
@@ -214,7 +208,6 @@ void SCR_DrawCenterString (void)
 
 void SCR_CheckDrawCenterString (void)
 {
-       scr_copytop = 1;
        if (scr_center_lines > 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();
 
index c9e0e03..2b3e9cc 100644 (file)
--- 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 e32d0a7..c4aa409 100644 (file)
--- 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");
index f9f3225..7510ee7 100644 (file)
@@ -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<Cmd_Argc() ; i++)
@@ -359,7 +360,7 @@ This is sent just before a server changes levels
 */
 void Host_Reconnect_f (void)
 {
-       SCR_BeginLoadingPlaque ();
+//     SCR_BeginLoadingPlaque ();
        cls.signon = 0;         // need new connection messages
 }
 
@@ -548,9 +549,10 @@ void Host_Loadgame_f (void)
 
        sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
        COM_DefaultExtension (name, ".sav");
-       
-// we can't call SCR_BeginLoadingPlaque, because too much stack space has
-// been used.  The menu calls it before stuffing loadgame command
+
+       // LordHavoc: made SCR_UpdateScreen use a great deal less stack space, no longer an issue
+       //// we can't call SCR_BeginLoadingPlaque, because too much stack space has
+       //// been used.  The menu calls it before stuffing loadgame command
 //     SCR_BeginLoadingPlaque ();
 
        Con_Printf ("Loading game from %s...\n", name);
diff --git a/keys.c b/keys.c
index 968cae6..8d4de8b 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -611,18 +611,14 @@ void Key_Event (int key, qboolean down)
        key_lastpress = key;
        key_count++;
        if (key_count <= 0)
-       {
                return;         // just catching keys for Con_NotifyBox
-       }
 
 // update auto-repeat status
        if (down)
        {
                key_repeats[key]++;
                if (key != K_BACKSPACE && key != K_PAUSE && key_repeats[key] > 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)
index 7cbbad7..e1f0778 100644 (file)
--- 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 dbb8add..e379532 100644 (file)
--- 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)
        {
index 8604c43..f1f87b8 100644 (file)
@@ -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 ; i<m->nummiptex ; 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 ; j<MIPLEVELS ; j++)
-                       mt->offsets[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 ; j<MIPLEVELS ; j++)
-                       tx->offsets[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 ; i<m->nummiptex ; 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 ; j<m->nummiptex ; 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 ; j<max ; j++)
+
+               // link them all together
+               for (j = 0;j < max;j++)
                {
                        tx2 = anims[j];
                        if (!tx2)
-                               Host_Error ("Missing frame %i of %s",j, tx->name);
-                       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 ; j<altmax ; j++)
+               for (j = 0;j < altmax;j++)
                {
                        tx2 = altanims[j];
                        if (!tx2)
-                               Host_Error ("Missing frame %i of %s",j, tx->name);
-                       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 ; i<count ; i++, out++, in++)
+       for (i = 0;i < count;i++, out++, in++)
        {
                out->planenum = 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 ; i<mod->numsubmodels ; 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 ; j<MAX_MAP_HULLS ; j++)
                {
                        mod->hulls[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];
 
index 33b0506..c88f109 100644 (file)
@@ -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;
index 1d50a07..d5af37a 100644 (file)
@@ -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;
index 7b67999..f698972 100644 (file)
@@ -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;
index cea29fd..9cfe99f 100644 (file)
@@ -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);
        }
 }
index d0aedc5..8a54e8d 100644 (file)
@@ -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);
index 2c4d2d0..8f7b983 100644 (file)
--- 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<<i))
                                        {
                                                leaf = &model->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];
index df11b53..6e29e58 100644 (file)
--- 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;
index ed53ba2..fff8f37 100644 (file)
--- 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)
                {
index 95facc3..bdc18f5 100644 (file)
@@ -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++;
 
index d67134d..933a765 100644 (file)
--- 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 32e1db6..73e51ca 100644 (file)
--- 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);
 }
index 64e0bc3..5828161 100644 (file)
--- 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);
index 4eada81..426291a 100644 (file)
--- 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;
 
 //===========================================================
index 4f760ac..d8001f4 100644 (file)
--- 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;
index 59da2be..92276c2 100644 (file)
--- 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 ; e<sv.num_edicts ; e++, ent = NEXT_EDICT(ent))
+       for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
        {
                bits = 0;
+
+               // prevent delta compression against this frame (unless actually sent, which will restore this later)
+               nextfullupdate = client->nextfullupdate[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;
                
index 06ed118..7d64795 100644 (file)
--- 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 958037f..0df1b9b 100644 (file)
--- 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
index 4f611f9..d01fcf7 100644 (file)
@@ -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
 
index 8452c9a..a7f2140 100644 (file)
--- 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;
index 8c15013..beb27db 100644 (file)
@@ -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 793fec6..355a8e6 100644 (file)
--- 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 ();
 }