-#define BUILDNUMBER 79
+#define BUILDNUMBER 100
int buildnumber = BUILDNUMBER;
return;
}
+// SCR_BeginLoadingPlaque();
+
//
// disconnect from server
//
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];
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));
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;
}
/*
{
// 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)
break;
case 4:
- SCR_EndLoadingPlaque (); // allow normal screen updates
+// SCR_EndLoadingPlaque (); // allow normal screen updates
+ Con_ClearNotify();
break;
}
}
if (cls.demonum == -1)
return; // don't play demos
- SCR_BeginLoadingPlaque ();
+// SCR_BeginLoadingPlaque ();
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
{
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;
+}
/*
===============
cl_numvisedicts = 0;
+ CL_RelinkStaticEntities();
+
//
// interpolate player info
//
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);
// 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);
{
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);
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
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();
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)
{
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;
}
/*
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
VectorCopy (ent->state_baseline.origin, ent->render.origin);
VectorCopy (ent->state_baseline.angles, ent->render.angles);
- R_AddEfrags (ent);
+// R_AddEfrags (ent);
}
/*
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
// 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
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];
// 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
{
*/
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");
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] != ':'))
COM_CopyFile (netpath, cachepath);
strcpy (netpath, cachepath);
}
+#endif
if (!quiet)
Sys_Printf ("FindFile: %s\n",netpath);
basedir[j-1] = 0;
}
+#if CACHEENABLE
//
// -cachedir <path>
// Overrides the system supplied cache directory (NULL or /qcache)
strcpy (com_cachedir, host_parms.cachedir);
else
com_cachedir[0] = 0;
+#endif
//
// start up with GAMENAME by default (id1)
else
key_dest = key_console;
- SCR_EndLoadingPlaque ();
+// SCR_EndLoadingPlaque ();
memset (con_times, 0, sizeof(con_times));
}
{
va_list argptr;
char msg[MAXPRINTMSG];
- static qboolean inupdate;
+// static qboolean inupdate;
va_start (argptr,fmt);
vsprintf (msg,fmt,argptr);
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 )
inupdate = false;
}
}
+ */
}
/*
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]);
if (key_dest == key_message)
{
clearnotify = 0;
- scr_copytop = 1;
x = 0;
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
-}
-
void Con_DrawNotify (void);
void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);
-
-void Con_NotifyBox (char *text); // during startup for sound / cd warnings
-
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++;
+++ /dev/null
-/*
-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);
- }
- }
-}
-
-
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];
mleaf_t *r_viewleaf, *r_oldviewleaf;
-texture_t *r_notexture_mip;
-
unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
//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"};
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;
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);
================
*/
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];
else
starttime = currtime = 0;
R_Clear();
- skyisvisible = false;
TIMEREPORT(time_clear)
// render normal view
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)
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
TIMEREPORT(time_moveexplosions)
R_DrawExplosions();
TIMEREPORT(time_drawexplosions)
- R_DrawDecals();
- TIMEREPORT(time_drawdecals)
transpolyrender();
TIMEREPORT(time_transpoly)
#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
// 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();
continue;
if (!strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
skytexturenum = i;
- cl.worldmodel->textures[i]->texturechain = NULL;
}
SHOWLMP_clear();
}
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();
}
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()
{
}
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);
}
*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++;
}
*/
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)
{
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)
}
return base;
+ */
}
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)
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
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();
}
{
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();
}
}
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)
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
|| (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];
}
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];
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))
}
}
-/*
-================
-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);
/*
msurface_t *s;
model_t *clmodel;
int rotated, vertexlit = false;
- texture_t *t;
vec3_t org;
currententity = e;
VectorAdd (e->render.origin, clmodel->maxs, maxs);
}
- if (R_CullBox (mins, maxs))
+ if (R_VisibleCullBox (mins, maxs))
return;
c_bmodels++;
}
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++)
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();
=============================================================
*/
-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)
{
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);
}
}
-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++;
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;
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;
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;
+ }
+ }
+ }
+}
/*
=============
{
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;
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 ();
}
-
-
/*
=============================================================================
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;
}
}
- for (i=0 ; i<w ; i++)
+ for (i = 0;i < w;i++)
allocated[texnum][*x + i] = best + h;
return texnum;
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
qpic_t *scr_net;
qpic_t *scr_turtle;
-int scr_fullupdate;
-
int clearconsole;
int clearnotify;
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);
void SCR_CheckDrawCenterString (void)
{
- scr_copytop = 1;
if (scr_center_lines > scr_erase_lines)
scr_erase_lines = scr_center_lines;
qboolean full = false;
- scr_fullupdate = 0; // force a background redraw
vid.recalc_refdef = 0;
//========================================
SCR_DrawLoading
==============
*/
+/*
void SCR_DrawLoading (void)
{
qpic_t *pic;
Draw_Pic ( (vid.width - pic->width)/2,
(vid.height - 48 - pic->height)/2, pic);
}
+*/
{
if (scr_con_current)
{
- scr_copyeverything = 1;
Con_DrawConsole (scr_con_current, true);
clearconsole = 0;
}
================
*/
+/*
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;
}
+*/
/*
===============
================
*/
+/*
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)
{
} 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);
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);
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);
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;
}
}
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)
{
Draw_String(0, vid.height - sb_lines - 8, r_speeds2_string7, 80);
}
- V_UpdateBlends ();
+ V_UpdateBlends();
GL_BrightenScreen();
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;
//
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;
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];
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;
}
inerror = true;
- SCR_EndLoadingPlaque (); // reenable screen updates
+// SCR_EndLoadingPlaque (); // reenable screen updates
va_start (argptr,error);
vsprintf (hosterrorstring,error,argptr);
Cvar_RegisterVariable (&timeformat);
Host_FindMaxClients ();
-
- host_time = 1.0; // so a think at time 0 won't get called
}
if (!sv.active)
CL_SendCmd ();
- host_time += host_frametime;
-
// fetch results from server
if (cls.state == ca_connected)
CL_ReadFromServer ();
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");
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++)
*/
void Host_Reconnect_f (void)
{
- SCR_BeginLoadingPlaque ();
+// SCR_BeginLoadingPlaque ();
cls.signon = 0; // need new connection messages
}
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);
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) );
// 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)
#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
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;
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;
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 ) ) );
}
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 ) ) );
}
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");
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;
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 ) ) );
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 ) ) );
}
int m_quit_prevstate;
qboolean wasInMenus;
-#ifndef _WIN32
+//#ifndef _WIN32
char *quitMessage [] =
{
/* .........1.........2.... */
+/*
" Are you gonna quit ",
" this game just like ",
" everything else? ",
" 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)
{
m_quit_prevstate = m_state;
m_state = m_quit;
m_entersound = true;
- msgNumber = rand()&7;
+ msgNumber = rand()&3; //&7;
}
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");
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
}
//=============================================================================
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) );
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)
{
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
*/
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)
{
// 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;
}
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;
}
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] != '*')
}
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;
}
}
//
// 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';
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++;
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] != '+')
continue;
num = tx2->name[1];
- if (num >= 'a' && num <= 'z')
- num -= 'a' - 'A';
if (num >= '0' && num <= '9')
{
num -= '0';
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;
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];
}
}
}
mtexinfo_t *out;
int i, j, k, count;
int miptex;
- float len1, len2;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
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
{
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;
}
}
}
{
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);
{
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);
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];
*/
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];
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;
}
}
}
}
+#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
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];
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;
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];
//
// in memory representation
//
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
{
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;
// 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;
short light_s, light_t; // gl lightmap coordinates
glpoly_t *polys; // multiple if warped
- struct msurface_s *texturechain;
mtexinfo_t *texinfo;
{
// 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;
{
// 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;
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;
byte *lightdata;
char *entities;
+ int numportals;
+ mportal_t *portals;
+
+ int numportalpoints;
+ mvertex_t *portalpoints;
+
// LordHavoc: useful for sprites and models
int numtris;
int numskins;
typedef struct
{
char *basedir;
+#if CACHEENABLE
char *cachedir; // for development over ISDN lines
+#endif
int argc;
char **argv;
void *membase;
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]);
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
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;
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)
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++)
{
}
}
}
- // 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);
}
}
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);
R_RegisterModule("R_Light", r_light_start, r_light_shutdown, r_light_newmap);
}
-int r_dlightframecount;
-
/*
==================
R_AnimateLight
{
float ndist, maxdist;
msurface_t *surf;
+ mleaf_t *leaf;
int i;
if (!r_dynamic.value)
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;
{
int d;
float dist, dist2, impact[3];
+ if (surf->visframe != r_framecount)
+ continue;
dist = ndist;
if (surf->flags & SURF_PLANEBACK)
dist = -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;
/*
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;
}
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))
}
}
- 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;
}
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;
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];
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;
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))
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)
{
*/
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++;
byte glowcolor;
byte colormod;
byte flags;
+ byte active;
} entity_state_t;
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
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
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);
if (scr_con_current == vid.height)
return; // console is full screen
- scr_copyeverything = 1;
-
// sb_updates++;
if (sb_lines > 24)
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);
if (vid.width < 512 || !sb_lines)
return;
- scr_copyeverything = 1;
- scr_fullupdate = 0;
-
// scores
Sbar_SortFrags ();
int dig;
int num;
- scr_copyeverything = 1;
- scr_fullupdate = 0;
-
if (cl.gametype == GAME_DEATHMATCH)
{
Sbar_DeathmatchOverlay ();
{
qpic_t *pic;
- scr_copyeverything = 1;
-
pic = Draw_CachePic ("gfx/finale.lmp");
Draw_Pic ( (vid.width-pic->width)/2, 16, pic);
}
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
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);
extern jmp_buf host_abortserver;
-extern double host_time;
-
extern edict_t *sv_player;
//===========================================================
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;
*/
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
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
}
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;
+ }
}
}
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;
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);
}
+*/
/*
=============
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);
//
// memory protection
//
+#if NOTUSED
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
+#endif
//
// system IO
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;
close(fd);
}
+#if NOTUSED
void Sys_EditFile(char *filename)
{
sprintf(cmd, "xterm -e %s %s", editor, filename);
system(cmd);
}
-
}
+#endif
double Sys_FloatTime (void)
{
oktogo=1;
}
+#if NOTUSED
void Sys_LineRefresh(void)
{
}
+#endif
void floating_point_exception_handler(int whatever)
{
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);
Host_Frame (time);
+#if NOTUSED
// graphic debugging aids
if (sys_linerefresh.value)
Sys_LineRefresh ();
+#endif
}
return 0;
}
+#if NOTUSED
/*
================
Sys_MakeCodeWriteable
Sys_Error("Protection change failed\n");
}
+#endif
===============================================================================
*/
+#if NOTUSED
/*
================
Sys_MakeCodeWriteable
if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
Sys_Error("Protection change failed\n");
}
+#endif
/*
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;
===============================================================================
*/
+#if NOTUSED
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
{
}
+#endif
void Sys_DebugLog(char *file, char *fmt, ...)
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 ();
}