]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
rewrote RecursiveHullCheck, no longer gets stuck on angle changes, and is generally...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 4 Dec 2001 13:28:29 +0000 (13:28 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 4 Dec 2001 13:28:29 +0000 (13:28 +0000)
added content value to RecursiveHullCheck and TraceLine, they can now treat any content change as an impact
TraceLine now can take NULL impact and normal if they are not desired
TraceLine now sets trace_endcontents to the impacted content value
rewrote nehahra/rogue/hipnotic/standard_quake variables to be gamemode (GAME_NORMAL, GAME_HIPNOTIC, GAME_ROGUE, GAME_NEHAHRA, etc)
unfinished code for directional static lighting on models (CL_ParseEntityLump)
game now uses current mode as title everywhere (window title, server title, etc), so it would say 'DarkPlaces-Hipnotic' for example
added Draw_AdditiveString variant of Draw_String, switchs to additive blending and back to alpha afterward
engineversion string is now generated in sys_shared
major rewrite of transpolyrender, now uses glDrawElements (with batching of same texture/mode) and array locking
transpolyparticle added to quickly add particles to transpoly list (30% or so savings)
split wallpolyrender into two pieces, first renders walls, second renders fog over them, decals are rendered between the two, so decals are now fogged
added field of vision distortion when underwater (in MYgluPerspective)
changed gl_lightmapalign to align to the specified byte boundary instead of pixel boundary, and removed NVIDIA mentions (it is not their problem, it is a matter of the texture unpack alignment, but I stuck with 4 byte alignment because it is likely faster for most people)
fixed animating textures
rearranged a little bmodel code (probably no effect)
got rid of r_solidworldnode and r_pvsworldnode cvars (only the fastest choices are available now)
screenshots are now corrected to match lighthalf if it is being done using hardware gamma
removed some old unused cruft from host.c
added RGB gamma correction code to image.c
added VectorRandom to mathlib.h
model skins are no longer mipmapped by default (r_mipskins 0, but this is saved in configs so most people might not notice) because quake skins were not designed for it, and it is a 25% texture memory use increase on model skins
removed old unused Mod_FloodFillSkin code
transparent textures no longer clip other geometry in the hidden surface removal (ouch this was a bug)
maps should be able to use engine fields without the mod knowing about them now (alpha, etc), engine fields are appended to the list of progs fields
particle and decal textures are now all stored in one 'particle font' texture, for a rather hefty speed gain (no texture switchs)
all particles are now alpha blended (additive wasn't necessary on them, but is still available), to kill off state changes
new splash effect from raindrops
added a few bithacking float optimizations here and there (most with alternates if you define SLOWMATH)
new explosion effect (on by default, but a major speed drain, turn off with r_particles_explosions 0)
particle textures are now all in one image (a 'particle font'), massive speed gains with mixed particle types
all particles are alpha blend now (additive still supported, just not used), for more speed gains
particles now use 24bit RGB colors, rather than palette colors (the quake palette has been included however, because many particles still use it)
a lot of old cruft has been removed from r_part
ui items can now be strings rather than pics (actually they can be both, but I have not found a real use for this, perhaps a second draw location needs to be added for the string, so a button could have a label centered on it)
unfinished X11 gamma ramp support (need to allocate colors before setting them, haven't figured this out yet)
changed pitch range in GLX to let you look straight up and down, like in wgl version
mostly redesigned animation interpolation management code (R_LerpUpdate is now CL_LerpUpdate and performed on all network entities, R_LerpAnimation has been tweaked to not crash on bmodels and is now automatically used on all visible entities in the renderer, lerping info has has been split out of entity_render_t into entity_persistent_t so that entity_render_t contains no persistent data)
renderer now only uses entity_render_t structures
renderer now uses only currentrenderentity, and rarely passes individual properties around
cleaned out some old global variables relating to rendering
moved most of glquake.h to render.h
envmap is now actually a vaguely useful command (renders cubic environment map images of the current scene, changed to write tga images rather than raw rgba, and take a basename to use, and name them like skyboxes expect, and place them in the env directory)
many things that should be private to a particular file have been marked static
models now contain a SERAddEntity function (to add themselves to the SER clipping list to verify visibility)
models now contain DrawEarly and DrawLate functions (to render before and after wallpoly/decals/skypoly/etc, respectively)
dlight management functions moved out of cl_main and into cl_light
rewrote RelinkStaticEntities (does the same, just cleaner)
renamed RelinkEntities to RelinkNetworkEntities, split out LerpPlayerVelocity, and made a RelinkEntities function which calls the various functions
rewrote or altered portions of RelinkNetworkEntities relating to origin
muzzleflash lights are now clipped to keep them out of walls
fixed up code relating to vid.conwidth/height and vid.width/height (which is now gone, converted to vid.conwidth/height) and renamed glx/gly/glwidth/glheight to vid.realx/y/width/height (updated each frame using GL_BeginRendering)
rewrote most (all?) code relating to r_refdef, it is now always recalculated as well
dynamic lights will only update a lightmap if they actually alter it (optimization)
models now have 3 bounding boxes, used depending on angles (normal, yaw rotation only, and full rotation)
bmodel bounding boxes are recalculated from vertices
server now uses model bounding box instead of entity bounding box for visibility testing (since entity bounding box is often smaller)
server no longer portal-visibility checks entities because it was FAR too slow (sv_vischeckentities is still available though)
gl_rsurf code now relies on there being a currentrenderentity (even if it is cl.worldent.render), R_SetupWorldEnt added to avoid duplicate code for this
engine no longer has a version number, only build number
makefile now uses buildnum (as was originally intended) to increment build number every time it is compiled, build numbers will be rising rapidly from now on
timedemos will now force up console instantly
rocket trails are more dense
renamed VectorMA (function) to VectorMASlow, renamed VectorMAQuick (#define) to VectorMA, don't know why I had changed it before, had already cleaned up the parameter issues where it is used
converted most of lighting in decal code to integer
added support for all sprite types (untested)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1185 d7cf8633-e32d-0410-b094-e92efae38249

73 files changed:
buildnumber.c
chase.c
cl_demo.c
cl_effects.c
cl_light.c [new file with mode: 0644]
cl_light.h [new file with mode: 0644]
cl_main.c
cl_parse.c
cl_tent.c
client.h
common.c
common.h
console.c
draw.h
gl_draw.c
gl_models.c
gl_poly.c
gl_poly.h
gl_rmain.c
gl_rmisc.c
gl_rsurf.c
gl_screen.c
glquake.h
host.c
host_cmd.c
image.c
image.h
keys.c
makefile
mathlib.c
mathlib.h
menu.c
model_alias.c
model_brush.c
model_brush.h
model_shared.h
model_sprite.c
portals.c
pr_cmds.c
pr_edict.c
quakedef.h
r_clip.c
r_crosshairs.c
r_decals.c
r_decals.h
r_explosion.c
r_lerpanim.c
r_lerpanim.h
r_light.c
r_light.h
r_part.c
r_sprites.c
render.h
sbar.c
sv_main.c
sv_phys.c
sv_user.c
sys.h
sys_linux.c
sys_shared.c
sys_win.c
transform.c
transform.h
ui.c
ui.h
vid.h
vid_3dfxsvga.c
vid_glx.c
vid_wgl.c
view.c
view.h
world.c
world.h

index 93dd2d40e26371b1290924ff50897edb4c9787bd..9bbf28af19e864cb8a3761a660b2e259ab23dea7 100644 (file)
@@ -1,4 +1,4 @@
 
-#define BUILDNUMBER 105
+#define BUILDNUMBER 253
 
 int buildnumber = BUILDNUMBER;
diff --git a/chase.c b/chase.c
index 4633565e1c303b3f7d608fa935f249015ef6b5e9..f4ee5b9611c5c2d6230969cf0670bcea873c0278 100644 (file)
--- a/chase.c
+++ b/chase.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -38,16 +38,26 @@ void Chase_Reset (void)
 //     start position 12 units behind head
 }
 
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
+int traceline_endcontents;
+
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents)
 {
-       trace_t trace;
+       trace_t trace;
 
        memset (&trace, 0, sizeof(trace));
        VectorCopy (end, trace.endpos);
        trace.fraction = 1;
-       SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
-       VectorCopy (trace.endpos, impact);
-       VectorCopy (trace.plane.normal, normal);
+       trace.startcontents = contents;
+       VectorCopy(start, RecursiveHullCheckInfo.start);
+       VectorSubtract(end, start, RecursiveHullCheckInfo.dist);
+       RecursiveHullCheckInfo.hull = cl.worldmodel->hulls;
+       RecursiveHullCheckInfo.trace = &trace;
+       SV_RecursiveHullCheck (0, 0, 1, start, end);
+       if (impact)
+               VectorCopy (trace.endpos, impact);
+       if (normal)
+               VectorCopy (trace.plane.normal, normal);
+       traceline_endcontents = trace.endcontents;
        return trace.fraction;
 }
 
@@ -66,7 +76,7 @@ void Chase_Update (void)
        chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist;
        chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value;
 
-       TraceLine (r_refdef.vieworg, chase_dest, stop, normal);
+       TraceLine (r_refdef.vieworg, chase_dest, stop, normal, 0);
        chase_dest[0] = stop[0] + forward[0] * 8 + normal[0] * 4;
        chase_dest[1] = stop[1] + forward[1] * 8 + normal[1] * 4;
        chase_dest[2] = stop[2] + forward[2] * 8 + normal[2] * 4;
index 34c875eaae37ef43f7e46cc7a4f3a802f08a7080..ee61e500b9e818090291908d7c31a2a84c78fec8 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -365,10 +365,15 @@ void CL_TimeDemo_f (void)
        }
 
        CL_PlayDemo_f ();
-       
+
 // cls.td_starttime will be grabbed at the second frame of the demo, so
 // all the loading time doesn't get counted
-       
+
+       // instantly hide console and deactivate it
+       key_dest = key_game;
+       scr_conlines = 0;
+       scr_con_current = 0;
+
        cls.timedemo = true;
        cls.td_startframe = host_framecount;
        cls.td_lastframe = -1;          // get a new message this frame
index 42341f0ec83dffd3e809556201982e9bbc097212..5020aaa4656ee935a396f5587b1dce2d46763072 100644 (file)
@@ -33,25 +33,25 @@ typedef struct effect_s
        int endframe;
        // these are for interpolation
        int frame;
-       double frame1start;
-       double frame2start;
+       double frame1time;
+       double frame2time;
 }
 effect_t;
 
-effect_t effect[MAX_EFFECTS];
+static effect_t effect[MAX_EFFECTS];
 
-cvar_t r_draweffects = {0, "r_draweffects", "1"};
+static cvar_t r_draweffects = {0, "r_draweffects", "1"};
 
-void r_effects_start(void)
+static void r_effects_start(void)
 {
        memset(effect, 0, sizeof(effect));
 }
 
-void r_effects_shutdown(void)
+static void r_effects_shutdown(void)
 {
 }
 
-void r_effects_newmap(void)
+static void r_effects_newmap(void)
 {
        memset(effect, 0, sizeof(effect));
 }
@@ -82,12 +82,14 @@ void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float
                e->framerate = framerate;
 
                e->frame = 0;
-               e->frame1start = cl.time;
-               e->frame2start = cl.time;
+               e->frame1time = cl.time;
+               e->frame2time = cl.time;
                break;
        }
 }
 
+extern void CL_LerpAnimation(entity_t *e);
+
 void CL_DoEffects()
 {
        int i, intframe;
@@ -111,28 +113,30 @@ void CL_DoEffects()
                        if (intframe != e->frame)
                        {
                                e->frame = intframe;
-                               e->frame1start = e->frame2start;
-                               e->frame2start = cl.time;
+                               e->frame1time = e->frame2time;
+                               e->frame2time = cl.time;
                        }
 
-                       vis = CL_NewTempEntity();
-                       if (!vis)
-                               continue;
-                       VectorCopy(e->origin, vis->render.origin);
-                       vis->render.lerp_model = vis->render.model = cl.model_precache[e->modelindex];
-                       vis->render.frame1 = e->frame;
-                       vis->render.frame2 = e->frame + 1;
-                       if (vis->render.frame2 >= e->endframe)
-                               vis->render.frame2 = -1; // disappear
-                       vis->render.frame = vis->render.frame2;
-                       vis->render.framelerp = frame - vis->render.frame1;
-                       vis->render.frame1start = e->frame1start;
-                       vis->render.frame2start = e->frame2start;
-                       vis->render.lerp_starttime = -1;
-                       vis->render.colormap = -1; // no special coloring
-                       vis->render.scale = 1;
-                       vis->render.alpha = 1;
-                       vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1;
+                       if ((vis = CL_NewTempEntity()))
+                       {
+                               // interpolation stuff
+                               vis->render.frame1 = intframe;
+                               vis->render.frame2 = intframe + 1;
+                               if (vis->render.frame2 >= e->endframe)
+                                       vis->render.frame2 = -1; // disappear
+                               vis->render.framelerp = frame - intframe;
+                               vis->render.frame1time = e->frame1time;
+                               vis->render.frame2time = e->frame2time;
+
+                               // normal stuff
+                               VectorCopy(e->origin, vis->render.origin);
+                               vis->render.model = cl.model_precache[e->modelindex];
+                               vis->render.frame = vis->render.frame2;
+                               vis->render.colormap = -1; // no special coloring
+                               vis->render.scale = 1;
+                               vis->render.alpha = 1;
+                               vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1;
+                       }
                }
        }
 }
diff --git a/cl_light.c b/cl_light.c
new file mode 100644 (file)
index 0000000..e4b9d4b
--- /dev/null
@@ -0,0 +1,99 @@
+#include "quakedef.h"
+
+dlight_t cl_dlights[MAX_DLIGHTS];
+
+void cl_light_start(void)
+{
+}
+
+void cl_light_shutdown(void)
+{
+}
+
+void cl_light_newmap(void)
+{
+       memset (cl_dlights, 0, sizeof(cl_dlights));
+}
+
+void CL_Light_Init(void)
+{
+       R_RegisterModule("CL_Light", cl_light_start, cl_light_shutdown, cl_light_newmap);
+}
+
+/*
+===============
+CL_AllocDlight
+
+===============
+*/
+void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime)
+{
+       int             i;
+       dlight_t        *dl;
+
+// first look for an exact key match
+       if (ent)
+       {
+               dl = cl_dlights;
+               for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+                       if (dl->ent == ent)
+                               goto dlightsetup;
+       }
+
+// then look for anything else
+       dl = cl_dlights;
+       for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+               if (!dl->radius)
+                       goto dlightsetup;
+
+       // unable to find one
+       return;
+
+dlightsetup:
+       memset (dl, 0, sizeof(*dl));
+       dl->ent = ent;
+       VectorCopy(org, dl->origin);
+       dl->radius = radius;
+       dl->color[0] = red;
+       dl->color[1] = green;
+       dl->color[2] = blue;
+       dl->decay = decay;
+       dl->die = cl.time + lifetime;
+}
+
+
+/*
+===============
+CL_DecayLights
+
+===============
+*/
+void CL_DecayLights (void)
+{
+       int                     i;
+       dlight_t        *dl;
+       float           time;
+
+       time = cl.time - cl.oldtime;
+
+       c_dlights = 0;
+       dl = cl_dlights;
+       for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+       {
+               if (!dl->radius)
+                       continue;
+               if (dl->die < cl.time)
+               {
+                       dl->radius = 0;
+                       continue;
+               }
+
+               c_dlights++; // count every dlight in use
+
+               dl->radius -= time*dl->decay;
+               if (dl->radius < 0)
+                       dl->radius = 0;
+       }
+}
+
+
diff --git a/cl_light.h b/cl_light.h
new file mode 100644 (file)
index 0000000..3843065
--- /dev/null
@@ -0,0 +1,21 @@
+
+// LordHavoc: 256 dynamic lights
+#define        MAX_DLIGHTS             256
+typedef struct
+{
+       vec3_t  origin;
+       float   radius;
+       float   die;                    // stop lighting after this time
+       float   decay;                  // drop this each second
+       entity_render_t *ent;   // the entity that spawned this light (can be NULL if it will never be replaced)
+       vec3_t  color;                  // LordHavoc: colored lighting
+} dlight_t;
+
+// LordHavoc: this affects the lighting scale of the whole game
+#define LIGHTOFFSET 4096.0f
+
+extern dlight_t                cl_dlights[MAX_DLIGHTS];
+
+extern void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime);
+extern void CL_DecayLights (void);
+
index a938d12db96d4228b71409cfcd705770650c0856..26b78cff7477b0dd6927ececb3c16b28c3cc1b91 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -49,7 +49,6 @@ client_state_t        cl;
 entity_t               cl_entities[MAX_EDICTS];
 entity_t               cl_static_entities[MAX_STATIC_ENTITIES];
 lightstyle_t   cl_lightstyle[MAX_LIGHTSTYLES];
-dlight_t               cl_dlights[MAX_DLIGHTS];
 
 int                            cl_numvisedicts;
 entity_t               *cl_visedicts[MAX_VISEDICTS];
@@ -72,9 +71,8 @@ void CL_ClearState (void)
 
        SZ_Clear (&cls.message);
 
-// clear other arrays  
+// clear other arrays
        memset (cl_entities, 0, sizeof(cl_entities));
-       memset (cl_dlights, 0, sizeof(cl_dlights));
        memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
        memset (cl_temp_entities, 0, sizeof(cl_temp_entities));
        memset (cl_beams, 0, sizeof(cl_beams));
@@ -87,6 +85,44 @@ void CL_ClearState (void)
        }
 }
 
+void CL_LerpUpdate(entity_t *e, int frame, int modelindex)
+{
+       entity_persistent_t *p;
+       entity_render_t *r;
+       p = &e->persistent;
+       r = &e->render;
+
+       if (p->modelindex != modelindex)
+       {
+               // reset all interpolation information
+               p->modelindex = modelindex;
+               p->frame1 = p->frame2 = frame;
+               p->frame1time = p->frame2time = cl.time;
+               p->framelerp = 1;
+       }
+       else if (p->frame2 != frame)
+       {
+               // transition to new frame
+               p->frame1 = p->frame2;
+               p->frame1time = p->frame2time;
+               p->frame2 = frame;
+               p->frame2time = cl.time;
+               p->framelerp = 0;
+       }
+       else
+       {
+               // update transition
+               p->framelerp = (cl.time - p->frame2time) * 10;
+               p->framelerp = bound(0, p->framelerp, 1);
+       }
+
+       r->frame1 = p->frame1;
+       r->frame2 = p->frame2;
+       r->framelerp = p->framelerp;
+       r->frame1time = p->frame1time;
+       r->frame2time = p->frame2time;
+}
+
 /*
 =====================
 CL_Disconnect
@@ -186,7 +222,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
                MSG_WriteByte (&cls.message, clc_stringcmd);
                MSG_WriteString (&cls.message, "prespawn");
                break;
-               
+
        case 2:
                MSG_WriteByte (&cls.message, clc_stringcmd);
                MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
@@ -283,83 +319,6 @@ void CL_PrintEntities_f (void)
 }
 
 
-/*
-===============
-CL_AllocDlight
-
-===============
-*/
-void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime)
-{
-       int             i;
-       dlight_t        *dl;
-
-// first look for an exact key match
-       if (ent)
-       {
-               dl = cl_dlights;
-               for (i = 0;i < MAX_DLIGHTS;i++, dl++)
-                       if (dl->ent == ent)
-                               goto dlightsetup;
-       }
-
-// then look for anything else
-       dl = cl_dlights;
-       for (i = 0;i < MAX_DLIGHTS;i++, dl++)
-               if (!dl->radius)
-                       goto dlightsetup;
-
-       // unable to find one
-       return;
-
-dlightsetup:
-       memset (dl, 0, sizeof(*dl));
-       dl->ent = ent;
-       VectorCopy(org, dl->origin);
-       dl->radius = radius;
-       dl->color[0] = red;
-       dl->color[1] = green;
-       dl->color[2] = blue;
-       dl->decay = decay;
-       dl->die = cl.time + lifetime;
-}
-
-
-/*
-===============
-CL_DecayLights
-
-===============
-*/
-void CL_DecayLights (void)
-{
-       int                     i;
-       dlight_t        *dl;
-       float           time;
-       
-       time = cl.time - cl.oldtime;
-
-       c_dlights = 0;
-       dl = cl_dlights;
-       for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
-       {
-               if (!dl->radius)
-                       continue;
-               if (dl->die < cl.time)
-               {
-                       dl->radius = 0;
-                       continue;
-               }
-
-               c_dlights++; // count every dlight in use
-
-               dl->radius -= time*dl->decay;
-               if (dl->radius < 0)
-                       dl->radius = 0;
-       }
-}
-
-
 /*
 ===============
 CL_LerpPoint
@@ -432,14 +391,9 @@ float CL_EntityLerpPoint (entity_t *ent)
 
 void CL_RelinkStaticEntities(void)
 {
-       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;
+       int i;
+       for (i = 0;i < cl.num_statics && cl_numvisedicts < MAX_VISEDICTS;i++)
+               cl_visedicts[cl_numvisedicts++] = &cl_static_entities[i];
 }
 
 /*
@@ -448,43 +402,18 @@ CL_RelinkEntities
 ===============
 */
 void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent);
-void CL_RelinkEntities (void)
+void CL_RelinkNetworkEntities()
 {
        entity_t        *ent;
        int                     i, j, glowcolor, effects;
-       float           frac, f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize;
-       vec3_t          oldorg, delta, dlightcolor;
-
-// determine partial update time       
-       frac = CL_LerpPoint ();
+       float           f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize;
+       vec3_t          oldorg, neworg, delta, dlightcolor;
 
-       cl_numvisedicts = 0;
+       bobjrotate = ANGLEMOD(100*cl.time);
+//     bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f;
 
        CL_RelinkStaticEntities();
 
-//
-// interpolate player info
-//
-       for (i = 0;i < 3;i++)
-               cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
-
-       if (cls.demoplayback)
-       {
-       // interpolate the angles
-               for (j = 0;j < 3;j++)
-               {
-                       d = cl.mviewangles[0][j] - cl.mviewangles[1][j];
-                       if (d > 180)
-                               d -= 360;
-                       else if (d < -180)
-                               d += 360;
-                       cl.viewangles[j] = cl.mviewangles[1][j] + frac*d;
-               }
-       }
-       
-       bobjrotate = ANGLEMOD(100*cl.time);
-//     bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f;
-       
 // start on the entity after the world
        for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++)
        {
@@ -492,33 +421,27 @@ void CL_RelinkEntities (void)
                if (!ent->state_current.active)
                        continue;
 
-               VectorCopy (ent->render.origin, oldorg);
+               VectorCopy(ent->persistent.trail_origin, oldorg);
 
                if (!ent->state_previous.active)
                {
                        // only one state available
-                       VectorCopy (ent->state_current.origin, ent->render.origin);
+                       VectorCopy (ent->state_current.origin, neworg);
                        VectorCopy (ent->state_current.angles, ent->render.angles);
-//                     Con_Printf(" %i", i);
                }
                else
                {
                        // if the delta is large, assume a teleport and don't lerp
-                       f = CL_EntityLerpPoint(ent);
-                       if (f < 1)
-                       {
-                               for (j = 0;j < 3;j++)
-                               {
-                                       delta[j] = ent->state_current.origin[j] - ent->state_previous.origin[j];
-                                       // LordHavoc: increased lerp tolerance from 100 to 200
-                                       if (delta[j] > 200 || delta[j] < -200)
-                                               f = 1;
-                               }
-                       }
+                       VectorSubtract(ent->state_current.origin, ent->state_previous.origin, delta);
+                       // LordHavoc: increased tolerance from 100 to 200
+                       if (DotProduct(delta, delta) > 200*200)
+                               f = 1;
+                       else
+                               f = CL_EntityLerpPoint(ent);
                        if (f >= 1)
                        {
                                // no interpolation
-                               VectorCopy (ent->state_current.origin, ent->render.origin);
+                               VectorCopy (ent->state_current.origin, neworg);
                                VectorCopy (ent->state_current.angles, ent->render.angles);
                        }
                        else
@@ -526,7 +449,7 @@ void CL_RelinkEntities (void)
                                // interpolate the origin and angles
                                for (j = 0;j < 3;j++)
                                {
-                                       ent->render.origin[j] = ent->state_previous.origin[j] + f*delta[j];
+                                       neworg[j] = ent->state_previous.origin[j] + f*delta[j];
 
                                        d = ent->state_current.angles[j] - ent->state_previous.angles[j];
                                        if (d > 180)
@@ -538,6 +461,12 @@ void CL_RelinkEntities (void)
                        }
                }
 
+               VectorCopy (neworg, ent->persistent.trail_origin);
+               // persistent.modelindex will be updated by CL_LerpUpdate
+               if (ent->state_current.modelindex != ent->persistent.modelindex)
+                       VectorCopy(neworg, oldorg);
+
+               VectorCopy (neworg, ent->render.origin);
                ent->render.flags = ent->state_current.flags;
                ent->render.effects = effects = ent->state_current.effects;
                ent->render.model = cl.model_precache[ent->state_current.modelindex];
@@ -555,6 +484,10 @@ void CL_RelinkEntities (void)
                ent->render.colormod[1] = (float) ((ent->state_current.colormod >> 2) & 7) * (1.0f / 7.0f);
                ent->render.colormod[2] = (float) (ent->state_current.colormod & 3) * (1.0f / 3.0f);
 
+               // update interpolation info
+               CL_LerpUpdate(ent, ent->state_current.frame, ent->state_current.modelindex);
+
+               // handle effects now...
                dlightradius = 0;
                dlightcolor[0] = 0;
                dlightcolor[1] = 0;
@@ -567,13 +500,14 @@ void CL_RelinkEntities (void)
                                R_EntityParticles (ent);
                        if (effects & EF_MUZZLEFLASH)
                        {
-                               vec3_t v;
+                               vec3_t v, v2;
 
                                AngleVectors (ent->render.angles, v, NULL, NULL);
 
-                               v[0] = v[0] * 18 + ent->render.origin[0];
-                               v[1] = v[1] * 18 + ent->render.origin[1];
-                               v[2] = v[2] * 18 + ent->render.origin[2] + 16;
+                               v2[0] = v[0] * 18 + neworg[0];
+                               v2[1] = v[1] * 18 + neworg[1];
+                               v2[2] = v[2] * 18 + neworg[2] + 16;
+                               TraceLine(neworg, v2, v, NULL, 0);
 
                                CL_AllocDlight (NULL, v, 100, 1, 1, 1, 0, 0.1);
                        }
@@ -602,14 +536,27 @@ void CL_RelinkEntities (void)
                                dlightcolor[1] +=  20.0f;
                                dlightcolor[2] += 200.0f;
                        }
-                       else if (effects & EF_FLAME)
+                       if (effects & EF_FLAME)
                        {
                                if (ent->render.model)
                                {
                                        vec3_t mins, maxs;
                                        int temp;
-                                       VectorAdd(ent->render.origin, ent->render.model->mins, mins);
-                                       VectorAdd(ent->render.origin, ent->render.model->maxs, maxs);
+                                       if (ent->render.angles[0] || ent->render.angles[2])
+                                       {
+                                               VectorAdd(neworg, ent->render.model->rotatedmins, mins);
+                                               VectorAdd(neworg, ent->render.model->rotatedmaxs, maxs);
+                                       }
+                                       else if (ent->render.angles[1])
+                                       {
+                                               VectorAdd(neworg, ent->render.model->yawmins, mins);
+                                               VectorAdd(neworg, ent->render.model->yawmaxs, maxs);
+                                       }
+                                       else
+                                       {
+                                               VectorAdd(neworg, ent->render.model->normalmins, mins);
+                                               VectorAdd(neworg, ent->render.model->normalmaxs, maxs);
+                                       }
                                        // how many flames to make
                                        temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300);
                                        R_FlameCube(mins, maxs, temp);
@@ -633,13 +580,13 @@ void CL_RelinkEntities (void)
                        if (ent->state_previous.active)
                        {
                                if (ent->render.model->flags & EF_GIB)
-                                       R_RocketTrail (oldorg, ent->render.origin, 2, ent);
+                                       R_RocketTrail (oldorg, neworg, 2, ent);
                                else if (ent->render.model->flags & EF_ZOMGIB)
-                                       R_RocketTrail (oldorg, ent->render.origin, 4, ent);
+                                       R_RocketTrail (oldorg, neworg, 4, ent);
                                else if (ent->render.model->flags & EF_TRACER)
-                                       R_RocketTrail (oldorg, ent->render.origin, 3, ent);
+                                       R_RocketTrail (oldorg, neworg, 3, ent);
                                else if (ent->render.model->flags & EF_TRACER2)
-                                       R_RocketTrail (oldorg, ent->render.origin, 5, ent);
+                                       R_RocketTrail (oldorg, neworg, 5, ent);
                                else if (ent->render.model->flags & EF_ROCKET)
                                {
                                        R_RocketTrail (oldorg, ent->render.origin, 0, ent);
@@ -650,12 +597,12 @@ void CL_RelinkEntities (void)
                                else if (ent->render.model->flags & EF_GRENADE)
                                {
                                        if (ent->render.alpha == -1) // LordHavoc: Nehahra dem compatibility
-                                               R_RocketTrail (oldorg, ent->render.origin, 7, ent);
+                                               R_RocketTrail (oldorg, neworg, 7, ent);
                                        else
-                                               R_RocketTrail (oldorg, ent->render.origin, 1, ent);
+                                               R_RocketTrail (oldorg, neworg, 1, ent);
                                }
                                else if (ent->render.model->flags & EF_TRACER3)
-                                       R_RocketTrail (oldorg, ent->render.origin, 6, ent);
+                                       R_RocketTrail (oldorg, neworg, 6, ent);
                        }
                }
                // LordHavoc: customizable glow
@@ -668,17 +615,18 @@ void CL_RelinkEntities (void)
                }
                // LordHavoc: customizable trail
                if (ent->render.flags & RENDER_GLOWTRAIL)
-                       R_RocketTrail2 (oldorg, ent->render.origin, glowcolor, ent);
+                       R_RocketTrail2 (oldorg, neworg, glowcolor, ent);
 
                if (dlightcolor[0] || dlightcolor[1] || dlightcolor[2])
                {
                        vec3_t vec;
                        dlightradius = VectorLength(dlightcolor);
                        d = 1.0f / dlightradius;
-                       VectorCopy(ent->render.origin, vec);
+                       VectorCopy(neworg, vec);
+                       // hack to make glowing player light shine on their gun
                        if (i == cl.viewentity && !chase_active.value)
                                vec[2] += 30;
-                       CL_AllocDlight (ent, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0);
+                       CL_AllocDlight (&ent->render, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0);
                }
 
                if (chase_active.value)
@@ -699,7 +647,40 @@ void CL_RelinkEntities (void)
                if (cl_numvisedicts < MAX_VISEDICTS)
                        cl_visedicts[cl_numvisedicts++] = ent;
        }
-//     Con_Printf("\n");
+}
+
+void CL_LerpPlayerVelocity (void)
+{
+       int i;
+       float frac, d;
+
+       // fraction from previous network update to current
+       frac = CL_LerpPoint ();
+
+       for (i = 0;i < 3;i++)
+               cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
+
+       if (cls.demoplayback)
+       {
+               // interpolate the angles
+               for (i = 0;i < 3;i++)
+               {
+                       d = cl.mviewangles[0][i] - cl.mviewangles[1][i];
+                       if (d > 180)
+                               d -= 360;
+                       else if (d < -180)
+                               d += 360;
+                       cl.viewangles[i] = cl.mviewangles[1][i] + frac*d;
+               }
+       }
+}
+
+void CL_RelinkEntities (void)
+{
+       cl_numvisedicts = 0;
+
+       CL_LerpPlayerVelocity();
+       CL_RelinkNetworkEntities();
 }
 
 
index f2c704f2b980c98c1b4a163fd6fadd6445c86ec5..ec3d3d597f712a80c4c521b3797f1cb155575044 100644 (file)
@@ -35,7 +35,7 @@ char *svc_strings[128] =
        "svc_stufftext",                // [string] stuffed into client's console buffer
                                                // the string should be \n terminated
        "svc_setangle",         // [vec3] set the view angle to this absolute value
-       
+
        "svc_serverinfo",               // [long] version
                                                // [string] signon string
                                                // [string]..[0]model cache [string]...[0]sounds cache
@@ -94,7 +94,7 @@ void CL_Parse_Init(void)
 {
        // LordHavoc: added demo_nehahra cvar
        Cvar_RegisterVariable (&demo_nehahra);
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
                Cvar_SetValue("demo_nehahra", 1);
 }
 
@@ -174,7 +174,7 @@ void CL_ParseStartSoundPacket(int largesoundindex)
        
        for (i=0 ; i<3 ; i++)
                pos[i] = MSG_ReadCoord ();
+
     S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
 }       
 
@@ -239,31 +239,90 @@ void CL_KeepaliveMessage (void)
        SZ_Clear (&cls.message);
 }
 
+//FIXME finish this code!
+#define MAX_STATICLIGHTS 2048
+// tyrlite types
+#define LIGHTFADE_LMINUSX 0 // light, arghlite, others?
+#define LIGHTFADE_LDIVX 1
+#define LIGHTFADE_LDIVX2 2 // hlight
+#define LIGHTFADE_L 3
+#define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later
+
+typedef struct
+{
+       int fadetype; // one of the LIGHTFADE_ values
+       int style;
+       vec3_t origin;
+       vec_t radius; // the point at which lighting stops
+       vec3_t direction;
+       vec_t cone; // if non-zero, it is a spot light
+       vec3_t color;
+       vec_t distancescale; // attenuation
+       vec_t lightsubtract; // biasing lighting toward black (hlight feature)
+}
+staticlight_t;
+
+staticlight_t staticlight[MAX_STATICLIGHTS];
+int staticlights;
+
+int r_sunlightenabled;
+vec3_t r_sunlightdirection, r_sunlightcolor;
+vec3_t r_light_ambientcolor;
+
 void CL_ParseEntityLump(char *entdata)
 {
        char *data;
        char key[128], value[4096];
        char wadname[128];
-       int i, j, k;
+       char targetnamebuffer[65536];
+       char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256];
+       vec3_t targetnameorigin[8192], targetnametemporigin, v;
+       int targets, targetnames, targetnamebufferpos, targetnameorigintofillin;
+       int i, j, k, n;
+       float f1, f2, f3, f4;
+       float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3];
+       int light_fadetype, light_style, hlight, tyrlite, light_enable;
+       float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius;
        FOG_clear(); // LordHavoc: no fog until set
        R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
        r_farclip.value = 6144; // LordHavoc: default farclip distance
+       r_sunlightenabled = false;
+       staticlights = 0;
        data = entdata;
        if (!data)
                return;
        data = COM_Parse(data);
        if (!data)
-               return; // valid exit
+               return; // error
        if (com_token[0] != '{')
                return; // error
+       hlight = false;
+       tyrlite = false;
+       ambientlight = 0;
+       ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1;
+       sunlight = 0;
+       sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1;
+       sunlightdirection[0] = 0;
+       sunlightdirection[1] = 0;
+       sunlightdirection[2] = -1;
+       targets = 0;
+       targetnames = 0;
+       targetnamebufferpos = 0;
+       targetnameorigintofillin = -1;
+       targetnametemporigin[0] = 0;
+       targetnametemporigin[1] = 0;
+       targetnametemporigin[2] = 0;
        while (1)
        {
                data = COM_Parse(data);
                if (!data)
                        return; // error
                if (com_token[0] == '}')
-                       return; // since we're just parsing the first ent (worldspawn), exit
-               strcpy(key, com_token);
+                       break; // end of worldspawn
+               if (com_token[0] == '_')
+                       strcpy(key, com_token + 1);
+               else
+                       strcpy(key, com_token);
                while (key[strlen(key)-1] == ' ') // remove trailing spaces
                        key[strlen(key)-1] = 0;
                data = COM_Parse(data);
@@ -283,10 +342,7 @@ void CL_ParseEntityLump(char *entdata)
                                r_farclip.value = 64;
                }
                else if (!strcmp("fog", key))
-               {
                        scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
-                       j = 0;
-               }
                else if (!strcmp("fog_density", key))
                        fog_density = atof(value);
                else if (!strcmp("fog_red", key))
@@ -325,6 +381,242 @@ void CL_ParseEntityLump(char *entdata)
                                }
                        }
                }
+               else if (!strcmp("light", key))
+                       ambientlight = atof(value);
+               else if (!strcmp("sunlight", key))
+               {
+                       sunlight = atof(value);
+                       tyrlite = true;
+               }
+               else if (!strcmp("sun_color", key))
+               {
+                       if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+                               VectorCopy(v, sunlightcolor);
+                       tyrlite = true;
+               }
+               else if (!strcmp("sun_mangle", key))
+               {
+                       if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+                               AngleVectors(v, sunlightdirection, NULL, NULL);
+                       tyrlite = true;
+               }
+               else if (!strcmp("origin", key))
+               {
+                       if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+                       {
+                               VectorCopy(v, targetnametemporigin);
+                               VectorCopy(v, light_origin);
+                       }
+               }
+               else if (!strcmp("targetname", key))
+               {
+                       if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+                       {
+                               targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
+                               strcpy(targetnamebuffer + targetnamebufferpos, value);
+                               targetnamebufferpos += strlen(value) + 1;
+                               targetnameorigintofillin = targetnames++;
+                       }
+               }
+       }
+       if (targetnameorigintofillin >= 0)
+               VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
+
+       if (sunlight)
+       {
+               r_sunlightenabled = true;
+               VectorScale(sunlightcolor, sunlight, r_sunlightcolor);
+               VectorCopy(sunlightdirection, r_sunlightdirection);
+       }
+       VectorScale(ambientcolor, ambientlight, r_light_ambientcolor);
+
+       while(1)
+       {
+               data = COM_Parse(data);
+               if (!data)
+                       break; // done
+               if (com_token[0] != '{')
+                       break; // error
+               light_light = 0;
+               light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
+               light_color[0] = light_color[1] = light_color[2] = 1.0f;
+               light_direction[0] = light_direction[1] = light_direction[2] = 0.0f;
+               light_cone = -cos(20*M_PI/180);
+               light_distancescale = 1.0f;
+               light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified
+               light_style = 0;
+               light_lightradius = 0;
+               light_enable = false;
+               targetnameorigintofillin = -1;
+               targetnametemporigin[0] = 0;
+               targetnametemporigin[1] = 0;
+               targetnametemporigin[2] = 0;
+               while (1)
+               {
+                       data = COM_Parse(data);
+                       if (!data)
+                               return; // error
+                       if (com_token[0] == '}')
+                               break;
+                       if (com_token[0] == '_')
+                               strcpy(key, com_token + 1);
+                       else
+                               strcpy(key, com_token);
+                       while (key[strlen(key)-1] == ' ') // remove trailing spaces
+                               key[strlen(key)-1] = 0;
+                       data = COM_Parse(data);
+                       if (!data)
+                               return; // error
+                       strcpy(value, com_token);
+                       if (!strcmp("light", key))
+                       {
+                               n = scanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4);
+                               switch(n)
+                               {
+                               case 1:
+                                       // id light, arghlite, tyrlite, others
+                                       light_light = f1;
+                                       light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
+                                       break;
+                               case 3:
+                                       // hlight specific (supports all 3 light formats, but this one is unique to it)
+                                       hlight = true;
+                                       light_light = max(f1, max(f2, f3));
+                                       light_lightcolor[0] = f1 / light_light;
+                                       light_lightcolor[1] = f2 / light_light;
+                                       light_lightcolor[2] = f3 / light_light;
+                                       break;
+                               case 4:
+                                       // halflife
+                                       hlight = true; // unless this is a halflife map, probably hlight
+                                       light_light = f4;
+                                       light_lightcolor[0] = f1 * (1.0f / 255.0f);
+                                       light_lightcolor[1] = f1 * (1.0f / 255.0f);
+                                       light_lightcolor[2] = f1 * (1.0f / 255.0f);
+                                       break;
+                               default:
+                                       // error
+                                       break;
+                               }
+                       }
+                       else if (!strcmp("color", key))
+                       {
+                               n = scanf(value, "%f %f %f", &f1, &f2, &f3);
+                               if (n == 3)
+                               {
+                                       light_color[0] = f1;
+                                       light_color[1] = f2;
+                                       light_color[2] = f3;
+                               }
+                               // n != 3 is an error
+                       }
+                       else if (!strcmp("wait", key))
+                               light_distancescale = atof(value);
+                       else if (!strcmp("delay", key))
+                       {
+                               light_fadetype = atoi(value);
+                               tyrlite = true;
+                       }
+                       else if (!strcmp("angle", key))
+                               light_cone = -cos(atof(value) * M_PI / 360);
+                       else if (!strcmp("mangle", key))
+                       {
+                               n = scanf(value, "%f %f %f", &v[0], &v[1], &v[2]);
+                               if (n == 3)
+                                       AngleVectors(v, light_direction, NULL, NULL);
+                               // n != 3 is an error
+                               tyrlite = true;
+                       }
+                       else if (!strcmp("style", key))
+                       {
+                               n = atoi(value);
+                               if (n >= 0 && n < MAX_LIGHTSTYLES)
+                                       light_style = n;
+                       }
+                       else if (!strcmp("lightradius", key))
+                       {
+                               hlight = true;
+                               light_lightradius = atof(value);
+                       }
+                       else if (!strcmp("classname", key))
+                               if (!strncmp(value, "light", 5))
+                                       light_enable = true;
+                       else if (!strcmp("origin", key))
+                       {
+                               if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+                                       VectorCopy(v, targetnametemporigin);
+                       }
+                       else if (!strcmp("targetname", key))
+                       {
+                               if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+                               {
+                                       targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
+                                       strcpy(targetnamebuffer + targetnamebufferpos, value);
+                                       targetnamebufferpos += strlen(value) + 1;
+                                       targetnameorigintofillin = targetnames++;
+                               }
+                       }
+                       else if (!strcmp("target", key))
+                               if (strlen(value) < sizeof(light_target))
+                                       strcpy(light_target, value);
+               }
+               if (targetnameorigintofillin >= 0)
+                       VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
+               if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0)
+               {
+                       VectorCopy(light_origin, staticlight[staticlights].origin);
+                       staticlight[staticlights].color[0] = light_light * light_lightcolor[0] * light_color[0];
+                       staticlight[staticlights].color[1] = light_light * light_lightcolor[1] * light_color[1];
+                       staticlight[staticlights].color[2] = light_light * light_lightcolor[2] * light_color[2];
+                       VectorCopy(light_direction, staticlight[staticlights].direction);
+                       staticlight[staticlights].cone = light_cone;
+                       staticlight[staticlights].distancescale = light_distancescale;
+                       staticlight[staticlights].fadetype = light_fadetype;
+                       staticlight[staticlights].style = light_style;
+                       if (light_target && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+                       {
+                               target[staticlights] = targetnamebuffer + targetnamebufferpos;
+                               strcpy(targetnamebuffer + targetnamebufferpos, value);
+                               targetnamebufferpos += strlen(value) + 1;
+                       }
+                       else
+                               target[staticlights] = NULL;
+                       staticlight[staticlights].lightsubtract = 0;
+                       if (light_lightradius)
+                       {
+                               staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2;
+                               staticlight[staticlights].lightsubtract = max(staticlight[staticlights].color[0], max(staticlight[staticlights].color[1], staticlight[staticlights].color[2])) * 0.5f / (light_lightradius * light_distancescale * light_lightradius * light_distancescale * (1.0f / 65536.0f) + 1.0f);
+                       }
+                       staticlights++;
+               }
+       }
+       if (hlbsp)
+               n = LIGHTFADE_LDIVX2;
+       else if (tyrlite)
+               n = LIGHTFADE_LMINUSX;
+       else if (hlight)
+               n = LIGHTFADE_LDIVX2;
+       else
+               n = LIGHTFADE_LMINUSX;
+       for (i = 0;i < staticlights;i++)
+       {
+               if (staticlight[i].fadetype == LIGHTFADE_DEFAULT)
+                       staticlight[i].fadetype = n;
+               if (target[i])
+               {
+                       for (j = 0;j < targetnames;j++)
+                       {
+                               if (!strcmp(target[i], targetname[j]))
+                               {
+                                       VectorSubtract(targetnameorigin[j], staticlight[i].origin, v);
+                                       VectorNormalize(v);
+                                       VectorCopy(v, staticlight[i].direction);
+                                       break;
+                               }
+                       }
+               }
+               if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0)
+                       staticlight[i].cone = 0;
        }
 }
 
@@ -340,7 +632,7 @@ void CL_ParseServerInfo (void)
        int             nummodels, numsounds;
        char    model_precache[MAX_MODELS][MAX_QPATH];
        char    sound_precache[MAX_SOUNDS][MAX_QPATH];
-       
+
        Con_DPrintf ("Serverinfo packet received.\n");
 //
 // wipe the client_state_t struct
@@ -495,6 +787,11 @@ void CL_ValidateState(entity_state_t *s)
                Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
                s->frame = 0;
        }
+       if (model && s->skin >= model->numskins)
+       {
+               Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
+               s->skin = 0;
+       }
 }
 
 /*
@@ -812,10 +1109,10 @@ void CL_ParseClientdata (int bits)
 
        i = MSG_ReadByte ();
 
-       if (standard_quake)
-               cl.stats[STAT_ACTIVEWEAPON] = i;
-       else
+       if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
                cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
+       else
+               cl.stats[STAT_ACTIVEWEAPON] = i;
 }
 
 /*
@@ -826,7 +1123,7 @@ CL_ParseStatic
 void CL_ParseStatic (int large)
 {
        entity_t *ent;
-               
+
        if (cl.num_statics >= MAX_STATIC_ENTITIES)
                Host_Error ("Too many static entities");
        ent = &cl_static_entities[cl.num_statics++];
@@ -836,9 +1133,8 @@ void CL_ParseStatic (int large)
        ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
        ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
        ent->render.framelerp = 0;
-       ent->render.lerp_starttime = -1;
        // make torchs play out of sync
-       ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
+       ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
        ent->render.colormap = -1; // no special coloring
        ent->render.skinnum = ent->state_baseline.skin;
        ent->render.effects = ent->state_baseline.effects;
@@ -1046,7 +1342,7 @@ void CL_ParseServerMessage (void)
                        
                case svc_serverinfo:
                        CL_ParseServerInfo ();
-                       vid.recalc_refdef = true;       // leave intermission full screen
+//                     vid.recalc_refdef = true;       // leave intermission full screen
                        break;
                        
                case svc_setangle:
@@ -1184,20 +1480,20 @@ void CL_ParseServerMessage (void)
                case svc_intermission:
                        cl.intermission = 1;
                        cl.completed_time = cl.time;
-                       vid.recalc_refdef = true;       // go to full screen
+//                     vid.recalc_refdef = true;       // go to full screen
                        break;
 
                case svc_finale:
                        cl.intermission = 2;
                        cl.completed_time = cl.time;
-                       vid.recalc_refdef = true;       // go to full screen
+//                     vid.recalc_refdef = true;       // go to full screen
                        SCR_CenterPrint (MSG_ReadString ());                    
                        break;
 
                case svc_cutscene:
                        cl.intermission = 3;
                        cl.completed_time = cl.time;
-                       vid.recalc_refdef = true;       // go to full screen
+//                     vid.recalc_refdef = true;       // go to full screen
                        SCR_CenterPrint (MSG_ReadString ());                    
                        break;
 
index 1c921fe36170cfe79008b1ed351d313292172586..d441a61ec59a65b2ddc92189c6caca1d00407f29 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -524,7 +524,7 @@ void CL_UpdateTEnts (void)
                        ent->render.angles[2] = rand()%360;
 
                        if (r_glowinglightning.value > 0)
-                               CL_AllocDlight(ent, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0);
+                               CL_AllocDlight(&ent->render, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0);
 
                        VectorMA(org, 30, dist, org);
                        d -= 30;
index a690fdc53efe9c9b923d5248d02dd71d11e19def..4b469bb30dd6d7dc568c5883affacef36bf72845 100644 (file)
--- a/client.h
+++ b/client.h
@@ -263,17 +263,16 @@ extern client_state_t cl;
 extern entity_t                cl_entities[MAX_EDICTS];
 extern entity_t                cl_static_entities[MAX_STATIC_ENTITIES];
 extern lightstyle_t    cl_lightstyle[MAX_LIGHTSTYLES];
-extern dlight_t                cl_dlights[MAX_DLIGHTS];
 extern entity_t                cl_temp_entities[MAX_TEMP_ENTITIES];
 extern beam_t                  cl_beams[MAX_BEAMS];
 
 //=============================================================================
 
+#include "cl_light.h"
+
 //
 // cl_main
 //
-extern void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime);
-extern void CL_DecayLights (void);
 
 extern void CL_Init (void);
 
index 4258945e5145fd9fe095b4cda379dd6354dc9b2a..7a042874f45cdb453f6ffd182c0d2207cd6d0551 100644 (file)
--- a/common.c
+++ b/common.c
@@ -58,7 +58,8 @@ char  **com_argv;
 #define CMDLINE_LENGTH 1024
 char   com_cmdline[CMDLINE_LENGTH];
 
-qboolean               standard_quake = true, rogue = false, hipnotic = false, nehahra = false;
+int gamemode;
+char *gamename;
 
 /*
 
@@ -1120,28 +1121,48 @@ void COM_InitArgv (int argc, char **argv)
        largv[com_argc] = argvdummy;
        com_argv = largv;
 
-#ifdef NEHAHRA
-       nehahra = true;
-       standard_quake = false;
+#if ZYMOTIC
+       gamemode = GAME_ZYMOTIC;
+#elif FIENDARENA
+       gamemode = GAME_FIENDARENA;
+#elif NEHAHRA
+       gamemode = GAME_NEHAHRA;
 #else
-       if (COM_CheckParm ("-rogue"))
-       {
-               rogue = true;
-               standard_quake = false;
-       }
-
-       if (COM_CheckParm ("-hipnotic"))
-       {
-               hipnotic = true;
-               standard_quake = false;
-       }
-
-       if (COM_CheckParm ("-nehahra"))
+       if (COM_CheckParm ("-zymotic"))
+               gamemode = GAME_ZYMOTIC;
+       else if (COM_CheckParm ("-fiendarena"))
+               gamemode = GAME_FIENDARENA;
+       else if (COM_CheckParm ("-nehahra"))
+               gamemode = GAME_NEHAHRA;
+       else if (COM_CheckParm ("-hipnotic"))
+               gamemode = GAME_HIPNOTIC;
+       else if (COM_CheckParm ("-rogue"))
+               gamemode = GAME_ROGUE;
+#endif
+       switch(gamemode)
        {
-               nehahra = true;
-               standard_quake = false;
+       case GAME_NORMAL:
+               gamename = "DarkPlaces";
+               break;
+       case GAME_HIPNOTIC:
+               gamename = "Darkplaces-Hipnotic";
+               break;
+       case GAME_ROGUE:
+               gamename = "Darkplaces-Rogue";
+               break;
+       case GAME_NEHAHRA:
+               gamename = "DarkPlaces-Nehahra";
+               break;
+       case GAME_FIENDARENA:
+               gamename = "FiendArena";
+               break;
+       case GAME_ZYMOTIC:
+               gamename = "Zymotic";
+               break;
+       default:
+               Sys_Error("COM_InitArgv: unknown gamemode %i\n", gamemode);
+               break;
        }
-#endif
 }
 
 
@@ -1378,7 +1399,7 @@ void COM_WriteFile (char *filename, void *data, int len)
 {
        int             handle;
        char    name[MAX_OSPATH];
-       
+
        sprintf (name, "%s/%s", com_gamedir, filename);
 
        // LordHavoc: added this
@@ -1390,8 +1411,8 @@ void COM_WriteFile (char *filename, void *data, int len)
                Sys_Printf ("COM_WriteFile: failed on %s\n", name);
                return;
        }
-       
-       Sys_Printf ("COM_WriteFile: %s\n", name);
+
+       Con_Printf ("COM_WriteFile: %s\n", name);
        Sys_FileWrite (handle, data, len);
        Sys_FileClose (handle);
 }
@@ -1846,21 +1867,32 @@ void COM_InitFilesystem (void)
                com_cachedir[0] = 0;
 #endif
 
-//
 // start up with GAMENAME by default (id1)
-//
        COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
 
-#ifdef NEHAHRA
-       COM_AddGameDirectory (va("%s/nehahra", basedir) );
-#else
-       if (COM_CheckParm ("-rogue"))
-               COM_AddGameDirectory (va("%s/rogue", basedir) );
-       if (COM_CheckParm ("-hipnotic"))
+       switch(gamemode)
+       {
+       case GAME_NORMAL:
+               break;
+       case GAME_HIPNOTIC:
                COM_AddGameDirectory (va("%s/hipnotic", basedir) );
-       if (COM_CheckParm ("-nehahra"))
+               break;
+       case GAME_ROGUE:
+               COM_AddGameDirectory (va("%s/rogue", basedir) );
+               break;
+       case GAME_NEHAHRA:
                COM_AddGameDirectory (va("%s/nehahra", basedir) );
-#endif
+               break;
+       case GAME_FIENDARENA:
+               COM_AddGameDirectory (va("%s/fiendarena", basedir) );
+               break;
+       case GAME_ZYMOTIC:
+               COM_AddGameDirectory (va("%s/zymotic", basedir) );
+               break;
+       default:
+               Sys_Error("COM_InitFilesystem: unknown gamemode %i\n", gamemode);
+               break;
+       }
 
 //
 // -game <gamedir>
@@ -1886,7 +1918,7 @@ void COM_InitFilesystem (void)
                {
                        if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
                                break;
-                       
+
                        search = Hunk_AllocName (sizeof(searchpath_t), "pack info");
                        if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
                        {
@@ -1924,7 +1956,7 @@ int COM_FileExists(char *filename)
                }
                else
                {
-                       sprintf (netpath, "%s/%s",search->filename, filename);               
+                       sprintf (netpath, "%s/%s",search->filename, filename);
                        findtime = Sys_FileTime (netpath);
                        if (findtime != -1)
                                return true;
index 98467fd3236745027bc53fca790f36563512321f..c7a0be34ac525a6b95bdeb4565e94d2fce4c547f 100644 (file)
--- a/common.h
+++ b/common.h
@@ -213,7 +213,15 @@ int COM_FileExists(char *filename);
 
 extern struct cvar_s   registered;
 
-extern qboolean                standard_quake, rogue, hipnotic, nehahra;
+#define GAME_NORMAL 0
+#define GAME_HIPNOTIC 1
+#define GAME_ROGUE 2
+#define GAME_NEHAHRA 3
+#define GAME_FIENDARENA 4
+#define GAME_ZYMOTIC 5
+
+extern int gamemode;
+extern char *gamename;
 
 // LordHavoc: useful...
 extern void COM_ToLowerString(char *in, char *out);
index 218ea632fbb918b3c78d0c9ac73d8f68dcf6d221..2fe6eea9783840601d5997b3265567b5e72e1637 100644 (file)
--- a/console.c
+++ b/console.c
@@ -160,7 +160,7 @@ void Con_CheckResize (void)
        int             i, j, width, oldwidth, oldtotallines, numlines, numchars;
        char    tbuf[CON_TEXTSIZE];
 
-       width = (vid.width >> 3) - 2;
+       width = (vid.conwidth >> 3) - 2;
 
        if (width == con_linewidth)
                return;
diff --git a/draw.h b/draw.h
index 58efe1b2978f5d93b6059c8d9507ed827ff3eda4..80ba2d18920dd96b6d27719f11a14da82c22a11e 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -32,5 +32,6 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation);
 void Draw_ConsoleBackground (int lines);
 void Draw_Fill (int x, int y, int w, int h, int c);
 void Draw_String (int x, int y, char *str, int maxlen); // LordHavoc: added maxlen
+void Draw_AdditiveString (int x, int y, char *str, int maxlen);
 qpic_t *Draw_PicFromWad (char *name);
 qpic_t *Draw_CachePic (char *path);
index 8e0b3dc6025278c4c271c7a034e99b12589f1587..bf3de8f98252d974c1098baaca33aa57e3aa9236 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -154,7 +154,7 @@ void gl_draw_newmap(void)
 {
 }
 
-char engineversion[40];
+extern char engineversion[40];
 int engineversionx, engineversiony;
 
 extern void R_Textures_Init();
@@ -163,17 +163,10 @@ void GL_Draw_Init (void)
        int i;
        Cvar_RegisterVariable (&scr_conalpha);
 
-#if defined(__linux__)
-       sprintf (engineversion, "DarkPlaces Linux   GL %.2f build %3i", (float) VERSION, buildnumber);
-#elif defined(WIN32)
-       sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
-#else
-       sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
-#endif
        for (i = 0;i < 40 && engineversion[i];i++)
                engineversion[i] += 0x80; // shift to orange
-       engineversionx = vid.width - strlen(engineversion) * 8 - 8;
-       engineversiony = vid.height - 8;
+       engineversionx = vid.conwidth - strlen(engineversion) * 8 - 8;
+       engineversiony = vid.conheight - 8;
 
        R_Textures_Init();
        R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
@@ -212,7 +205,7 @@ void Draw_Character (int x, int y, int num)
                return;
        glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
        // LordHavoc: NEAREST mode on text if not scaling up
-       if (glwidth <= (int) vid.width)
+       if (vid.realwidth <= (int) vid.conwidth)
        {
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -239,7 +232,7 @@ void Draw_Character (int x, int y, int num)
        glEnd ();
 
        // LordHavoc: revert to LINEAR mode
-//     if (glwidth < (int) vid.width)
+//     if (vid.realwidth <= (int) vid.conwidth)
 //     {
 //             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 //             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -258,7 +251,7 @@ void Draw_String (int x, int y, char *str, int maxlen)
        float frow, fcol;
        if (!r_render.value)
                return;
-       if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
+       if (y <= -8 || y >= (int) vid.conheight || x >= (int) vid.conwidth || *str == 0) // completely offscreen or no text to print
                return;
        if (maxlen < 1)
                maxlen = strlen(str);
@@ -267,7 +260,7 @@ void Draw_String (int x, int y, char *str, int maxlen)
        glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
 
        // LordHavoc: NEAREST mode on text if not scaling up
-       if (glwidth <= (int) vid.width)
+       if (vid.realwidth <= (int) vid.conwidth)
        {
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -283,7 +276,7 @@ void Draw_String (int x, int y, char *str, int maxlen)
        else
                glColor3f(1.0f,1.0f,1.0f);
        glBegin (GL_QUADS);
-       while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
+       while (maxlen-- && x < (int) vid.conwidth) // stop rendering when out of characters or room
        {
                if ((num = *str++) != 32) // skip spaces
                {
@@ -299,13 +292,22 @@ void Draw_String (int x, int y, char *str, int maxlen)
        glEnd ();
 
        // LordHavoc: revert to LINEAR mode
-//     if (glwidth < (int) vid.width)
+//     if (vid.realwidth < (int) vid.conwidth)
 //     {
 //             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 //             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 //     }
 }
 
+void Draw_AdditiveString (int x, int y, char *str, int maxlen)
+{
+       if (!r_render.value)
+               return;
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+       Draw_String(x, y, str, maxlen);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
 void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height)
 {
        if (!r_render.value)
@@ -397,9 +399,9 @@ Draw_ConsoleBackground
 */
 void Draw_ConsoleBackground (int lines)
 {
-       Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value*lines/vid.height, 0, lines - vid.height, vid.width, vid.height);
+       Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value * lines / vid.conheight, 0, lines - vid.conheight, vid.conwidth, vid.conheight);
        // LordHavoc: draw version
-       Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
+       Draw_String(engineversionx, lines - vid.conheight + engineversiony, engineversion, 9999);
 }
 
 /*
@@ -448,11 +450,11 @@ void GL_Set2D (void)
 {
        if (!r_render.value)
                return;
-       glViewport (glx, gly, glwidth, glheight);
+       glViewport (vid.realx, vid.realy, vid.realwidth, vid.realheight);
 
        glMatrixMode(GL_PROJECTION);
     glLoadIdentity ();
-       glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
+       glOrtho  (0, vid.conwidth, vid.conheight, 0, -99999, 99999);
 
        glMatrixMode(GL_MODELVIEW);
     glLoadIdentity ();
@@ -503,7 +505,7 @@ void SHOWLMP_decodeshow(void)
        float x, y;
        strcpy(lmplabel,MSG_ReadString());
        strcpy(picname, MSG_ReadString());
-       if (nehahra) // LordHavoc: nasty old legacy junk
+       if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
        {
                x = MSG_ReadByte();
                y = MSG_ReadByte();
index 035e5b09486a1a6f451627789b3fa5621daccb70..1a18c9512d3be1f57b9bb5994517a782149ba1fe 100644 (file)
@@ -266,7 +266,7 @@ void R_AliasLerpVerts(int vertcount,
        }
 }
 
-void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr)
+void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *m)
 {
        if (!r_render.value)
                return;
@@ -284,7 +284,7 @@ void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr)
                glEnableClientState(GL_COLOR_ARRAY);
        }
 
-       glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+       glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata));
 
        if (colors)
                glDisableClientState(GL_COLOR_ARRAY);
@@ -317,51 +317,65 @@ R_DrawAliasFrame
 
 =================
 */
-void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor);
-void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t **skin, int colormap, int effects, int flags)
+void R_DrawAliasFrame (void)
 {
+       maliashdr_t *m = Mod_Extradata(currentrenderentity->model);
+//     int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2;
+//     int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader);
+       int *skinanimrange = currentrenderentity->model->skinanimrange;
+       int skin;
+       rtexture_t **skinanim = currentrenderentity->model->skinanim;
+       rtexture_t **skinset;
+
+       skinanimrange += currentrenderentity->skinnum * 2;
+       skin = skinanimrange[0];
+       if (skinanimrange[1] > 1) // animated
+               skin += (int) (cl.time * 10) % skinanimrange[1];
+       skinset = skinanim + skin * 5;
+
        if (gl_transform.value)
        {
                if (r_render.value)
                {
                        glPushMatrix();
-                       GL_SetupModelTransform(org, angles, scale);
+                       GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
                }
        }
        // always needed, for model lighting
-       softwaretransformforentity(ent);
+       softwaretransformforentity(currentrenderentity);
+
+       R_AliasLerpVerts(m->numverts,
+               currentrenderentity->frameblend[0].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[0].frame * m->numverts, m->scale, m->scale_origin,
+               currentrenderentity->frameblend[1].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[1].frame * m->numverts, m->scale, m->scale_origin,
+               currentrenderentity->frameblend[2].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[2].frame * m->numverts, m->scale, m->scale_origin,
+               currentrenderentity->frameblend[3].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[3].frame * m->numverts, m->scale, m->scale_origin);
 
-       R_AliasLerpVerts(maliashdr->numverts,
-               blend[0].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[0].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
-               blend[1].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[1].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
-               blend[2].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[2].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
-               blend[3].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[3].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin);
        if (!gl_transform.value)
-               R_AliasTransformVerts(maliashdr->numverts);
+               R_AliasTransformVerts(m->numverts);
 
        // prep the vertex array as early as possible
        if (r_render.value)
        {
                glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
                glEnableClientState(GL_VERTEX_ARRAY);
-               glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) maliashdr->texdata + (int) maliashdr));
+               glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) m->texdata + (int) m));
                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-               GL_LockArray(0, maliashdr->numverts);
+               GL_LockArray(0, m->numverts);
        }
 
-       R_LightModel(ent, maliashdr->numverts, org, color);
+       R_LightModel(m->numverts);
 
        if (!r_render.value)
                return;
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glShadeModel(GL_SMOOTH);
-       if (effects & EF_ADDITIVE)
+//     glShadeModel(GL_SMOOTH);
+       if (currentrenderentity->effects & EF_ADDITIVE)
        {
                glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
                glEnable(GL_BLEND);
                glDepthMask(0);
        }
-       else if (alpha != 1.0 || (model->flags2 & MODF_TRANSPARENT))
+       else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT))
        {
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glEnable(GL_BLEND);
@@ -373,40 +387,41 @@ void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3
                glDepthMask(1);
        }
 
-       if (skin[0] || skin[1] || skin[2] || skin[3] || skin[4])
+       if (skinset[0] || skinset[1] || skinset[2] || skinset[3] || skinset[4])
        {
-               if (colormap >= 0 && (skin[0] || skin[1] || skin[2]))
+               if (currentrenderentity->colormap >= 0 && (skinset[0] || skinset[1] || skinset[2]))
                {
                        int c;
-                       if (skin[0])
-                               GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
-                       if (skin[1])
+                       if (skinset[0])
+                               GL_DrawModelMesh(skinset[0], aliasvertcolor, m);
+                       if (skinset[1])
                        {
-                               c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
-                               R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
-                               GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
+                               c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+                               R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c]));
+                               GL_DrawModelMesh(skinset[1], aliasvertcolor2, m);
                        }
-                       if (skin[2])
+                       if (skinset[2])
                        {
-                               c = colormap & 0xF0      ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
-                               R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
-                               GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
+                               c = currentrenderentity->colormap & 0xF0      ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+                               R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c]));
+                               GL_DrawModelMesh(skinset[2], aliasvertcolor2, m);
                        }
                }
                else
                {
-                       if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
+                       if (skinset[4])
+                               GL_DrawModelMesh(skinset[4], aliasvertcolor, m);
                        else
                        {
-                               if (skin[0]) GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
-                               if (skin[1]) GL_DrawModelMesh(skin[1], aliasvertcolor, maliashdr);
-                               if (skin[2]) GL_DrawModelMesh(skin[2], aliasvertcolor, maliashdr);
+                               if (skinset[0]) GL_DrawModelMesh(skinset[0], aliasvertcolor, m);
+                               if (skinset[1]) GL_DrawModelMesh(skinset[1], aliasvertcolor, m);
+                               if (skinset[2]) GL_DrawModelMesh(skinset[2], aliasvertcolor, m);
                        }
                }
-               if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+               if (skinset[3]) GL_DrawModelMesh(skinset[3], NULL, m);
        }
        else
-               GL_DrawModelMesh(0, NULL, maliashdr);
+               GL_DrawModelMesh(0, NULL, m);
 
        if (fogenabled)
        {
@@ -416,14 +431,15 @@ void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3
                glEnable (GL_BLEND);
                glDepthMask(0); // disable zbuffer updates
 
-               VectorSubtract(org, r_origin, diff);
+               VectorSubtract(currentrenderentity->origin, r_origin, diff);
                glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
 
-               glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+               glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata));
 
                glEnable (GL_TEXTURE_2D);
                glColor3f (1,1,1);
        }
+
        GL_UnlockArray();
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
@@ -441,41 +457,74 @@ R_DrawQ2AliasFrame
 
 =================
 */
-void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t *skin, int effects, int flags)
+void R_DrawQ2AliasFrame (void)
 {
        int *order, count;
        md2frame_t *frame1, *frame2, *frame3, *frame4;
+       vec3_t diff;
+       md2mem_t *m = Mod_Extradata(currentrenderentity->model);
+//     int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2;
+//     int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader);
+       int *skinanimrange = currentrenderentity->model->skinanimrange;
+       int skin;
+       rtexture_t **skinanim = currentrenderentity->model->skinanim;
+       rtexture_t **skinset;
+
+       skinanimrange += currentrenderentity->skinnum * 2;
+       skin = skinanimrange[0];
+       if (skinanimrange[1] > 1) // animated
+               skin += (int) (cl.time * 10) % skinanimrange[1];
+       skinset = skinanim + skin * 5;
 
        if (r_render.value)
-               glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin));
+               glBindTexture(GL_TEXTURE_2D, R_GetTexture(skinset[0]));
 
        if (gl_transform.value)
        {
                if (r_render.value)
                {
                        glPushMatrix();
-                       GL_SetupModelTransform(org, angles, scale);
+                       GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
                }
        }
        // always needed, for model lighting
-       softwaretransformforentity(ent);
-
-       frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[0].frame));
-       frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[1].frame));
-       frame3 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[2].frame));
-       frame4 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[3].frame));
-       R_AliasLerpVerts(pheader->num_xyz,
-               blend[0].lerp, frame1->verts, frame1->scale, frame1->translate,
-               blend[1].lerp, frame2->verts, frame2->scale, frame2->translate,
-               blend[2].lerp, frame3->verts, frame3->scale, frame3->translate,
-               blend[3].lerp, frame4->verts, frame4->scale, frame4->translate);
+       softwaretransformforentity(currentrenderentity);
+
+       frame1 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[0].frame));
+       frame2 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[1].frame));
+       frame3 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[2].frame));
+       frame4 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[3].frame));
+       R_AliasLerpVerts(m->num_xyz,
+               currentrenderentity->frameblend[0].lerp, frame1->verts, frame1->scale, frame1->translate,
+               currentrenderentity->frameblend[1].lerp, frame2->verts, frame2->scale, frame2->translate,
+               currentrenderentity->frameblend[2].lerp, frame3->verts, frame3->scale, frame3->translate,
+               currentrenderentity->frameblend[3].lerp, frame4->verts, frame4->scale, frame4->translate);
        if (!gl_transform.value)
-               R_AliasTransformVerts(pheader->num_xyz);
+               R_AliasTransformVerts(m->num_xyz);
 
-       R_LightModel(ent, pheader->num_xyz, org, color);
+       R_LightModel(m->num_xyz);
 
        if (!r_render.value)
                return;
+
+       if (currentrenderentity->effects & EF_ADDITIVE)
+       {
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
+               glEnable(GL_BLEND);
+               glDepthMask(0);
+       }
+       else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT))
+       {
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable(GL_BLEND);
+               glDepthMask(0);
+       }
+       else
+       {
+               glDisable(GL_BLEND);
+               glDepthMask(1);
+       }
+
        // LordHavoc: big mess...
        // using vertex arrays only slightly, although it is enough to prevent duplicates
        // (saving half the transforms)
@@ -484,7 +533,7 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
 
-       order = (int *)((int)pheader + pheader->ofs_glcmds);
+       order = (int *)((int)m + m->ofs_glcmds);
        while(1)
        {
                if (!(count = *order++))
@@ -514,11 +563,9 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glEnable (GL_BLEND);
                glDepthMask(0); // disable zbuffer updates
-               {
-                       vec3_t diff;
-                       VectorSubtract(org, r_origin, diff);
-                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
-               }
+
+               VectorSubtract(currentrenderentity->origin, r_origin, diff);
+               glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
 
                // LordHavoc: big mess...
                // using vertex arrays only slightly, although it is enough to prevent duplicates
@@ -526,7 +573,7 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t
                glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
                glEnableClientState(GL_VERTEX_ARRAY);
 
-               order = (int *)((int)pheader + pheader->ofs_glcmds);
+               order = (int *)((int)m + m->ofs_glcmds);
                while(1)
                {
                        if (!(count = *order++))
@@ -880,25 +927,26 @@ void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
 R_DrawZymoticFrame
 =================
 */
-void R_DrawZymoticFrame (model_t *model, zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, int skinblah, int effects, int flags)
+void R_DrawZymoticFrame (void)
 {
-       ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), blend, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles, scale);
+       zymtype1header_t *m = Mod_Extradata(currentrenderentity->model);
+       ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), currentrenderentity->frameblend, (zymbone_t *)(m->lump_bones.start + (int) m), currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
        ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
        ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
 
-       R_LightModel(ent, m->numverts, org, color);
+       R_LightModel(m->numverts);
 
        if (!r_render.value)
                return;
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glShadeModel(GL_SMOOTH);
-       if (effects & EF_ADDITIVE)
+//     glShadeModel(GL_SMOOTH);
+       if (currentrenderentity->effects & EF_ADDITIVE)
        {
                glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
                glEnable(GL_BLEND);
                glDepthMask(0);
        }
-       else if (alpha != 1.0)
+       else if (currentrenderentity->alpha != 1.0)
        {
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                glEnable(GL_BLEND);
@@ -913,7 +961,7 @@ void R_DrawZymoticFrame (model_t *model, zymtype1header_t *m, float alpha, vec3_
        GL_DrawZymoticModelMesh(aliasvertcolor, m);
 
        if (fogenabled)
-               GL_DrawZymoticModelMeshFog(org, m);
+               GL_DrawZymoticModelMeshFog(currentrenderentity->origin, m);
 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable (GL_BLEND);
@@ -926,51 +974,21 @@ R_DrawAliasModel
 
 =================
 */
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap)
+void R_DrawAliasModel (void)
 {
-       int                     i;
-       vec3_t          mins, maxs, color;
-       void            *modelheader;
-       rtexture_t      **skinset;
-
-       if (alpha < (1.0 / 64.0))
+       if (currentrenderentity->alpha < (1.0 / 64.0))
                return; // basically completely transparent
 
-       VectorAdd (org, clmodel->mins, mins);
-       VectorAdd (org, clmodel->maxs, maxs);
-
-//     if (cull && R_CullBox (mins, maxs))
-//             return;
-
        c_models++;
 
-       if (skin < 0 || skin >= clmodel->numskins)
-       {
-               skin = 0;
-               Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
-       }
-
-       modelheader = Mod_Extradata (clmodel);
-
-       {
-//             int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
-//             int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
-               int *skinanimrange = clmodel->skinanimrange + skin * 2;
-               rtexture_t **skinanim = clmodel->skinanim;
-               i = skinanimrange[0];
-               if (skinanimrange[1] > 1) // animated
-                       i += ((int) (cl.time * 10) % skinanimrange[1]);
-               skinset = skinanim + i*5;
-       }
-
        if (r_render.value)
                glEnable (GL_TEXTURE_2D);
 
-       c_alias_polys += clmodel->numtris;
-       if (clmodel->aliastype == ALIASTYPE_ZYM)
-               R_DrawZymoticFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, 0                   , effects, flags);
-       else if (clmodel->aliastype == ALIASTYPE_MD2)
-               R_DrawQ2AliasFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset[0]          , effects, flags);
+       c_alias_polys += currentrenderentity->model->numtris;
+       if (currentrenderentity->model->aliastype == ALIASTYPE_ZYM)
+               R_DrawZymoticFrame ();
+       else if (currentrenderentity->model->aliastype == ALIASTYPE_MD2)
+               R_DrawQ2AliasFrame ();
        else
-               R_DrawAliasFrame   (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset   , colormap, effects, flags);
+               R_DrawAliasFrame   ();
 }
index 0f35ab8576e19a5230a8915cae5223e1e79cc386..8750595a38f6ea1fd26264d75e31ef1a92c3e8b9 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -1,8 +1,18 @@
 #include "quakedef.h"
 
+typedef struct
+{
+       unsigned short tex;
+       unsigned short type;
+       int indices;
+}
+rendertranspoly_t;
+
 transvert_t *transvert;
 transpoly_t *transpoly;
-unsigned short *transpolyindex;
+rendertranspoly_t *rendertranspoly;
+int *transpolyindex;
+int *transvertindex;
 wallvert_t *wallvert;
 wallvertcolor_t *wallvertcolor;
 wallpoly_t *wallpoly;
@@ -16,11 +26,13 @@ int currentwallvert;
 int currentskypoly;
 int currentskyvert;
 
+
 void LoadSky_f(void);
 
 cvar_t r_multitexture = {0, "r_multitexture", "1"};
 cvar_t r_skyquality = {CVAR_SAVE, "r_skyquality", "2"};
 cvar_t r_mergesky = {CVAR_SAVE, "r_mergesky", "0"};
+cvar_t gl_transpolytris = {0, "gl_transpolytris", "0"};
 
 static char skyworldname[1024];
 static rtexture_t *mergeskytexture;
@@ -29,7 +41,7 @@ static rtexture_t *alphaskytexture, *alphaskytexture_half;
 static qboolean skyavailable_quake;
 static qboolean skyavailable_box;
 
-void R_BuildSky (int scrollupper, int scrolllower);
+static void R_BuildSky (int scrollupper, int scrolllower);
 
 typedef struct translistitem_s
 {
@@ -47,12 +59,14 @@ float transviewdist; // distance of view origin along the view normal
 
 float transreciptable[256];
 
-void gl_poly_start(void)
+static void gl_poly_start(void)
 {
        int i;
        transvert = qmalloc(MAX_TRANSVERTS * sizeof(transvert_t));
        transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
-       transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(unsigned short));
+       rendertranspoly = qmalloc(MAX_TRANSPOLYS * sizeof(rendertranspoly_t));
+       transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(int));
+       transvertindex = qmalloc(MAX_TRANSVERTS * sizeof(int));
        wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t));
        wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t));
        wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t));
@@ -63,11 +77,13 @@ void gl_poly_start(void)
                transreciptable[i] = 1.0f / i;
 }
 
-void gl_poly_shutdown(void)
+static void gl_poly_shutdown(void)
 {
        qfree(transvert);
        qfree(transpoly);
+       qfree(rendertranspoly);
        qfree(transpolyindex);
+       qfree(transvertindex);
        qfree(wallvert);
        qfree(wallvertcolor);
        qfree(wallpoly);
@@ -75,7 +91,7 @@ void gl_poly_shutdown(void)
        qfree(skypoly);
 }
 
-void gl_poly_newmap(void)
+static void gl_poly_newmap(void)
 {
        skyavailable_box = false;
        skyavailable_quake = false;
@@ -89,6 +105,7 @@ void GL_Poly_Init(void)
        Cvar_RegisterVariable (&r_multitexture);
        Cvar_RegisterVariable (&r_skyquality);
        Cvar_RegisterVariable (&r_mergesky);
+       Cvar_RegisterVariable (&gl_transpolytris);
        R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown, gl_poly_newmap);
 }
 
@@ -100,42 +117,7 @@ void transpolyclear(void)
        transviewdist = DotProduct(r_origin, vpn);
 }
 
-// turned into a #define
-/*
-void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype)
-{
-       if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS)
-               return;
-       transpoly[currenttranspoly].texnum = (unsigned short) texnum;
-       transpoly[currenttranspoly].glowtexnum = (unsigned short) glowtexnum;
-       transpoly[currenttranspoly].fogtexnum = (unsigned short) fogtexnum;
-       transpoly[currenttranspoly].transpolytype = (unsigned short) transpolytype;
-       transpoly[currenttranspoly].firstvert = currenttransvert;
-       transpoly[currenttranspoly].verts = 0;
-//     transpoly[currenttranspoly].ndist = 0; // clear the normal
-}
-*/
-
-// turned into a #define
-/*
-void transpolyvert(float x, float y, float z, float s, float t, int r, int g, int b, int a)
-{
-       int i;
-       if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS)
-               return;
-       transvert[currenttransvert].s = s;
-       transvert[currenttransvert].t = t;
-       transvert[currenttransvert].r = bound(0, r, 255);
-       transvert[currenttransvert].g = bound(0, g, 255);
-       transvert[currenttransvert].b = bound(0, b, 255);
-       transvert[currenttransvert].a = bound(0, a, 255);
-       transvert[currenttransvert].v[0] = x;
-       transvert[currenttransvert].v[1] = y;
-       transvert[currenttransvert].v[2] = z;
-       currenttransvert++;
-       transpoly[currenttranspoly].verts++;
-}
-*/
+// transpolybegin and transpolyvert are #define macros
 
 void transpolyend(void)
 {
@@ -174,207 +156,367 @@ void transpolyend(void)
        currenttranspoly++;
 }
 
-int transpolyindices;
+void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2)
+{
+       float center, scale2;
+       int i;
+       vec3_t corner;
+       byte br, bg, bb, ba;
+       transpoly_t *p;
+       transvert_t *v;
+       center = DotProduct(org, vpn) - transviewdist;
+       if (center < 4.0f || currenttranspoly >= MAX_TRANSPOLYS || (currenttransvert + 4) > MAX_TRANSVERTS)
+               return;
+
+       p = transpoly + (currenttranspoly++);
+       v = transvert + currenttransvert;
+
+       if (lighthalf)
+       {
+               ir >>= 1;
+               ig >>= 1;
+               ib >>= 1;
+       }
+       ir = bound(0, ir, 255);
+       ig = bound(0, ig, 255);
+       ib = bound(0, ib, 255);
+       br = (byte) ir;
+       bg = (byte) ig;
+       bb = (byte) ib;
+
+#if SLOWMATH
+       i = (int) alphaf;
+       if (i > 255)
+               i = 255;
+       ba = (byte) i;
+
+       i = (int) center;
+#else
+       alphaf += 8388608.0f;
+       i = *((long *)&alphaf) & 0x007FFFFF;
+       if (i > 255)
+               i = 255;
+       ba = (byte) i;
+
+       center += 8388608.0f;
+       i = *((long *)&center) & 0x007FFFFF;
+#endif
+       i = bound(0, i, 4095);
+       currenttranslist->next = translisthash[i];
+       currenttranslist->poly = p;
+       translisthash[i] = currenttranslist++;
+
+       p->texnum = p->fogtexnum = texnum;
+       p->glowtexnum = 0;
+       p->transpolytype = transpolytype;
+       p->firstvert = currenttransvert;
+       p->verts = 4;
+       currenttransvert += 4;
+
+       scale2 = scale * -0.5f;
+       corner[0] = org[0] + (up[0] + right[0]) * scale2;
+       corner[1] = org[1] + (up[1] + right[1]) * scale2;
+       corner[2] = org[2] + (up[2] + right[2]) * scale2;
+       v->s = s1;
+       v->t = t1;
+       v->r = br;
+       v->g = bg;
+       v->b = bb;
+       v->a = ba;
+       v->v[0] = corner[0];
+       v->v[1] = corner[1];
+       v->v[2] = corner[2];
+       v++;
+       v->s = s1;
+       v->t = t2;
+       v->r = br;
+       v->g = bg;
+       v->b = bb;
+       v->a = ba;
+       v->v[0] = corner[0] + up[0] * scale;
+       v->v[1] = corner[1] + up[1] * scale;
+       v->v[2] = corner[2] + up[2] * scale;
+       v++;
+       v->s = s2;
+       v->t = t2;
+       v->r = br;
+       v->g = bg;
+       v->b = bb;
+       v->a = ba;
+       v->v[0] = corner[0] + (up[0] + right[0]) * scale;
+       v->v[1] = corner[1] + (up[1] + right[1]) * scale;
+       v->v[2] = corner[2] + (up[2] + right[2]) * scale;
+       v++;
+       v->s = s2;
+       v->t = t1;
+       v->r = br;
+       v->g = bg;
+       v->b = bb;
+       v->a = ba;
+       v->v[0] = corner[0] + right[0] * scale;
+       v->v[1] = corner[1] + right[1] * scale;
+       v->v[2] = corner[2] + right[2] * scale;
+       v++;
+}
 
 void transpolyrender(void)
 {
-       int i, j, tpolytype, texnum;
-       transpoly_t *p;
+       int                             i, j, k, l, tpolytype, texnum, transvertindices, alpha, currentrendertranspoly;
+       byte                    fogr, fogg, fogb;
+       vec3_t                  diff;
+       transpoly_t             *p;
+       rendertranspoly_t *r, *rend;
+       translistitem   *item;
+
        if (!r_render.value)
                return;
        if (currenttranspoly < 1)
                return;
-//     transpolyrenderminmax();
-//     if (transpolyindices < 1)
-//             return;
-       // testing
-//     Con_DPrintf("transpolyrender: %i polys %i infront %i vertices\n", currenttranspoly, transpolyindices, currenttransvert);
-//     if (transpolyindices >= 2)
-//             transpolysort();
+
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glEnable(GL_BLEND);
-       glShadeModel(GL_SMOOTH);
+//     glShadeModel(GL_SMOOTH);
        glDepthMask(0); // disable zbuffer updates
-       glDisable(GL_ALPHA_TEST);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       tpolytype = TPOLYTYPE_ALPHA;
-       texnum = -1;
-       /*
-       if (gl_vertexarrays.value)
+
+       // set up the vertex array
+       glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(transvert[0]), transvert);
+
+       currentrendertranspoly = 0;
+       transvertindices = 0;
+       fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
+       fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
+       fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
+       if (gl_transpolytris.value)
        {
-               // set up the vertex array
-               glInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert);
-               for (i = 0;i < transpolyindices;i++)
+               int glowtexnum, fogtexnum;
+               for (i = 4095;i >= 0;i--)
                {
-                       p = &transpoly[transpolyindex[i]];
-                       if (p->texnum != texnum || p->transpolytype != tpolytype)
+                       item = translisthash[i];
+                       while(item)
                        {
-                               if (p->texnum != texnum)
+                               p = item->poly;
+                               item = item->next;
+                               glowtexnum = p->glowtexnum;
+                               fogtexnum = p->fogtexnum;
+
+#define POLYTOTRI(pfirstvert, ptexnum, ptranspolytype) \
+                               l = pfirstvert;\
+                               r = &rendertranspoly[currentrendertranspoly++];\
+                               r->tex = ptexnum;\
+                               r->type = ptranspolytype;\
+                               if (p->verts == 4)\
+                               {\
+                                       transvertindex[transvertindices] = l;\
+                                       transvertindex[transvertindices + 1] = l + 1;\
+                                       transvertindex[transvertindices + 2] = l + 2;\
+                                       transvertindex[transvertindices + 3] = l;\
+                                       transvertindex[transvertindices + 4] = l + 2;\
+                                       transvertindex[transvertindices + 5] = l + 3;\
+                                       transvertindices += 6;\
+                                       r->indices = 6;\
+                               }\
+                               else if (p->verts == 3)\
+                               {\
+                                       transvertindex[transvertindices] = l;\
+                                       transvertindex[transvertindices + 1] = l + 1;\
+                                       transvertindex[transvertindices + 2] = l + 2;\
+                                       transvertindices += 3;\
+                                       r->indices = 3;\
+                               }\
+                               else\
+                               {\
+                                       for (j = l + p->verts, k = l + 2;k < j;k++)\
+                                       {\
+                                               transvertindex[transvertindices] = l;\
+                                               transvertindex[transvertindices + 1] = k - 1;\
+                                               transvertindex[transvertindices + 2] = k;\
+                                               transvertindices += 3;\
+                                       }\
+                                       r->indices = (p->verts - 2) * 3;\
+                               }
+
+                               POLYTOTRI(p->firstvert, p->texnum, p->transpolytype)
+
+                               if (p->glowtexnum)
                                {
-                                       texnum = p->texnum;
-                                       glBindTexture(GL_TEXTURE_2D, texnum);
+                                       // make another poly for glow effect
+                                       if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
+                                       {
+                                               memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+                                               POLYTOTRI(currenttransvert, p->glowtexnum, TPOLYTYPE_ADD)
+                                               for (j = 0;j < p->verts;j++)
+                                               {
+                                                       transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
+                                                       currenttransvert++;
+                                               }
+                                       }
                                }
-                               if (p->transpolytype != tpolytype)
+
+                               if (fogenabled)
                                {
-                                       tpolytype = p->transpolytype;
-                                       if (tpolytype == TPOLYTYPE_ADD) // additive
-                                               glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                                       else // alpha
-                                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                                       // make another poly for fog
+                                       if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
+                                       {
+                                               memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+                                               POLYTOTRI(currenttransvert, p->fogtexnum, TPOLYTYPE_ALPHA)
+                                               for (j = 0, k = p->firstvert;j < p->verts;j++, k++)
+                                               {
+                                                       transvert[currenttransvert].r = fogr;
+                                                       transvert[currenttransvert].g = fogg;
+                                                       transvert[currenttransvert].b = fogb;
+                                                       VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
+                                                       alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
+                                                       transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
+                                                       currenttransvert++;
+                                               }
+                                       }
                                }
                        }
-                       glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
-                       if (p->glowtexnum)
-                       {
-                               texnum = p->glowtexnum; // highly unlikely to match next poly, but...
-                               glBindTexture(GL_TEXTURE_2D, texnum);
-                               tpolytype = TPOLYTYPE_ADD; // might match next poly
-                               glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                               glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
-                       }
                }
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-               glDisableClientState(GL_COLOR_ARRAY);
-               glDisableClientState(GL_VERTEX_ARRAY);
        }
        else
-       */
        {
-               int points = -1;
-               translistitem *item;
-               transvert_t *vert;
                for (i = 4095;i >= 0;i--)
                {
                        item = translisthash[i];
-                       while (item)
+                       while(item)
                        {
                                p = item->poly;
                                item = item->next;
-                               if (p->texnum != texnum || p->verts != points || p->transpolytype != tpolytype)
-                               {
-                                       glEnd();
-                                       if (isG200)
-                                       {
-                                               // LordHavoc: Matrox G200 cards can't handle per pixel alpha
-                                               if (p->fogtexnum)
-                                                       glEnable(GL_ALPHA_TEST);
-                                               else
-                                                       glDisable(GL_ALPHA_TEST);
-                                       }
-                                       if (p->texnum != texnum)
-                                       {
-                                               texnum = p->texnum;
-                                               glBindTexture(GL_TEXTURE_2D, texnum);
-                                       }
-                                       if (p->transpolytype != tpolytype)
-                                       {
-                                               tpolytype = p->transpolytype;
-                                               if (tpolytype == TPOLYTYPE_ADD) // additive
-                                                       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                                               else // alpha
-                                                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                                       }
-                                       points = p->verts;
-                                       switch (points)
-                                       {
-                                       case 3:
-                                               glBegin(GL_TRIANGLES);
-                                               break;
-                                       case 4:
-                                               glBegin(GL_QUADS);
-                                               break;
-                                       default:
-                                               glBegin(GL_POLYGON);
-                                               points = -1; // to force a reinit on the next poly
-                                               break;
-                                       }
-                               }
-                               for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
-                               {
-                                       // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
-                                       glTexCoord2f(vert->s, vert->t);
-                                       // again, vector version isn't supported I think
-                                       glColor4ub(vert->r, vert->g, vert->b, vert->a);
-                                       glVertex3fv(vert->v);
-                               }
+
+                               l = p->firstvert;
+                               r = &rendertranspoly[currentrendertranspoly++];
+                               r->tex = p->texnum;
+                               r->type = p->transpolytype;
+                               r->indices = p->verts;
+
+                               for (j = l + p->verts, k = l;k < j;k++)
+                                       transvertindex[transvertindices++] = k;
+
                                if (p->glowtexnum)
                                {
-                                       glEnd();
-                                       texnum = p->glowtexnum; // highly unlikely to match next poly, but...
-                                       glBindTexture(GL_TEXTURE_2D, texnum);
-                                       if (tpolytype != TPOLYTYPE_ADD)
-                                       {
-                                               tpolytype = TPOLYTYPE_ADD; // might match next poly
-                                               glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                                       }
-                                       points = -1;
-                                       glBegin(GL_POLYGON);
-                                       for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
-                                       {
-                                               glColor4ub(255,255,255,vert->a);
-                                               // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
-                                               glTexCoord2f(vert->s, vert->t);
-                                               glVertex3fv(vert->v);
-                                       }
-                                       glEnd();
-                               }
-                               if (fogenabled && p->transpolytype == TPOLYTYPE_ALPHA)
-                               {
-                                       vec3_t diff;
-                                       glEnd();
-                                       points = -1; // to force a reinit on the next poly
-                                       if (tpolytype != TPOLYTYPE_ALPHA)
+                                       // make another poly for glow effect
+                                       if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
                                        {
-                                               tpolytype = TPOLYTYPE_ALPHA; // probably matchs next poly
-                                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                                       }
-                                       if (p->fogtexnum)
-                                       {
-                                               if (texnum != p->fogtexnum) // highly unlikely to match next poly, but...
-                                               {
-                                                       texnum = p->fogtexnum;
-                                                       glBindTexture(GL_TEXTURE_2D, texnum);
-                                               }
-                                               glBegin(GL_POLYGON);
-                                               for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
+                                               l = currenttransvert;
+                                               r = &rendertranspoly[currentrendertranspoly++];
+                                               r->tex = p->glowtexnum;
+                                               r->type = TPOLYTYPE_ADD;
+                                               r->indices = p->verts;
+
+                                               memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+                                               for (j = 0;j < p->verts;j++)
                                                {
-                                                       VectorSubtract(vert->v, r_origin, diff);
-                                                       glTexCoord2f(vert->s, vert->t);
-                                                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff)));
-                                                       glVertex3fv(vert->v);
+                                                       transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
+                                                       transvertindex[transvertindices++] = currenttransvert++;
                                                }
-                                               glEnd ();
                                        }
-                                       else
+                               }
+                               if (fogenabled)
+                               {
+                                       // make another poly for fog
+                                       if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
                                        {
-                                               glDisable(GL_TEXTURE_2D);
-                                               glBegin(GL_POLYGON);
-                                               for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
+                                               l = currenttransvert;
+                                               r = &rendertranspoly[currentrendertranspoly++];
+                                               r->tex = p->fogtexnum;
+                                               r->type = TPOLYTYPE_ALPHA;
+                                               r->indices = p->verts;
+
+                                               memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+                                               for (j = 0;j < p->verts;j++)
                                                {
-                                                       VectorSubtract(vert->v, r_origin, diff);
-                                                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff)));
-                                                       glVertex3fv(vert->v);
+                                                       transvert[currenttransvert].r = fogr;
+                                                       transvert[currenttransvert].g = fogg;
+                                                       transvert[currenttransvert].b = fogb;
+                                                       VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
+                                                       alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
+                                                       transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
+                                                       transvertindex[transvertindices++] = currenttransvert++;
                                                }
-                                               glEnd ();
-                                               glEnable(GL_TEXTURE_2D);
                                        }
                                }
                        }
                }
-               glEnd();
        }
 
+       GL_LockArray(0, currenttransvert);
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       tpolytype = TPOLYTYPE_ALPHA;
+       texnum = -1;
+       transvertindices = 0;
+       r = rendertranspoly;
+       rend = r + currentrendertranspoly;
+       while(r < rend)
+       {
+               if (texnum != r->tex)
+               {
+                       texnum = r->tex;
+                       glBindTexture(GL_TEXTURE_2D, texnum);
+               }
+               if (tpolytype != r->type)
+               {
+                       tpolytype = r->type;
+                       if (tpolytype == TPOLYTYPE_ADD) // additive
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       else // alpha
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               }
+               k = transvertindices;
+               if (gl_transpolytris.value)
+               {
+                       do
+                               transvertindices += r->indices, r++;
+                       while (r < rend && r->tex == texnum && r->type == tpolytype);
+                       glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+               }
+               else
+               {
+                       if (r->indices == 4)
+                       {
+                               do
+                                       transvertindices += 4, r++;
+                               while (r < rend && r->indices == 4 && r->tex == texnum && r->type == tpolytype);
+                               glDrawElements(GL_QUADS, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+                       }
+                       else if (r->indices == 3)
+                       {
+                               do
+                                       transvertindices += 3, r++;
+                               while (r < rend && r->indices == 3 && r->tex == texnum && r->type == tpolytype);
+                               glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+                       }
+                       else
+                       {
+                               transvertindices += r->indices, r++;
+                               glDrawElements(GL_POLYGON, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+                       }
+               }
+       }
+
+       GL_UnlockArray();
+
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glDepthMask(1); // enable zbuffer updates
-       glDisable(GL_ALPHA_TEST);
+       glDisable(GL_BLEND);
+       glColor3f(1,1,1);
+
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDisableClientState(GL_COLOR_ARRAY);
+       glDisableClientState(GL_VERTEX_ARRAY);
+
 }
 
 void wallpolyclear(void)
 {
+       if (!gl_mtexable)
+               r_multitexture.value = 0;
        currentwallpoly = currentwallvert = 0;
 }
 
-void wallpolyrender(void)
+// render walls and fullbrights, but not fog
+void wallpolyrender1(void)
 {
        int i, j, texnum, lighttexnum;
        wallpoly_t *p;
@@ -387,11 +529,9 @@ void wallpolyrender(void)
        c_brush_polys += currentwallpoly;
        // testing
        //Con_DPrintf("wallpolyrender: %i polys %i vertices\n", currentwallpoly, currentwallvert);
-       if (!gl_mtexable)
-               r_multitexture.value = 0;
        glDisable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glShadeModel(GL_FLAT);
+//     glShadeModel(GL_FLAT);
        // make sure zbuffer is enabled
        glEnable(GL_DEPTH_TEST);
 //     glDisable(GL_ALPHA_TEST);
@@ -401,7 +541,7 @@ void wallpolyrender(void)
        {
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
                texnum = -1;
-               for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+               for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
                {
                        if (p->texnum != texnum)
                        {
@@ -472,7 +612,7 @@ void wallpolyrender(void)
                }
                texnum = -1;
                lighttexnum = -1;
-               for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+               for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
                {
                        if (p->texnum != texnum)
                        {
@@ -508,7 +648,7 @@ void wallpolyrender(void)
                // first do the textures
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
                texnum = -1;
-               for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+               for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
                {
                        if (p->texnum != texnum)
                        {
@@ -549,10 +689,10 @@ void wallpolyrender(void)
        // switch to additive mode settings
        glDepthMask(0);
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+       glBlendFunc(GL_ONE, GL_ONE);
        glEnable(GL_BLEND);
 //     glDisable(GL_ALPHA_TEST);
-       glShadeModel(GL_SMOOTH);
+//     glShadeModel(GL_SMOOTH);
        // render vertex lit overlays ontop
        texnum = -1;
        for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
@@ -582,14 +722,13 @@ lit:
                glEnd();
        }
        // render glow textures
-       glShadeModel(GL_FLAT);
-       glBlendFunc(GL_ONE, GL_ONE);
+//     glShadeModel(GL_FLAT);
        if (lighthalf)
                glColor3f(0.5,0.5,0.5);
        else
                glColor3f(1,1,1);
        texnum = -1;
-       for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+       for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
        {
                if (!p->glowtexnum)
                        continue;
@@ -609,31 +748,54 @@ lit:
        }
        glColor3f(1,1,1);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glShadeModel(GL_SMOOTH);
+//     glDisable(GL_ALPHA_TEST);
+//     glShadeModel(GL_SMOOTH);
+       glDisable(GL_BLEND);
+       glDepthMask(1);
+}
+
+// render fog
+void wallpolyrender2(void)
+{
+       if (!r_render.value)
+               return;
+       if (currentwallpoly < 1)
+               return;
        if (fogenabled)
        {
+               int i, j, alpha, fogr, fogg, fogb;
+               wallpoly_t *p;
+               wallvert_t *vert;
                vec3_t diff;
+               glEnable(GL_DEPTH_TEST);
+               glDepthMask(0);
+               glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable(GL_BLEND);
+//             glShadeModel(GL_SMOOTH);
                glDisable(GL_TEXTURE_2D);
-               for (i = 0,p = &wallpoly[0];i < currentwallpoly;i++, p++)
+               fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
+               fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
+               fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
+               for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
                {
                        vert = &wallvert[p->firstvert];
                        glBegin(GL_POLYGON);
                        for (j=0 ; j<p->numverts ; j++, vert++)
                        {
                                VectorSubtract(vert->vert, r_origin, diff);
-                               glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+                               alpha = 255.0f * exp(fogdensity/DotProduct(diff,diff));
+                               alpha = bound(0, alpha, 255);
+                               glColor4ub(fogr, fogg, fogb, (byte) alpha);
                                glVertex3fv (vert->vert);
                        }
                        glEnd ();
                }
                glEnable(GL_TEXTURE_2D);
+               glColor3f(1,1,1);
+               glDisable(GL_BLEND);
+               glDepthMask(1);
        }
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-//     glDisable(GL_ALPHA_TEST);
-       glShadeModel(GL_SMOOTH);
-       glDisable(GL_BLEND);
-       glDepthMask(1);
 }
 
 static int skyrendersphere;
@@ -691,6 +853,8 @@ void skypolyclear(void)
 
 }
 
+static void R_Sky(void);
+
 void skypolyrender(void)
 {
        int i, j;
@@ -859,6 +1023,8 @@ void skypolyrender(void)
        }
        GL_UnlockArray();
        glDisableClientState(GL_VERTEX_ARRAY);
+
+       R_Sky();
 }
 
 static char skyname[256];
@@ -868,8 +1034,8 @@ static char skyname[256];
 R_SetSkyBox
 ==================
 */
-char   *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
-rtexture_t *skyboxside[6];
+static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
+static rtexture_t *skyboxside[6];
 int R_SetSkyBox(char *sky)
 {
        int             i;
@@ -900,7 +1066,7 @@ int R_SetSkyBox(char *sky)
                        sprintf (name, "gfx/env/%s%s", sky, suf[i]);
                        if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
                        {
-                               Con_Printf ("Couldn't load %s\n", name);
+                               Con_Printf ("Couldn't load env/%s%s or gfx/env/%s%s\n", sky, suf[i], sky, suf[i]);
                                continue;
                        }
                }
@@ -949,7 +1115,7 @@ void LoadSky_f (void)
        glTexCoord2f((s) * (254.0f/256.0f) + (1.0f/256.0f), (t) * (254.0f/256.0f) + (1.0f/256.0f));\
        glVertex3f((x) * 1024.0 + r_origin[0], (y) * 1024.0 + r_origin[1], (z) * 1024.0 + r_origin[2]);
 
-void R_SkyBox(void)
+static void R_SkyBox(void)
 {
        glDisable(GL_DEPTH_TEST);
        glDepthMask(0);
@@ -1006,9 +1172,9 @@ void R_SkyBox(void)
        glColor3f (1,1,1);
 }
 
-float skysphere[33*33*5];
-int skysphereindices[32*32*6];
-void skyspherecalc(float *sphere, float dx, float dy, float dz)
+static float skysphere[33*33*5];
+static int skysphereindices[32*32*6];
+static void skyspherecalc(float *sphere, float dx, float dy, float dz)
 {
        float a, b, x, ax, ay, v[3], length;
        int i, j, *index;
@@ -1047,7 +1213,7 @@ void skyspherecalc(float *sphere, float dx, float dy, float dz)
        }
 }
 
-void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2)
+static void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2)
 {
        float *v, *t, *t2;
        int i;
@@ -1068,7 +1234,7 @@ void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float
        }
 }
 
-void R_SkySphere(void)
+static void R_SkySphere(void)
 {
        float speedscale, speedscale2;
        float vert[33*33*4], tex[33*33*2], tex2[33*33*2];
@@ -1207,7 +1373,7 @@ void R_SkySphere(void)
        glColor3f (1,1,1);
 }
 
-void R_Sky(void)
+static void R_Sky(void)
 {
        if (!r_render.value)
                return;
@@ -1219,11 +1385,11 @@ void R_Sky(void)
 
 //===============================================================
 
-byte skyupperlayerpixels[128*128*4];
-byte skylowerlayerpixels[128*128*4];
-byte skymergedpixels[128*128*4];
+static byte skyupperlayerpixels[128*128*4];
+static byte skylowerlayerpixels[128*128*4];
+static byte skymergedpixels[128*128*4];
 
-void R_BuildSky (int scrollupper, int scrolllower)
+static void R_BuildSky (int scrollupper, int scrolllower)
 {
        int x, y, ux, uy, lx, ly;
        byte *m, *u, *l;
index 21665d71a600d691e7a973aa69dbe163acc205f2..6db5741e8469451aab0556481fcf3585cadc3709 100644 (file)
--- a/gl_poly.h
+++ b/gl_poly.h
@@ -9,9 +9,11 @@ extern void transpolyclear(void);
 extern void transpolyrender(void);
 extern void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype);
 extern void transpolyend(void);
+extern void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2);
 
 extern void wallpolyclear(void);
-extern void wallpolyrender(void);
+extern void wallpolyrender1(void);
+extern void wallpolyrender2(void);
 
 extern void skypolyclear(void);
 extern void skypolyrender(void);
@@ -88,7 +90,9 @@ skypoly_t;
 
 extern transvert_t *transvert;
 extern transpoly_t *transpoly;
-extern unsigned short *transpolyindex;
+extern int *transpolyindex;
+extern int *transvertindex;
+extern transpoly_t **transpolylist;
 extern wallvert_t *wallvert;
 extern wallvertcolor_t *wallvertcolor;
 extern wallpoly_t *wallpoly;
index ffa9226b28ea9440eb4c85f307ec9c5aba855253..f848defad3109e647fa9533251708d0c209c51ed 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -21,10 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-qboolean       r_cache_thrash;         // compatability
+//static qboolean      r_cache_thrash;         // compatability
 
-vec3_t         modelorg, r_entorigin;
-entity_t       *currententity;
+vec3_t         modelorg;
+entity_render_t        *currentrenderentity;
 
 int                    r_framecount;           // used for dlight push checking
 
@@ -46,8 +46,8 @@ vec3_t        vpn;
 vec3_t vright;
 vec3_t r_origin;
 
-float  r_world_matrix[16];
-float  r_base_world_matrix[16];
+//float        r_world_matrix[16];
+//float        r_base_world_matrix[16];
 
 //
 // screen size info
@@ -58,8 +58,6 @@ mleaf_t               *r_viewleaf, *r_oldviewleaf;
 
 unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
 
-void R_MarkLeaves (void);
-
 //cvar_t       r_norefresh = {0, "r_norefresh","0"};
 cvar_t r_drawentities = {0, "r_drawentities","1"};
 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
@@ -86,24 +84,23 @@ cvar_t      gl_fogend = {0, "gl_fogend","0"};
 cvar_t glfog = {0, "glfog", "0"};
 
 cvar_t r_ser = {CVAR_SAVE, "r_ser", "1"};
+cvar_t gl_viewmodeldepthhack = {0, "gl_viewmodeldepthhack", "1"};
 
-/*
 int R_VisibleCullBox (vec3_t mins, vec3_t maxs)
 {
        int sides;
        mnode_t *nodestack[8192], *node;
        int stack = 0;
 
+       if (R_CullBox(mins, maxs))
+               return true;
+
        node = cl.worldmodel->nodes;
 loc0:
        if (node->contents < 0)
        {
                if (((mleaf_t *)node)->visframe == r_framecount)
-               {
-                       if (R_CullBox(mins, maxs))
-                               return true;
                        return false;
-               }
                if (!stack)
                        return true;
                node = nodestack[--stack];
@@ -132,7 +129,6 @@ loc0:
        node = node->children[1];
        goto loc0;
 }
-*/
 
 qboolean lighthalf;
 
@@ -143,10 +139,8 @@ qboolean fogenabled;
 qboolean oldgl_fogenable;
 void FOG_framebegin(void)
 {
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
-//             if (!Nehahrademcompatibility)
-//                     gl_fogenable.value = 0;
                if (gl_fogenable.value)
                {
                        oldgl_fogenable = true;
@@ -182,7 +176,7 @@ void FOG_framebegin(void)
                        return;
                if(fog_density)
                {
-                       // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler...
+                       // LordHavoc: Borland C++ 5.0 was choking on this line...
                        //GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1};
                        GLfloat colors[4];
                        colors[0] = fog_red;
@@ -197,7 +191,7 @@ void FOG_framebegin(void)
                        }
 
                        glFogi (GL_FOG_MODE, GL_EXP2);
-                       glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); 
+                       glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100);
                        glFogfv (GL_FOG_COLOR, colors);
                        glEnable (GL_FOG);
                }
@@ -225,7 +219,7 @@ void FOG_frameend(void)
 
 void FOG_clear(void)
 {
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                Cvar_Set("gl_fogenable", "0");
                Cvar_Set("gl_fogdensity", "0.2");
@@ -239,7 +233,7 @@ void FOG_clear(void)
 void FOG_registercvars(void)
 {
        Cvar_RegisterVariable (&glfog);
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                Cvar_RegisterVariable (&gl_fogenable);
                Cvar_RegisterVariable (&gl_fogdensity);
@@ -278,12 +272,11 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable (&r_dynamic);
        Cvar_RegisterVariable (&r_waterripple);
        Cvar_RegisterVariable (&r_farclip);
-       if (nehahra)
-               Cvar_SetValue("r_fullbrights", 0);
-//     if (gl_vendor && strstr(gl_vendor, "3Dfx"))
-//             gl_lightmode.value = 0;
        Cvar_RegisterVariable (&r_fullbright);
        Cvar_RegisterVariable (&r_ser);
+       Cvar_RegisterVariable (&gl_viewmodeldepthhack);
+       if (gamemode == GAME_NEHAHRA)
+               Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
 }
 
@@ -360,151 +353,66 @@ void GL_Init (void)
 }
 
 
-/*
-void R_RotateForEntity (entity_t *e)
-{
-       glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
-
-       glRotatef (e->angles[1],  0, 0, 1);
-       glRotatef (-e->angles[0],  0, 1, 0);
-       glRotatef (e->angles[2],  1, 0, 0);
-
-       glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale
-}
-*/
-
-// LordHavoc: shading stuff
-vec3_t shadevector;
-vec3_t shadecolor;
-
-float  modelalpha;
-
 //==================================================================================
 
-void R_LerpUpdate(entity_t *ent)
+void R_Entity_Callback(void *data, void *junk)
 {
-       int frame;
-       frame = ent->render.frame;
-       if (ent->render.model && ent->render.frame >= ent->render.model->numframes)
-       {
-               Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->render.frame, ent->render.model->name);
-               frame = 0;
-       }
-
-       if (ent->render.lerp_model != ent->render.model)
-       {
-               // reset all interpolation information
-               ent->render.lerp_model = ent->render.model;
-               ent->render.frame1 = ent->render.frame2 = frame;
-               ent->render.frame1start = ent->render.frame2start = cl.time;
-               ent->render.framelerp = 1;
-               ent->render.lerp_starttime = 0;
-       }
-       else if (ent->render.frame2 != frame)
-       {
-               // transition to new frame
-               ent->render.frame1 = ent->render.frame2;
-               ent->render.frame1start = ent->render.frame2start;
-               ent->render.frame2 = frame;
-               ent->render.frame2start = cl.time;
-               ent->render.framelerp = 0;
-               ent->render.lerp_starttime = cl.time;
-       }
-       else
-       {
-               // lerp_starttime < 0 is used to prevent changing of framelerp
-               if (ent->render.lerp_starttime >= 0)
-               {
-                       // update transition
-                       ent->render.framelerp = (cl.time - ent->render.lerp_starttime) * 10;
-                       ent->render.framelerp = bound(0, ent->render.framelerp, 1);
-               }
-       }
+       ((entity_render_t *)data)->visframe = r_framecount;
 }
 
-
-void R_PrepareEntities (void)
+static void R_AddModelEntities (void)
 {
-       int i;
-       entity_t *ent;
-       vec3_t v;
-       // this updates entities that are supposed to be view relative
+       int             i;
+       vec3_t  v;
+
+       if (!r_drawentities.value)
+               return;
+
        for (i = 0;i < cl_numvisedicts;i++)
        {
-               ent = cl_visedicts[i];
+               currentrenderentity = &cl_visedicts[i]->render;
 
-               if (ent->render.flags & RENDER_VIEWMODEL)
+               // move view-relative models to where they should be
+               if (currentrenderentity->flags & RENDER_VIEWMODEL)
                {
                        // remove flag so it will not be repeated incase RelinkEntities is not called again for a while
-                       ent->render.flags -= RENDER_VIEWMODEL;
+                       currentrenderentity->flags -= RENDER_VIEWMODEL;
                        // transform origin
-                       VectorCopy(ent->render.origin, v);
-                       ent->render.origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
-                       ent->render.origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
-                       ent->render.origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
+                       VectorCopy(currentrenderentity->origin, v);
+                       currentrenderentity->origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
+                       currentrenderentity->origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
+                       currentrenderentity->origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
                        // adjust angles
-                       VectorAdd(ent->render.angles, r_refdef.viewangles, ent->render.angles);
+                       VectorAdd(currentrenderentity->angles, r_refdef.viewangles, currentrenderentity->angles);
                }
-       }
-}
-
-void R_Entity_Callback(void *data, void *junk)
-{
-       ((entity_t *)data)->render.visframe = r_framecount;
-}
-
-void R_AddModelEntities (void)
-{
-       int             i;
-       vec3_t  mins, maxs;
-       frameblend_t blend[4];
-
-       if (!r_drawentities.value)
-               return;
 
-       for (i = 0;i < cl_numvisedicts;i++)
-       {
-               currententity = cl_visedicts[i];
-               if (currententity->render.model->type == mod_brush)
+               if (currentrenderentity->angles[0] || currentrenderentity->angles[2])
                {
-                       modelalpha = currententity->render.alpha;
-                       R_DrawBrushModel (currententity);
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmins, currentrenderentity->mins);
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmaxs, currentrenderentity->maxs);
                }
-               else if (currententity->render.model->type == mod_alias)
+               else if (currentrenderentity->angles[1])
                {
-                       VectorAdd(currententity->render.origin, currententity->render.model->mins, mins);
-                       VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs);
-                       if (r_ser.value)
-                               R_Clip_AddBox(mins, maxs, R_Entity_Callback, currententity, NULL);
-                       else if (R_NotCulledBox(mins, maxs))
-                               currententity->render.visframe = r_framecount;
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmins, currentrenderentity->mins);
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmaxs, currentrenderentity->maxs);
                }
-               else if (currententity->render.model->type == mod_sprite)
+               else
                {
-                       R_LerpUpdate(currententity);
-                       if (r_ser.value)
-                       {
-                               R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
-                               R_ClipSprite(currententity, blend);
-                       }
-                       else
-                       {
-                               VectorAdd(currententity->render.origin, currententity->render.model->mins, mins);
-                               VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs);
-                               if (R_NotCulledBox(mins, maxs))
-                                       currententity->render.visframe = r_framecount;
-                       }
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmins, currentrenderentity->mins);
+                       VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmaxs, currentrenderentity->maxs);
                }
+               if (R_VisibleCullBox(currentrenderentity->mins, currentrenderentity->maxs))
+                       continue;
+
+               R_LerpAnimation(currentrenderentity);
+               if (r_ser.value)
+                       currentrenderentity->model->SERAddEntity();
+               else
+                       currentrenderentity->visframe = r_framecount;
        }
 }
 
-/*
-=============
-R_DrawEntitiesOnList
-=============
-*/
-/*
-void R_DrawEntitiesOnList1 (void)
+void R_DrawModels1 (void)
 {
        int             i;
 
@@ -513,65 +421,24 @@ void R_DrawEntitiesOnList1 (void)
 
        for (i = 0;i < cl_numvisedicts;i++)
        {
-               if (cl_visedicts[i]->render.visframe != r_framecount)
-                       continue;
-               if (cl_visedicts[i]->render.model->type != mod_brush)
-                       continue;
-               currententity = cl_visedicts[i];
-               modelalpha = currententity->render.alpha;
-
-               R_DrawBrushModel (currententity);
+               currentrenderentity = &cl_visedicts[i]->render;
+               if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawEarly)
+                       currentrenderentity->model->DrawEarly();
        }
 }
-*/
 
-void R_DrawModels (void)
+void R_DrawModels2 (void)
 {
        int             i;
-       frameblend_t blend[4];
-//     vec3_t  mins, maxs;
 
        if (!r_drawentities.value)
                return;
 
        for (i = 0;i < cl_numvisedicts;i++)
        {
-               if (cl_visedicts[i]->render.visframe != r_framecount)
-                       continue;
-               currententity = cl_visedicts[i];
-               if (currententity->render.model->type != mod_alias && currententity->render.model->type != mod_sprite)
-                       continue;
-
-               modelalpha = currententity->render.alpha;
-
-               if (currententity->render.model->type == mod_alias)
-               {
-                       // only lerp models here because sprites were already lerped for their clip polygon
-                       R_LerpUpdate(currententity);
-                       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
-                       R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
-               }
-               else //if (currententity->render.model->type == mod_sprite)
-               {
-                       // build blend array
-                       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
-                       R_DrawSpriteModel (currententity, blend);
-               }
-
-               /*
-               VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->mins, mins);
-               VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->maxs, maxs);
-
-               switch (cl_visedicts[i]->render.model->type)
-               {
-               case mod_alias:
-                       R_Clip_AddBox(mins, maxs, R_DrawModelCallback, cl_visedicts[i], NULL);
-                       break;
-               case mod_sprite:
-                       R_Clip_AddBox(mins, maxs, R_DrawSpriteCallback, cl_visedicts[i], NULL);
-                       break;
-               }
-               */
+               currentrenderentity = &cl_visedicts[i]->render;
+               if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawLate)
+                       currentrenderentity->model->DrawLate();
        }
 }
 
@@ -582,31 +449,22 @@ R_DrawViewModel
 */
 void R_DrawViewModel (void)
 {
-       frameblend_t blend[4];
-
        if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
                return;
 
-       currententity = &cl.viewent;
-       currententity->render.alpha = modelalpha = cl_entities[cl.viewentity].render.alpha; // LordHavoc: if the player is transparent, so is the gun
-       currententity->render.effects = cl_entities[cl.viewentity].render.effects;
-       currententity->render.scale = 1;
-       VectorCopy(cl_entities[cl.viewentity].render.colormod, currententity->render.colormod);
+       currentrenderentity = &cl.viewent.render;
 
-       R_LerpUpdate(currententity);
-       R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
+       R_LerpAnimation(currentrenderentity);
 
        // hack the depth range to prevent view model from poking into walls
-       glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
-       R_DrawAliasModel (currententity, false, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
-       glDepthRange (gldepthmin, gldepthmax);
+       if (gl_viewmodeldepthhack.value)
+               glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
+       currentrenderentity->model->DrawLate();
+       if (gl_viewmodeldepthhack.value)
+               glDepthRange (gldepthmin, gldepthmax);
 }
 
-void R_DrawBrushModel (entity_t *e);
-
-void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
-
-void R_SetFrustum (void)
+static void R_SetFrustum (void)
 {
        int             i;
 
@@ -646,21 +504,20 @@ void R_SetFrustum (void)
        }
 }
 
-void R_AnimateLight (void);
-void V_CalcBlend (void);
-
 /*
 ===============
 R_SetupFrame
 ===============
 */
-void R_SetupFrame (void)
+static void R_SetupFrame (void)
 {
 // don't allow cheats in multiplayer
        if (cl.maxclients > 1)
        {
-               Cvar_Set ("r_fullbright", "0");
-               Cvar_Set ("r_ambient", "0");
+               if (r_fullbright.value != 0)
+                       Cvar_Set ("r_fullbright", "0");
+               if (r_ambient.value != 0)
+                       Cvar_Set ("r_ambient", "0");
        }
 
        r_framecount++;
@@ -677,7 +534,7 @@ void R_SetupFrame (void)
        V_SetContentsColor (r_viewleaf->contents);
        V_CalcBlend ();
 
-       r_cache_thrash = false;
+//     r_cache_thrash = false;
 
        c_brush_polys = 0;
        c_alias_polys = 0;
@@ -695,17 +552,20 @@ void R_SetupFrame (void)
 }
 
 
-void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
+static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
 {
-   GLdouble xmin, xmax, ymin, ymax;
+       GLdouble xmax, ymax;
 
-   ymax = zNear * tan( fovy * M_PI / 360.0 );
-   ymin = -ymax;
+       xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
+       ymax = zNear * tan( fovy * M_PI / 360.0 );
 
-   xmin = ymin * aspect;
-   xmax = ymax * aspect;
+       if (r_viewleaf->contents != CONTENTS_EMPTY && r_viewleaf->contents != CONTENTS_SOLID)
+       {
+               xmax *= (sin(cl.time * 4.7) * 0.03 + 0.97);
+               ymax *= (sin(cl.time * 3) * 0.03 + 0.97);
+       }
 
-   glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+       glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
 }
 
 
@@ -714,60 +574,33 @@ void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble
 R_SetupGL
 =============
 */
-void R_SetupGL (void)
+static void R_SetupGL (void)
 {
-       float   screenaspect;
-       int             x, x2, y2, y, w, h;
-
        if (!r_render.value)
                return;
-       //
+
        // set up viewpoint
-       //
        glMatrixMode(GL_PROJECTION);
-    glLoadIdentity ();
-       x = r_refdef.vrect.x * glwidth/vid.width;
-       x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
-       y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
-       y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
-
-       // fudge around because of frac screen scale
-       if (x > 0)
-               x--;
-       if (x2 < glwidth)
-               x2++;
-       if (y2 < 0)
-               y2--;
-       if (y < glheight)
-               y++;
-
-       w = x2 - x;
-       h = y - y2;
-
-       if (envmap)
-       {
-               x = y2 = 0;
-               w = h = 256;
-       }
+       glLoadIdentity ();
 
-       glViewport (glx + x, gly + y2, w, h);
-    screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
-//     yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
-       MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  r_farclip.value);
+       // y is weird beause OpenGL is bottom to top, we use top to bottom
+       glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
+//     yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
+       MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip.value);
 
        glCullFace(GL_FRONT);
 
        glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity ();
+       glLoadIdentity ();
 
-    glRotatef (-90,  1, 0, 0);     // put Z going up
-    glRotatef (90,  0, 0, 1);      // put Z going up
-    glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
-    glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
-    glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
-    glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
+       glRotatef (-90,  1, 0, 0);          // put Z going up
+       glRotatef (90,  0, 0, 1);           // put Z going up
+       glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
+       glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
+       glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
+       glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
 
-       glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
+//     glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
 
        //
        // set drawing parms
@@ -790,7 +623,7 @@ void R_SetupGL (void)
 R_Clear
 =============
 */
-void R_Clear (void)
+static void R_Clear (void)
 {
        if (!r_render.value)
                return;
@@ -802,35 +635,7 @@ void R_Clear (void)
        glDepthRange (gldepthmin, gldepthmax);
 }
 
-// LordHavoc: my trick to *FIX* GLQuake lighting once and for all :)
-void GL_Brighten(void)
-{
-       if (!r_render.value)
-               return;
-       glMatrixMode(GL_PROJECTION);
-    glLoadIdentity ();
-       glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
-       glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity ();
-       glDisable (GL_DEPTH_TEST);
-       glDisable (GL_CULL_FACE);
-       glDisable(GL_TEXTURE_2D);
-       glEnable(GL_BLEND);
-       glBlendFunc (GL_DST_COLOR, GL_ONE);
-       glBegin (GL_TRIANGLES);
-       glColor3f (1, 1, 1);
-       glVertex2f (-5000, -5000);
-       glVertex2f (10000, -5000);
-       glVertex2f (-5000, 10000);
-       glEnd ();
-       glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glDisable(GL_BLEND);
-       glEnable(GL_TEXTURE_2D);
-       glEnable (GL_DEPTH_TEST);
-       glEnable (GL_CULL_FACE);
-}
-
-void GL_BlendView(void)
+static void GL_BlendView(void)
 {
        if (!r_render.value)
                return;
@@ -840,7 +645,7 @@ void GL_BlendView(void)
 
        glMatrixMode(GL_PROJECTION);
     glLoadIdentity ();
-       glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
+       glOrtho  (0, 256, 256, 0, -99999, 99999);
        glMatrixMode(GL_MODELVIEW);
     glLoadIdentity ();
        glDisable (GL_DEPTH_TEST);
@@ -871,7 +676,6 @@ R_RenderView
 r_refdef must be set before the first call
 ================
 */
-extern void R_Sky(void);
 extern void UploadLightmaps(void);
 extern void R_DrawSurfaces(void);
 extern void R_DrawPortals(void);
@@ -919,28 +723,28 @@ void timestring(int t, char *desc)
 void R_RenderView (void)
 {
        double starttime, currtime, temptime;
-//     if (r_norefresh.value)
-//             return;
 
        if (!cl.worldmodel)
                Host_Error ("R_RenderView: NULL worldmodel");
 
        if (r_speeds2.value)
        {
-               starttime = currtime = Sys_DoubleTime();
-
                speedstringcount = 0;
                sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i transpoly\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
                        r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
                        c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly,
                        c_faces, c_nodes, c_leafs,
                        c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+
+               starttime = currtime = Sys_DoubleTime();
        }
        else
                starttime = currtime = 0;
 
        R_MoveParticles ();
+       TIMEREPORT("mparticles")
        R_MoveExplosions();
+       TIMEREPORT("mexplosion")
 
        FOG_framebegin();
 
@@ -954,8 +758,6 @@ void R_RenderView (void)
        R_SetupGL ();
        R_Clip_StartFrame();
 
-       R_PrepareEntities();
-
        skypolyclear();
        wallpolyclear();
        transpolyclear();
@@ -963,17 +765,21 @@ void R_RenderView (void)
        TIMEREPORT("setup     ")
 
        R_DrawWorld ();
-       TIMEREPORT("world     ")
+       TIMEREPORT("addworld  ")
 
        R_AddModelEntities();
-       TIMEREPORT("addmodels")
+       TIMEREPORT("addmodels ")
 
        R_Clip_EndFrame();
        TIMEREPORT("scanedge  ")
 
        // now mark the lit surfaces
        R_PushDlights ();
-       // yes this does add the world surfaces after the brush models
+       TIMEREPORT("marklights")
+
+       R_DrawModels1 ();
+
+       // yes this does add the world after the brush models when using the SER
        R_DrawSurfaces ();
        R_DrawPortals ();
        TIMEREPORT("surfaces  ");
@@ -981,30 +787,29 @@ void R_RenderView (void)
        UploadLightmaps();
        TIMEREPORT("uploadlmap")
 
-       // fogged sky polys, affects depth
        skypolyrender();
-
-       // does not affect depth, draws over the sky polys
-       if (currentskypoly)
-               R_Sky();
        TIMEREPORT("skypoly   ")
 
-       wallpolyrender();
-       TIMEREPORT("wallpoly  ")
+       wallpolyrender1();
+       TIMEREPORT("wallpoly1 ")
 
        GL_DrawDecals();
        TIMEREPORT("ddecal    ")
 
+       wallpolyrender2();
+       TIMEREPORT("wallpoly2 ")
+
        // don't let sound skip if going slow
        if (!intimerefresh && !r_speeds2.value)
                S_ExtraUpdate ();
 
        R_DrawViewModel ();
-       R_DrawModels ();
+       R_DrawModels2 ();
        TIMEREPORT("models    ")
 
        R_DrawParticles ();
        TIMEREPORT("dparticles")
+
        R_DrawExplosions();
        TIMEREPORT("dexplosion")
 
index 5a8a874b27b5c48115f32f2cae6f635d5b2b7750..5cf56120ec71628880160189ebd16a1dd6e7e266 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -29,74 +29,104 @@ R_Envmap_f
 Grab six views for environment mapping tests
 ===============
 */
+float CalcFov (float fov_x, float width, float height);
+struct
+{
+       float angles[3];
+       char *name;
+}
+envmapinfo[6] =
+{
+       {{  0,   0, 0}, "ft"},
+       {{  0,  90, 0}, "rt"},
+       {{  0, 180, 0}, "bk"},
+       {{  0, 270, 0}, "lf"},
+       {{-90,  90, 0}, "up"},
+       {{ 90,  90, 0}, "dn"}
+};
 void R_Envmap_f (void)
 {
-       byte    buffer[256*256*4];
+       int             i, size;
+       char    filename[256];
+       char    basename[256];
+       byte    *buffer, gamma[256];
+
+       if (Cmd_Argc() != 3)
+       {
+               Con_Printf ("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
+               return;
+       }
 
        if (!r_render.value)
                return;
 
-       glDrawBuffer  (GL_FRONT);
-       glReadBuffer  (GL_FRONT);
+       strcpy(basename, Cmd_Argv(1));
+       size = atoi(Cmd_Argv(2));
+       if (size != 128 && size != 256 && size != 512 && size != 1024)
+       {
+               Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
+               return;
+       }
+       if (size > vid.realwidth || size > vid.realheight)
+       {
+               Con_Printf("envmap: your resolution is not big enough to render that size\n");
+               return;
+       }
+
+       buffer = malloc(size*size*3);
+       if (buffer == NULL)
+       {
+               Con_Printf("envmap: unable to allocate memory for image\n");
+               return;
+       }
+
+       BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+
+//     glDrawBuffer  (GL_FRONT);
+//     glReadBuffer  (GL_FRONT);
+       glDrawBuffer  (GL_BACK);
+       glReadBuffer  (GL_BACK);
        envmap = true;
 
-       r_refdef.vrect.x = 0;
-       r_refdef.vrect.y = 0;
-       r_refdef.vrect.width = 256;
-       r_refdef.vrect.height = 256;
-
-       r_refdef.viewangles[0] = 0;
-       r_refdef.viewangles[1] = 0;
-       r_refdef.viewangles[2] = 0;
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));             
-
-       r_refdef.viewangles[1] = 90;
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));             
-
-       r_refdef.viewangles[1] = 180;
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));             
-
-       r_refdef.viewangles[1] = 270;
-       GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));             
-
-       r_refdef.viewangles[0] = -90;
-       r_refdef.viewangles[1] = 0;
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));             
-
-       r_refdef.viewangles[0] = 90;
-       r_refdef.viewangles[1] = 0;
-       R_RenderView ();
-       glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-       COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));             
+       r_refdef.x = 0;
+       r_refdef.y = 0;
+       r_refdef.width = size;
+       r_refdef.height = size;
+
+       r_refdef.fov_x = 90;
+       r_refdef.fov_y = 90;
+
+       for (i = 0;i < 6;i++)
+       {
+               VectorCopy(envmapinfo[i].angles, r_refdef.viewangles);
+               glClearColor(0,0,0,0);
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+               R_RenderView ();
+               glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+               sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name);
+               Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma);
+               Image_WriteTGARGB_preflipped(filename, size, size, buffer);
+       }
 
        envmap = false;
        glDrawBuffer  (GL_BACK);
        glReadBuffer  (GL_BACK);
-       GL_EndRendering ();
-}
 
-void R_InitParticles (void);
+       free(buffer);
+
+       // cause refdef to be fixed
+//     vid.recalc_refdef = 1;
+}
 
-void gl_misc_start(void)
+static void gl_misc_start(void)
 {
 }
 
-void gl_misc_shutdown(void)
+static void gl_misc_shutdown(void)
 {
 }
 
-void gl_misc_newmap(void)
+static void gl_misc_newmap(void)
 {
 }
 
@@ -105,15 +135,15 @@ void gl_misc_newmap(void)
 R_Init
 ===============
 */
+static void R_TimeRefresh_f (void);
 void GL_Misc_Init (void)
-{      
-       Cmd_AddCommand ("envmap", R_Envmap_f);  
-       Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);        
+{
+       Cmd_AddCommand ("envmap", R_Envmap_f);
+       Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
 
        R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown, gl_misc_newmap);
 }
 
-extern void R_ClearParticles (void);
 extern void GL_BuildLightmaps (void);
 
 /*
@@ -124,7 +154,7 @@ R_NewMap
 void R_NewMap (void)
 {
        int             i;
-       
+
        for (i=0 ; i<256 ; i++)
                d_lightstylevalue[i] = 264;             // normal light value
 
@@ -145,20 +175,22 @@ For program optimization
 ====================
 */
 qboolean intimerefresh = 0;
-void R_TimeRefresh_f (void)
+static void R_TimeRefresh_f (void)
 {
        int                     i;
        float           start, stop, time;
 
        intimerefresh = 1;
        start = Sys_DoubleTime ();
+       glDrawBuffer (GL_FRONT);
        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();
+               R_RenderView();
        }
+       glDrawBuffer  (GL_BACK);
 
        stop = Sys_DoubleTime ();
        intimerefresh = 0;
index 30851689c9919a32077f96492dea74f818c2a187..0b9f07f2b1bbac66711a141160ab96adb1b43e22 100644 (file)
@@ -38,8 +38,10 @@ short lightmapupdate[MAX_LIGHTMAPS][2];
 
 signed int blocklights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; // LordHavoc: *3 for colored lighting
 
-int lightmapalign, lightmapalignmask; // LordHavoc: NVIDIA's broken subimage fix, see BuildLightmaps for notes
-cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"};
+byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4];
+
+int lightmapalign, lightmapalignmask; // LordHavoc: align texsubimage updates on 4 byte boundaries
+cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"}; // align texsubimage updates on 4 byte boundaries
 cvar_t gl_lightmaprgba = {0, "gl_lightmaprgba", "1"};
 cvar_t gl_nosubimagefragments = {0, "gl_nosubimagefragments", "0"};
 cvar_t gl_nosubimage = {0, "gl_nosubimage", "0"};
@@ -48,8 +50,6 @@ cvar_t gl_vertex = {0, "gl_vertex", "0"};
 cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"};
 cvar_t r_drawportals = {0, "r_drawportals", "0"};
 cvar_t r_testvis = {0, "r_testvis", "0"};
-cvar_t r_solidworldnode = {0, "r_solidworldnode", "3"};
-cvar_t r_pvsworldnode = {0, "r_pvsworldnode", "1"};
 
 qboolean lightmaprgba, nosubimagefragments, nosubimage;
 int lightmapbytes;
@@ -82,8 +82,6 @@ void GL_Surf_Init(void)
        Cvar_RegisterVariable(&r_dlightmap);
        Cvar_RegisterVariable(&r_drawportals);
        Cvar_RegisterVariable(&r_testvis);
-       Cvar_RegisterVariable(&r_solidworldnode);
-       Cvar_RegisterVariable(&r_pvsworldnode);
 
        R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
 }
@@ -124,7 +122,7 @@ int R_AddDynamicLights (msurface_t *surf)
                if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
                        continue;                                       // not lit by this light
 
-               VectorSubtract (cl_dlights[lnum].origin, currententity->render.origin, local);
+               VectorSubtract (cl_dlights[lnum].origin, currentrenderentity->origin, local);
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
@@ -232,7 +230,7 @@ R_BuildLightMap
 Combine and scale multiple lightmaps into the 8.8 format in blocklights
 ===============
 */
-void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
+void R_BuildLightMap (msurface_t *surf, byte *dest, int stride, int dlightchanged)
 {
        int             smax, tmax;
        int             i, j, size, size3;
@@ -241,9 +239,14 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
        int             maps;
        int             *bl;
 
+       // update cached lighting info
        surf->cached_dlight = 0;
        surf->cached_lightscalebit = lightscalebit;
        surf->cached_ambient = r_ambient.value;
+       surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
+       surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
+       surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
+       surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
 
        smax = (surf->extents[0]>>4)+1;
        tmax = (surf->extents[1]>>4)+1;
@@ -252,10 +255,10 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
        lightmap = surf->samples;
 
 // set to full bright if no light data
-       if ((currententity && (currententity->render.effects & EF_FULLBRIGHT)) || !cl.worldmodel->lightdata)
+       if ((currentrenderentity->effects & EF_FULLBRIGHT) || !cl.worldmodel->lightdata)
        {
                bl = blocklights;
-               for (i=0 ; i<size ; i++)
+               for (i = 0;i < size;i++)
                {
                        *bl++ = 255*256;
                        *bl++ = 255*256;
@@ -275,28 +278,25 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
                else
                        memset(&blocklights[0], 0, size*3*sizeof(int));
 
+               if (r_dlightmap.value && surf->dlightframe == r_framecount)
+               {
+                       if ((surf->cached_dlight = R_AddDynamicLights(surf)))
+                               c_light_polys++;
+                       else if (dlightchanged)
+                               return; // don't upload if only updating dlights and none mattered
+               }
+
 // add all the lightmaps
                if (lightmap)
-               {
                        for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
-                       {
-                               scale = d_lightstylevalue[surf->styles[maps]];
-                               surf->cached_light[maps] = scale;       // 8.8 fraction
-                               bl = blocklights;
-                               for (i = 0;i < size3;i++)
+                               for (scale = d_lightstylevalue[surf->styles[maps]], bl = blocklights, i = 0;i < size3;i++)
                                        *bl++ += *lightmap++ * scale;
-                       }
-               }
-               if (r_dlightmap.value && surf->dlightframe == r_framecount)
-                       if ((surf->cached_dlight = R_AddDynamicLights(surf)))
-                               c_light_polys++;
        }
+
        R_ConvertLightmap(blocklights, dest, smax, tmax, stride);
 }
 
-byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4];
-
-void R_UpdateLightmap(msurface_t *s, int lnum)
+void R_UpdateLightmap(msurface_t *s, int lnum, int dlightschanged)
 {
        int smax, tmax;
        // upload the new lightmap texture fragment
@@ -309,9 +309,9 @@ void R_UpdateLightmap(msurface_t *s, int lnum)
                if (lightmapupdate[lnum][1] < (s->light_t + ((s->extents[1]>>4)+1)))
                        lightmapupdate[lnum][1] = (s->light_t + ((s->extents[1]>>4)+1));
                if (lightmaprgba)
-                       R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4);
+                       R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4, false);
                else
-                       R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3);
+                       R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3, false);
        }
        else
        {
@@ -319,13 +319,13 @@ void R_UpdateLightmap(msurface_t *s, int lnum)
                tmax = (s->extents[1]>>4)+1;
                if (lightmaprgba)
                {
-                       R_BuildLightMap (s, templight, smax * 4);
+                       R_BuildLightMap (s, templight, smax * 4, false);
                        if(r_upload.value)
                                glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
                }
                else
                {
-                       R_BuildLightMap (s, templight, smax * 3);
+                       R_BuildLightMap (s, templight, smax * 3, false);
                        if(r_upload.value)
                                glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
                }
@@ -342,44 +342,13 @@ Returns the proper texture for a given time and base texture
 */
 texture_t *R_TextureAnimation (texture_t *base)
 {
-//     texture_t *original;
-//     int             relative;
-//     int             count;
+       if (currentrenderentity->frame && base->alternate_anims != NULL)
+               base = base->alternate_anims;
 
-       if (currententity->render.frame)
-       {
-               if (base->alternate_anims)
-                       base = base->alternate_anims;
-       }
-       
-       if (!base->anim_total)
+       if (base->anim_total < 2)
                return base;
 
-       return base->anim_frames[(int)(cl.time*5) % base->anim_total];
-
-       /*
-       original = base;
-
-       relative = (int)(cl.time*5) % base->anim_total;
-
-       count = 0;      
-       while (base->anim_min > relative || base->anim_max <= relative)
-       {
-               base = base->anim_next;
-               if (!base)
-               {
-                       Con_Printf("R_TextureAnimation: broken cycle");
-                       return original;
-               }
-               if (++count > 100)
-               {
-                       Con_Printf("R_TextureAnimation: infinite cycle");
-                       return original;
-               }
-       }
-
-       return base;
-       */
+       return base->anim_frames[(int)(cl.time * 5.0f) % base->anim_total];
 }
 
 
@@ -625,24 +594,26 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
        wallvertcolor_t *outcolor;
        // check for lightmap modification
        if (s->cached_dlight
-        || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount)
         || r_ambient.value != s->cached_ambient
         || lightscalebit != s->cached_lightscalebit
         || (r_dynamic.value
-        && ((s->styles[0] != 255 && d_lightstylevalue[s->styles[0]] != s->cached_light[0])
-        || (s->styles[1] != 255 && d_lightstylevalue[s->styles[1]] != s->cached_light[1])
-        || (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);
+        && (d_lightstylevalue[s->styles[0]] != s->cached_light[0]
+        ||  d_lightstylevalue[s->styles[1]] != s->cached_light[1]
+        ||  d_lightstylevalue[s->styles[2]] != s->cached_light[2]
+        ||  d_lightstylevalue[s->styles[3]] != s->cached_light[3])))
+               R_UpdateLightmap(s, s->lightmaptexturenum, false); // base lighting changed
+       else if (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount)
+               R_UpdateLightmap(s, s->lightmaptexturenum, true); // only dlights
+
        if (s->dlightframe != r_framecount || r_dlightmap.value)
        {
                // LordHavoc: fast path version for no vertex lighting cases
-               wp = &wallpoly[currentwallpoly];
                out = &wallvert[currentwallvert];
                for (p = s->polys;p;p = p->next)
                {
                        if ((currentwallpoly >= MAX_WALLPOLYS) || (currentwallvert+p->numverts > MAX_WALLVERTS))
                                return;
+                       wp = &wallpoly[currentwallpoly++];
                        wp->texnum = (unsigned short) R_GetTexture(t->texture);
                        wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum);
                        wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture);
@@ -650,7 +621,6 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
                        wp->numverts = p->numverts;
                        wp->lit = false;
                        wp++;
-                       currentwallpoly++;
                        currentwallvert += p->numverts;
                        v = p->verts[0];
                        if (transform)
@@ -757,7 +727,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
        float *v, *wv, scale;
        glpoly_t *p;
        byte *lm;
-       alpha = (int) (modelalpha * 255.0f);
+       alpha = (int) (currentrenderentity->alpha * 255.0f);
        size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3; // *3 for colored lighting
        wv = wvert;
        for (p = s->polys;p;p = p->next)
@@ -792,14 +762,14 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
        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))
+       if (alpha != 255 || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[1] != 1 || currentrenderentity->colormod[2] != 1)
        {
                for (p = s->polys;p;p = p->next)
                {
                        v = p->verts[0];
-                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
                        for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
-                               transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->render.colormod[0], wv[4] * currententity->render.colormod[1], wv[5] * currententity->render.colormod[2], alpha);
+                               transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currentrenderentity->colormod[0], wv[4] * currentrenderentity->colormod[1], wv[5] * currentrenderentity->colormod[2], alpha);
                        transpolyend();
                }
        }
@@ -808,7 +778,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
                for (p = s->polys;p;p = p->next)
                {
                        v = p->verts[0];
-                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
                        for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
                                transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha);
                        transpolyend();
@@ -822,6 +792,7 @@ float bmverts[256*3];
 
 int vertexworld;
 
+// LordHavoc: disabled clipping on bmodels because they tend to intersect things sometimes
 /*
 void RBrushModelSurf_DoVisible(msurface_t *surf)
 {
@@ -837,12 +808,14 @@ void RBrushModelSurf_DoVisible(msurface_t *surf)
 }
 */
 
+/*
 void RBrushModelSurf_Callback(void *data, void *data2)
 {
-       entity_t *ent = data2;
        msurface_t *surf = data;
        texture_t *t;
 
+       currentrenderentity = data2;
+*/
        /*
        // FIXME: implement better dupe prevention in AddPolygon callback code
        if (ent->render.model->firstmodelsurface != 0)
@@ -852,14 +825,12 @@ void RBrushModelSurf_Callback(void *data, void *data2)
                        return;
        }
        */
+/*
        surf->visframe = r_framecount;
 
        c_faces++;
 
-       currententity = ent;
-       modelalpha = ent->render.alpha;
-
-       softwaretransformforbrushentity (ent);
+       softwaretransformforbrushentity (currentrenderentity);
 
        if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
        {
@@ -872,69 +843,52 @@ void RBrushModelSurf_Callback(void *data, void *data2)
        else
        {
                t = R_TextureAnimation(surf->texinfo->texture);
-               if (surf->texinfo->texture->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1)
+               if (t->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1)
                        RSurf_DrawWallVertex(surf, t, true, true);
                else
                        RSurf_DrawWall(surf, t, true);
        }
 }
+*/
 
 /*
 =================
 R_DrawBrushModel
 =================
 */
-void R_DrawBrushModel (entity_t *e)
+void R_DrawBrushModel (void)
 {
-       int                     i, j, vertexlit;
-       vec3_t          mins, maxs;
+       int                     i/*, j*/, vertexlit, rotated, transform;
        msurface_t      *s;
-       model_t         *clmodel;
-       int                     rotated;
-       vec3_t          org;
-       glpoly_t        *p;
-
-       currententity = e;
-
-       clmodel = e->render.model;
-
-       if (e->render.angles[0] || e->render.angles[1] || e->render.angles[2])
-       {
-               rotated = true;
-               for (i=0 ; i<3 ; i++)
-               {
-                       mins[i] = e->render.origin[i] - clmodel->radius;
-                       maxs[i] = e->render.origin[i] + clmodel->radius;
-               }
-       }
-       else
-       {
-               rotated = false;
-               VectorAdd (e->render.origin, clmodel->mins, mins);
-               VectorAdd (e->render.origin, clmodel->maxs, maxs);
-       }
+       model_t         *model;
+       vec3_t          org, temp, forward, right, up;
+//     glpoly_t        *p;
+       texture_t       *t;
 
-       if (R_CullBox (mins, maxs))
-               return;
+       model = currentrenderentity->model;
 
        c_bmodels++;
 
-       VectorSubtract (r_origin, e->render.origin, modelorg);
-       if (rotated)
+       VectorSubtract (r_origin, currentrenderentity->origin, modelorg);
+       rotated = false;
+       transform = false;
+       if (currentrenderentity->angles[0] || currentrenderentity->angles[1] || currentrenderentity->angles[2])
        {
-               vec3_t  temp;
-               vec3_t  forward, right, up;
-
+               transform = true;
+               rotated = true;
                VectorCopy (modelorg, temp);
-               AngleVectors (e->render.angles, forward, right, up);
+               AngleVectors (currentrenderentity->angles, forward, right, up);
                modelorg[0] = DotProduct (temp, forward);
                modelorg[1] = -DotProduct (temp, right);
                modelorg[2] = DotProduct (temp, up);
        }
+       else if (currentrenderentity->origin[0] || currentrenderentity->origin[1] || currentrenderentity->origin[2] || currentrenderentity->scale)
+               transform = true;
 
-       softwaretransformforbrushentity (e);
+       if (transform)
+               softwaretransformforbrushentity (currentrenderentity);
 
-       for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
+       for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++)
        {
                s->visframe = -1;
                if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0))
@@ -947,45 +901,56 @@ void R_DrawBrushModel (entity_t *e)
                if (!cl_dlights[i].radius)
                        continue;
 
-               VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org);
-               R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel);
+               if (rotated)
+               {
+                       VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, temp);
+                       org[0] = DotProduct (temp, forward);
+                       org[1] = -DotProduct (temp, right);
+                       org[2] = DotProduct (temp, up);
+               }
+               else
+                       VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, org);
+               R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, model);
        }
-       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;
+       vertexlit = vertexworld || currentrenderentity->alpha != 1 || model->firstmodelsurface == 0 || (currentrenderentity->effects & EF_FULLBRIGHT) || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[2] != 1 || currentrenderentity->colormod[2] != 1;
 
        // draw texture
-       for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
+       for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++)
        {
                if (s->visframe == r_framecount)
                {
 //                     R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent);
+                       /*
                        if (r_ser.value)
                        {
                                for (p = s->polys;p;p = p->next)
                                {
                                        for (j = 0;j < p->numverts;j++)
                                                softwaretransform(&p->verts[j][0], bmverts + j * 3);
-                                       R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && modelalpha == 1, RBrushModelSurf_Callback, s, e, NULL);
+                                       R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && currentrenderentity->alpha == 1, RBrushModelSurf_Callback, s, e, NULL);
                                }
                        }
                        else
                        {
+                       */
+                               c_faces++;
+                               t = R_TextureAnimation(s->texinfo->texture);
                                if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
                                {
                                        // sky and liquid don't need sorting (skypoly/transpoly)
                                        if (s->flags & SURF_DRAWSKY)
-                                               RSurf_DrawSky(s, true);
+                                               RSurf_DrawSky(s, transform);
                                        else
-                                               RSurf_DrawWater(s, R_TextureAnimation(s->texinfo->texture), true, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+                                               RSurf_DrawWater(s, t, transform, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
                                }
                                else
                                {
-                                       texture_t *t = R_TextureAnimation(s->texinfo->texture);
-                                       if (vertexlit || s->texinfo->texture->transparent)
-                                               RSurf_DrawWallVertex(s, t, true, true);
+                                       if (t->transparent || vertexlit)
+                                               RSurf_DrawWallVertex(s, t, transform, true);
                                        else
-                                               RSurf_DrawWall(s, t, true);
+                                               RSurf_DrawWall(s, t, transform);
                                }
-                       }
+                       //}
                }
        }
        UploadLightmaps();
@@ -1138,7 +1103,7 @@ void R_MarkLeaves (void)
 
 void R_SolidWorldNode (void)
 {
-       if ((int) r_solidworldnode.value == 3)
+       if (r_viewleaf->contents != CONTENTS_SOLID)
        {
                int portalstack;
                mportal_t *p, *pstack[8192];
@@ -1146,6 +1111,10 @@ void R_SolidWorldNode (void)
                mleaf_t *leaf;
                glpoly_t *poly;
                tinyplane_t plane;
+               // LordHavoc: portal-passage worldnode; follows portals leading
+               // outward from viewleaf, if a portal leads offscreen it is not
+               // followed, in indoor maps this can often cull a great deal of
+               // geometry away when pvs data is not present (useful with pvs as well)
 
                leaf = r_viewleaf;
                leaf->worldnodeframe = r_framecount;
@@ -1239,18 +1208,22 @@ void R_SolidWorldNode (void)
                if (portalstack)
                        goto loc1;
        }
-       else if ((int) r_solidworldnode.value == 2)
+       else
        {
                mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
                int nodestackpos = 0;
                glpoly_t *poly;
+               // LordHavoc: recursive descending worldnode; if portals are not
+               // available, this is a good last resort, can cull large amounts of
+               // geometry, but is more time consuming than portal-passage and renders
+               // things behind walls
 
 loc2:
                if (R_NotCulledBox(node->mins, node->maxs))
                {
-                       if (r_ser.value)
+                       if (node->numsurfaces)
                        {
-                               if (node->numsurfaces)
+                               if (r_ser.value)
                                {
                                        msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
                                        tinyplane_t plane;
@@ -1277,10 +1250,7 @@ loc2:
                                                }
                                        }
                                }
-                       }
-                       else
-                       {
-                               if (node->numsurfaces)
+                               else
                                {
                                        msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
                                        if (PlaneDiff (r_origin, node->plane) < 0)
@@ -1339,111 +1309,6 @@ loc2:
                        goto loc2;
                }
        }
-       else if ((int) r_solidworldnode.value == 1 && r_ser.value)
-       {
-               glpoly_t *poly;
-               msurface_t *surf, *endsurf;
-               tinyplane_t plane;
-
-               surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
-               endsurf = surf + cl.worldmodel->nummodelsurfaces;
-               for (;surf < endsurf;surf++)
-               {
-                       if (PlaneDiff(r_origin, surf->plane) < 0)
-                       {
-                               if (surf->flags & SURF_PLANEBACK)
-                               {
-                                       VectorNegate(surf->plane->normal, plane.normal);
-                                       plane.dist = -surf->plane->dist;
-                                       for (poly = surf->polys;poly;poly = poly->next)
-                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
-                               }
-                       }
-                       else
-                       {
-                               if (!(surf->flags & SURF_PLANEBACK))
-                                       for (poly = surf->polys;poly;poly = poly->next)
-                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)&surf->plane);
-                       }
-               }
-       }
-       else
-       {
-               int l;
-               mleaf_t *leaf;
-               msurface_t *surf, **mark, **endmark;
-               glpoly_t *poly;
-               tinyplane_t plane;
-
-               for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++)
-               {
-                       if (R_CullBox(leaf->mins, leaf->maxs))
-                               continue;
-                       leaf->visframe = r_framecount;
-                       c_leafs++;
-                       if (leaf->nummarksurfaces)
-                       {
-//                             if (R_CullBox(leaf->mins, leaf->maxs))
-//                                     continue;
-
-                               if (leaf->nummarksurfaces)
-                               {
-                                       mark = leaf->firstmarksurface;
-                                       endmark = mark + leaf->nummarksurfaces;
-                                       if (r_ser.value)
-                                       {
-                                               do
-                                               {
-                                                       surf = *mark++;
-                                                       // make sure surfaces are only processed once
-                                                       if (surf->worldnodeframe == r_framecount)
-                                                               continue;
-                                                       surf->worldnodeframe = r_framecount;
-                                                       if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
-                                                       {
-                                                               if (surf->flags & SURF_PLANEBACK)
-                                                               {
-                                                                       VectorNegate(surf->plane->normal, plane.normal);
-                                                                       plane.dist = -surf->plane->dist;
-                                                                       for (poly = surf->polys;poly;poly = poly->next)
-                                                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               if (!(surf->flags & SURF_PLANEBACK))
-                                                                       for (poly = surf->polys;poly;poly = poly->next)
-                                                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
-                                                       }
-                                               }
-                                               while (mark < endmark);
-                                       }
-                                       else
-                                       {
-                                               do
-                                               {
-                                                       surf = *mark++;
-                                                       // make sure surfaces are only processed once
-                                                       if (surf->worldnodeframe == r_framecount)
-                                                               continue;
-                                                       surf->worldnodeframe = r_framecount;
-                                                       if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
-                                                       {
-                                                               if (surf->flags & SURF_PLANEBACK)
-                                                                       surf->visframe = r_framecount;
-                                                       }
-                                                       else
-                                                       {
-                                                               if (!(surf->flags & SURF_PLANEBACK))
-                                                                       surf->visframe = r_framecount;
-                                                       }
-                                               }
-                                               while (mark < endmark);
-                                       }
-                               }
-                       }
-               }
-       }
 }
 
 /*
@@ -1629,220 +1494,111 @@ void R_Portal_Callback(void *data, void *data2)
 
 void R_PVSWorldNode()
 {
-       if (r_pvsworldnode.value == 1)
-       {
-               int portalstack, i;
-               mportal_t *p, *pstack[8192];
-               msurface_t *surf, **mark, **endmark;
-               mleaf_t *leaf;
-               tinyplane_t plane;
-               glpoly_t *poly;
-               byte *worldvis;
+       int portalstack, i;
+       mportal_t *p, *pstack[8192];
+       msurface_t *surf, **mark, **endmark;
+       mleaf_t *leaf;
+       tinyplane_t plane;
+       glpoly_t *poly;
+       byte *worldvis;
 
-               worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
+       worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
 
-               leaf = r_viewleaf;
-               leaf->worldnodeframe = r_framecount;
-               portalstack = 0;
-       loc0:
-               c_leafs++;
+       leaf = r_viewleaf;
+       leaf->worldnodeframe = r_framecount;
+       portalstack = 0;
+loc0:
+       c_leafs++;
 
-               leaf->visframe = r_framecount;
+       leaf->visframe = r_framecount;
 
-               if (leaf->nummarksurfaces)
+       if (leaf->nummarksurfaces)
+       {
+               mark = leaf->firstmarksurface;
+               endmark = mark + leaf->nummarksurfaces;
+               if (r_ser.value)
                {
-                       mark = leaf->firstmarksurface;
-                       endmark = mark + leaf->nummarksurfaces;
-                       if (r_ser.value)
+                       do
                        {
-                               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)
                                {
-                                       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)
-                                               {
-                                                       VectorNegate(surf->plane->normal, plane.normal);
-                                                       plane.dist = -surf->plane->dist;
-                                                       for (poly = surf->polys;poly;poly = poly->next)
-                                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
-                                               }
-                                       }
-                                       else
+                                       if (surf->flags & SURF_PLANEBACK)
                                        {
-                                               if (!(surf->flags & SURF_PLANEBACK))
-                                                       for (poly = surf->polys;poly;poly = poly->next)
-                                                               R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
+                                               VectorNegate(surf->plane->normal, plane.normal);
+                                               plane.dist = -surf->plane->dist;
+                                               for (poly = surf->polys;poly;poly = poly->next)
+                                                       R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
                                        }
                                }
-                               while (mark < endmark);
-                       }
-                       else
-                       {
-                               do
+                               else
                                {
-                                       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;
-                                       }
+                                       if (!(surf->flags & SURF_PLANEBACK))
+                                               for (poly = surf->polys;poly;poly = poly->next)
+                                                       R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
                                }
-                               while (mark < endmark);
                        }
+                       while (mark < endmark);
                }
-
-               // follow portals into other leafs
-               p = leaf->portals;
-               for (;p;p = p->next)
+               else
                {
-                       if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
+                       do
                        {
-                               leaf = p->past;
-                               if (leaf->worldnodeframe != r_framecount)
+                               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)
                                {
-                                       leaf->worldnodeframe = r_framecount;
-                                       if (leaf->contents != CONTENTS_SOLID)
-                                       {
-                                               i = (leaf - cl.worldmodel->leafs) - 1;
-                                               if (worldvis[i>>3] & (1<<(i&7)))
-                                               {
-                                                       if (R_NotCulledBox(leaf->mins, leaf->maxs))
-                                                       {
-                                                               pstack[portalstack++] = p;
-                                                               goto loc0;
-
-       loc1:
-                                                               p = pstack[--portalstack];
-                                                       }
-                                               }
-                                       }
+                                       if (surf->flags & SURF_PLANEBACK)
+                                               surf->visframe = r_framecount;
+                               }
+                               else
+                               {
+                                       if (!(surf->flags & SURF_PLANEBACK))
+                                               surf->visframe = r_framecount;
                                }
                        }
+                       while (mark < endmark);
                }
-
-               if (portalstack)
-                       goto loc1;
        }
-       else
-       {
-               int i/*, l*/, k, c, row, numbits, bit, leafnum, numleafs;
-               mleaf_t *leaf;
-               msurface_t *surf, **mark, **endmark;
-               model_t *model = cl.worldmodel;
-               byte *in;
-       //      mportal_t *portal;
-               glpoly_t *poly;
-               tinyplane_t plane;
-
-       //      c_leafs++;
-       //      r_viewleaf->visframe = r_framecount;
-               if (!r_testvis.value)
-                       r_portalframecount++;
 
-               numleafs = model->numleafs;
-               numbits = numleafs;
-               k = 0;
-               in = r_viewleaf->compressed_vis;
-               row = (numbits + 7) >> 3;
-               while (k < row)
+       // follow portals into other leafs
+       p = leaf->portals;
+       for (;p;p = p->next)
+       {
+               if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
                {
-                       c = *in++;
-                       if (c)
+                       leaf = p->past;
+                       if (leaf->worldnodeframe != r_framecount)
                        {
-                               for (i = 0, bit = 1;c;i++, bit <<= 1)
+                               leaf->worldnodeframe = r_framecount;
+                               if (leaf->contents != CONTENTS_SOLID)
                                {
-                                       if (c & bit)
+                                       i = (leaf - cl.worldmodel->leafs) - 1;
+                                       if (worldvis[i>>3] & (1<<(i&7)))
                                        {
-                                               leafnum = (k << 3)+i+1;
-                                               if (leafnum > numleafs)
-                                                       return;
-                                               c -= bit;
-                                               leaf = &model->leafs[leafnum];
                                                if (R_NotCulledBox(leaf->mins, leaf->maxs))
                                                {
-                                                       //for (portal = leaf->portals;portal;portal = portal->next)
-                                                       //      if (DotProduct(r_origin, portal->plane.normal) > portal->plane.dist)
-                                                       //              R_Clip_AddPolygon((float *)portal->points, portal->numpoints, sizeof(mvertex_t), false, R_Portal_Callback, leaf, portal, portal->plane);
-                                                       //leaf->visframe = r_framecount;
-                                                       c_leafs++;
-                                                       if (leaf->nummarksurfaces)
-                                                       {
-                                                               mark = leaf->firstmarksurface;
-                                                               endmark = mark + leaf->nummarksurfaces;
-                                                               if (r_ser.value)
-                                                               {
-                                                                       do
-                                                                       {
-                                                                               surf = *mark++;
-                                                                               // make sure surfaces are only processed once
-                                                                               if (surf->worldnodeframe == r_framecount)
-                                                                                       continue;
-                                                                               surf->worldnodeframe = r_framecount;
-                                                                               if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
-                                                                               {
-                                                                                       if (surf->flags & SURF_PLANEBACK)
-                                                                                       {
-                                                                                               VectorNegate(surf->plane->normal, plane.normal);
-                                                                                               plane.dist = -surf->plane->dist;
-                                                                                               for (poly = surf->polys;poly;poly = poly->next)
-                                                                                                       R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
-                                                                                       }
-                                                                               }
-                                                                               else
-                                                                               {
-                                                                                       if (!(surf->flags & SURF_PLANEBACK))
-                                                                                               for (poly = surf->polys;poly;poly = poly->next)
-                                                                                                       R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
-                                                                               }
-                                                                       }
-                                                                       while (mark < endmark);
-                                                               }
-                                                               else
-                                                               {
-                                                                       do
-                                                                       {
-                                                                               surf = *mark++;
-                                                                               // make sure surfaces are only processed once
-                                                                               if (surf->worldnodeframe == r_framecount)
-                                                                                       continue;
-                                                                               surf->worldnodeframe = r_framecount;
-                                                                               if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
-                                                                               {
-                                                                                       if (surf->flags & SURF_PLANEBACK)
-                                                                                               surf->visframe = r_framecount;
-                                                                               }
-                                                                               else
-                                                                               {
-                                                                                       if (!(surf->flags & SURF_PLANEBACK))
-                                                                                               surf->visframe = r_framecount;
-                                                                               }
-                                                                       }
-                                                                       while (mark < endmark);
-                                                               }
-                                                       }
+                                                       pstack[portalstack++] = p;
+                                                       goto loc0;
+
+loc1:
+                                                       p = pstack[--portalstack];
                                                }
                                        }
                                }
-                               k++;
                        }
-                       else
-                               k += *in++;
                }
        }
+
+       if (portalstack)
+               goto loc1;
 }
 
 entity_t clworldent;
@@ -1853,8 +1609,7 @@ void R_DrawSurfaces (void)
        texture_t       *t, *currentt;
        int vertex = gl_vertex.value;
 
-       currententity = &clworldent;
-       modelalpha = 1;
+       currentrenderentity = &clworldent.render;
        softwaretransformidentity();
        surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
        endsurf = surf + cl.worldmodel->nummodelsurfaces;
@@ -1955,6 +1710,19 @@ void R_DrawPortals(void)
        }
 }
 
+void R_SetupWorldEnt(void)
+{
+       memset (&clworldent, 0, sizeof(clworldent));
+       clworldent.render.model = cl.worldmodel;
+       clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1;
+       clworldent.render.alpha = 1;
+       clworldent.render.scale = 1;
+
+       VectorCopy (r_origin, modelorg);
+
+       currentrenderentity = &clworldent.render;
+}
+
 /*
 =============
 R_DrawWorld
@@ -1965,28 +1733,14 @@ void R_DrawWorld (void)
        wateralpha = bound(0, r_wateralpha.value*255.0f, 255);
        vertexworld = gl_vertex.value;
 
-       memset (&clworldent, 0, sizeof(clworldent));
-       clworldent.render.model = cl.worldmodel;
-       clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1;
-       modelalpha = clworldent.render.alpha = 1;
-       clworldent.render.scale = 1;
-
-       VectorCopy (r_origin, modelorg);
-
-       currententity = &clworldent;
+       R_SetupWorldEnt();
 
        softwaretransformidentity(); // LordHavoc: clear transform
 
-       if (cl.worldmodel)
-       {
-               if (r_novis.value || r_viewleaf->compressed_vis == NULL)
-                       R_SolidWorldNode ();
-               else
-               {
-//                     R_MarkLeaves ();
-                       R_PVSWorldNode ();
-               }
-       }
+       if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.value || r_viewleaf->compressed_vis == NULL)
+               R_SolidWorldNode ();
+       else
+               R_PVSWorldNode ();
 }
 
 /*
@@ -2008,7 +1762,7 @@ int AllocBlock (int w, int h, short *x, short *y)
        {
                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: align updates on 4 byte boundaries
                {
                        best2 = 0;
 
@@ -2040,17 +1794,16 @@ int AllocBlock (int w, int h, short *x, short *y)
                // LordHavoc: clear texture to blank image, fragments are uploaded using subimage
                else if (!allocated[texnum][0])
                {
-                       byte blank[BLOCK_WIDTH*BLOCK_HEIGHT*4];
-                       memset(blank, 0, sizeof(blank));
+                       memset(templight, 0, sizeof(templight));
                        if(r_upload.value)
                        {
                                glBindTexture(GL_TEXTURE_2D, lightmap_textures + texnum);
                                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                                if (lightmaprgba)
-                                       glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, blank);
+                                       glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, templight);
                                else
-                                       glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, blank);
+                                       glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, templight);
                        }
                }
 
@@ -2195,13 +1948,13 @@ void GL_CreateSurfaceLightmap (msurface_t *surf)
        smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask;
        if (lightmaprgba)
        {
-               R_BuildLightMap (surf, templight, smax * 4);
+               R_BuildLightMap (surf, templight, smax * 4, false);
                if(r_upload.value)
                        glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
        }
        else
        {
-               R_BuildLightMap (surf, templight, smax * 3);
+               R_BuildLightMap (surf, templight, smax * 3, false);
                if(r_upload.value)
                        glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
        }
@@ -2246,18 +1999,24 @@ void GL_BuildLightmaps (void)
                lightmapbytes = 3;
        }
 
-       // LordHavoc: NVIDIA seems to have a broken glTexSubImage2D,
-       //            it needs to be aligned on 4 pixel boundaries...
-       //            so I implemented an adjustable lightmap alignment
-       if (gl_lightmapalign.value < 1)
-               gl_lightmapalign.value = 1;
-       if (gl_lightmapalign.value > 16)
-               gl_lightmapalign.value = 16;
+       // LordHavoc: TexSubImage2D needs data aligned on 4 byte boundaries unless
+       // I specify glPixelStorei(GL_UNPACK_ALIGNMENT, 1), I suspect 4 byte may be
+       // faster anyway, so I implemented an adjustable lightmap alignment...
+
+       // validate the lightmap alignment
+       i = 1;
+       while (i < 16 && i < gl_lightmapalign.value)
+               i <<= 1;
+       Cvar_SetValue("gl_lightmapalign", i);
+
+       // find the lowest pixel count which satisfies the byte alignment
        lightmapalign = 1;
-       while (lightmapalign < gl_lightmapalign.value)
+       j = lightmaprgba ? 4 : 3; // bytes per pixel
+       while ((lightmapalign * j) & (i - 1))
                lightmapalign <<= 1;
-       gl_lightmapalign.value = lightmapalign;
        lightmapalignmask = ~(lightmapalign - 1);
+
+       // alignment is irrelevant if using fallback modes
        if (nosubimagefragments || nosubimage)
        {
                lightmapalign = 1;
@@ -2267,6 +2026,9 @@ void GL_BuildLightmaps (void)
        if (!lightmap_textures)
                lightmap_textures = R_GetTextureSlots(MAX_LIGHTMAPS);
 
+       // need a world entity for lightmap code
+       R_SetupWorldEnt();
+
        for (j=1 ; j<MAX_MODELS ; j++)
        {
                m = cl.model_precache[j];
index 729e292b17d1baf6682335557dc79416b35ed094..0cfd6ac1d5aceca24d0659f4cb8f949e3f137fd5 100644 (file)
@@ -70,8 +70,6 @@ console is:
 */
 
 
-int            glx, gly, glwidth, glheight;
-
 float  scr_con_current;
 float  scr_conlines;           // lines of console to display
 
@@ -164,7 +162,7 @@ void SCR_DrawCenterString (void)
        start = scr_centerstring;
 
        if (scr_center_lines <= 4)
-               y = vid.height*0.35;
+               y = vid.conheight*0.35;
        else
                y = 48;
 
@@ -174,7 +172,7 @@ void SCR_DrawCenterString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
+               x = (vid.conwidth - l*8)/2;
                // LordHavoc: speedup
                if (l > 0)
                {
@@ -229,19 +227,8 @@ CalcFov
 */
 float CalcFov (float fov_x, float width, float height)
 {
-       float   a;
-       float   x;
-
-       if (fov_x < 1 || fov_x > 179)
-               Sys_Error ("Bad fov: %f", fov_x);
-
-       x = width/tan(fov_x/360*M_PI);
-
-       a = atan (height/x);
-
-       a = a*360/M_PI;
-
-       return a;
+       // calculate vision size and alter by aspect, then convert back to angle
+       return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI;
 }
 
 /*
@@ -254,15 +241,12 @@ Internal use only
 */
 static void SCR_CalcRefdef (void)
 {
-       float           size;
-       int             h;
-       qboolean                full = false;
-
+       float size;
 
-       vid.recalc_refdef = 0;
+//     vid.recalc_refdef = 0;
 
 //========================================
-       
+
 // bound viewsize
        if (scr_viewsize.value < 30)
                Cvar_Set ("viewsize","30");
@@ -278,7 +262,6 @@ static void SCR_CalcRefdef (void)
 // intermission is always full screen
        if (cl.intermission)
        {
-               full = true;
                size = 1;
                sb_lines = 0;
        }
@@ -290,39 +273,31 @@ static void SCR_CalcRefdef (void)
                        sb_lines = 24;          // no inventory
                else
                        sb_lines = 24+16+8;
-
-               if (scr_viewsize.value >= 100.0)
-               {
-                       full = true;
-                       size = 1.0f;
-               }
-               else
-                       size = scr_viewsize.value * (1.0f / 100.0f);
+               size = scr_viewsize.value * (1.0 / 100.0);
        }
 
-       // LordHavoc: always fullscreen rendering
-       h = vid.height/* - sb_lines*/;
-
-       r_refdef.vrect.width = vid.width * size;
-       if (r_refdef.vrect.width < 96)
+       if (size >= 1)
        {
-               size = 96.0 / r_refdef.vrect.width;
-               r_refdef.vrect.width = 96;      // min for icons
+               r_refdef.width = vid.realwidth;
+               r_refdef.height = vid.realheight;
+               r_refdef.x = 0;
+               r_refdef.y = 0;
        }
-
-       r_refdef.vrect.height = vid.height * size;
-       //if (r_refdef.vrect.height > vid.height - sb_lines)
-       //      r_refdef.vrect.height = vid.height - sb_lines;
-       if (r_refdef.vrect.height > (int) vid.height)
-                       r_refdef.vrect.height = vid.height;
-       r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
-       if (full)
-               r_refdef.vrect.y = 0;
        else
-               r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
+       {
+               r_refdef.width = vid.realwidth * size;
+               r_refdef.height = vid.realheight * size;
+               r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+               r_refdef.y = (vid.realheight - r_refdef.height)/2;
+       }
 
        r_refdef.fov_x = scr_fov.value;
-       r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+       r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+       r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
+       r_refdef.height = bound(0, r_refdef.height, vid.realheight);
+       r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx;
+       r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy;
 }
 
 
@@ -336,7 +311,7 @@ Keybinding command
 void SCR_SizeUp_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value+10);
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 }
 
 
@@ -350,7 +325,7 @@ Keybinding command
 void SCR_SizeDown_f (void)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 }
 
 //============================================================================
@@ -415,13 +390,9 @@ SCR_DrawRam
 */
 void SCR_DrawRam (void)
 {
-       if (!scr_showram.value)
-               return;
-
-       if (!r_cache_thrash)
-               return;
-
-       Draw_Pic (32, 0, scr_ram);
+//     if (!scr_showram.value)
+//             return;
+//     Draw_Pic (32, 0, scr_ram);
 }
 
 /*
@@ -480,8 +451,7 @@ void SCR_DrawPause (void)
                return;
 
        pic = Draw_CachePic ("gfx/pause.lmp");
-       Draw_Pic ( (vid.width - pic->width)/2, 
-               (vid.height - 48 - pic->height)/2, pic);
+       Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
 }
 
 
@@ -500,8 +470,7 @@ void SCR_DrawLoading (void)
                return;
                
        pic = Draw_CachePic ("gfx/loading.lmp");
-       Draw_Pic ( (vid.width - pic->width)/2, 
-               (vid.height - 48 - pic->height)/2, pic);
+       Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
 }
 */
 
@@ -527,14 +496,14 @@ void SCR_SetUpToDrawConsole (void)
 
        if (con_forcedup)
        {
-               scr_conlines = vid.height;              // full screen
+               scr_conlines = vid.conheight;           // full screen
                scr_con_current = scr_conlines;
        }
        else if (key_dest == key_console)
-               scr_conlines = vid.height/2;    // half screen
+               scr_conlines = vid.conheight/2; // half screen
        else
                scr_conlines = 0;                               // none visible
-       
+
        if (scr_conlines < scr_con_current)
        {
                scr_con_current -= scr_conspeed.value*host_realframetime;
@@ -549,7 +518,7 @@ void SCR_SetUpToDrawConsole (void)
                        scr_con_current = scr_conlines;
        }
 }
-       
+
 /*
 ==================
 SCR_DrawConsole
@@ -572,33 +541,33 @@ void SCR_DrawConsole (void)
 
 /*
 ============================================================================== 
+
                                                SCREEN SHOTS 
  
 ============================================================================== 
 */ 
 
 /*
-================== 
+==================
 SCR_ScreenShot_f
-================== 
+==================
 */
-void SCR_ScreenShot_f (void) 
+void SCR_ScreenShot_f (void)
 {
-       byte            *buffer;
-       char            filename[80]; 
+       byte            *buffer, gamma[256];
+       char            filename[80];
        char            checkname[MAX_OSPATH];
        int                     i;
 //
-// find a file name to save it to 
-// 
+// find a file name to save it to
+//
        strcpy(filename,"dp0000.tga");
-               
-       for (i=0 ; i<=9999 ; i++) 
-       { 
-               filename[2] = (i/1000)%10 + '0'; 
-               filename[3] = (i/ 100)%10 + '0'; 
-               filename[4] = (i/  10)%10 + '0'; 
+
+       for (i=0 ; i<=9999 ; i++)
+       {
+               filename[2] = (i/1000)%10 + '0';
+               filename[3] = (i/ 100)%10 + '0';
+               filename[4] = (i/  10)%10 + '0';
                filename[5] = (i/   1)%10 + '0';
                sprintf (checkname, "%s/%s", com_gamedir, filename);
                if (Sys_FileTime(checkname) == -1)
@@ -606,13 +575,18 @@ void SCR_ScreenShot_f (void)
        }
        if (i==10000)
        {
-               Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); 
+               Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
                return;
        }
 
-       buffer = qmalloc(glwidth*glheight*3);
-       glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
-       Image_WriteTGARGB_preflipped(filename, glwidth, glheight, buffer);
+       buffer = qmalloc(vid.realwidth*vid.realheight*3);
+       glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+
+       // apply hardware gamma to the image
+       BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+       Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma);
+
+       Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer);
 
        qfree(buffer);
        Con_Printf ("Wrote %s\n", filename);
@@ -637,7 +611,7 @@ void SCR_BeginLoadingPlaque (void)
 //             return;
 //     if (cls.signon != SIGNONS)
 //             return;
-       
+
 // redraw with no console and the loading plaque
 //     Con_ClearNotify ();
 //     scr_centertime_off = 0;
@@ -678,7 +652,7 @@ void SCR_DrawNotifyString (void)
 
        start = scr_notifystring;
 
-       y = vid.height*0.35;
+       y = vid.conheight*0.35;
 
        do      
        {
@@ -686,7 +660,7 @@ void SCR_DrawNotifyString (void)
                for (l=0 ; l<40 ; l++)
                        if (start[l] == '\n' || !start[l])
                                break;
-               x = (vid.width - l*8)/2;
+               x = (vid.conwidth - l*8)/2;
                // LordHavoc: speedup
 //             for (j=0 ; j<l ; j++, x+=8)
 //                     Draw_Character (x, y, start[j]);
@@ -810,7 +784,7 @@ void SCR_UpdateScreen (void)
                return;                         // not initialized yet
 
 
-       GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+       GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
 
        if (gl_combine.value && !gl_combine_extension)
                Cvar_SetValue("gl_combine", false);
@@ -832,16 +806,16 @@ void SCR_UpdateScreen (void)
        if (oldfov != scr_fov.value)
        {
                oldfov = scr_fov.value;
-               vid.recalc_refdef = true;
+//             vid.recalc_refdef = true;
        }
 
        if (oldscreensize != scr_viewsize.value)
        {
                oldscreensize = scr_viewsize.value;
-               vid.recalc_refdef = true;
+//             vid.recalc_refdef = true;
        }
 
-       if (vid.recalc_refdef)
+//     if (vid.recalc_refdef)
                SCR_CalcRefdef();
 
        if (r_render.value)
@@ -895,18 +869,17 @@ void SCR_UpdateScreen (void)
                calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
                sprintf(temp, "%4i fps", calc);
                currtime = newtime;
-               Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999);
+               Draw_String(vid.conwidth - (8*8), vid.conheight - sb_lines - 8, temp, 9999);
        }
 
-       // LordHavoc: only print info if renderer is being used
-       if (r_speeds2.value && !con_forcedup)
+       if (r_speeds2.value && r_speeds2_string[0])
        {
                int i, j, lines, y;
                lines = 1;
                for (i = 0;r_speeds2_string[i];i++)
                        if (r_speeds2_string[i] == '\n')
                                lines++;
-               y = vid.height - sb_lines - lines * 8 - 8;
+               y = vid.conheight - sb_lines - lines * 8 - 8;
                i = j = 0;
                while (r_speeds2_string[i])
                {
@@ -919,6 +892,8 @@ void SCR_UpdateScreen (void)
                                i++;
                        y += 8;
                }
+               // clear so it won't reprint without renderer being called again
+               r_speeds2_string[0] = 0;
        }
 
        V_UpdateBlends();
index d1f65a1ea306994893ee143ac03a9c9e35b839b5..be414912de626a7add5b4ea89ca4e0b8d3287d74 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -54,58 +54,8 @@ typedef struct
 
 extern glvert_t glv;
 
-extern int glx, gly, glwidth, glheight;
-
-// r_local.h -- private refresh defs
-
-#define ALIAS_BASE_SIZE_RATIO          (1.0 / 11.0)
-                                       // normalizing factor so player model works out to about
-                                       //  1 pixel per triangle
-#define        MAX_LBM_HEIGHT          480
-
-#define BACKFACE_EPSILON       0.01
-
-
-extern void R_TimeRefresh_f (void);
-
 //====================================================
 
-
-extern qboolean        r_cache_thrash;         // compatability
-extern vec3_t          modelorg, r_entorigin;
-extern entity_t        *currententity;
-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;
-
-
-//
-// view origin
-//
-extern vec3_t  vup;
-extern vec3_t  vpn;
-extern vec3_t  vright;
-extern vec3_t  r_origin;
-
-//
-// screen size info
-//
-extern refdef_t        r_refdef;
-extern mleaf_t         *r_viewleaf, *r_oldviewleaf;
-extern unsigned short  d_lightstylevalue[256]; // 8.8 fraction of base light value
-
-extern qboolean        envmap;
-
-extern cvar_t  r_drawentities;
-extern cvar_t  r_drawviewmodel;
-extern cvar_t  r_speeds;
-extern cvar_t  r_fullbright;
-extern cvar_t  r_wateralpha;
-extern cvar_t  r_dynamic;
-extern cvar_t  r_waterripple;
-
-extern float   r_world_matrix[16];
-
 extern const char *gl_vendor;
 extern const char *gl_renderer;
 extern const char *gl_version;
diff --git a/host.c b/host.c
index 4d272b974d46c97d50a381dd7f3dbcef12a10099..38ef5231629c7fc1f18b3f9e1270e3747ed7b782 100644 (file)
--- a/host.c
+++ b/host.c
@@ -778,18 +778,6 @@ Host_Init
 void Host_Init (void)
 {
        int i;
-       /*
-       if (standard_quake)
-               minimum_memory = MINIMUM_MEMORY;
-       else
-               minimum_memory = MINIMUM_MEMORY_LEVELPAK;
-
-       if (COM_CheckParm ("-minmemory"))
-               host_parms.memsize = minimum_memory;
-
-       if (host_parms.memsize < minimum_memory)
-               Sys_Error ("Only %4.1f megs of memory available, can't execute game", host_parms.memsize / (float)0x100000);
-       */
 
        host_parms.memsize = DEFAULTMEM * 1024 * 1024;
 
index 745503219dcad3f3d3ec0380391d4f2389971f9d..780abeeb7ed0ab768040f57a97d1885bede96de4 100644 (file)
@@ -45,7 +45,7 @@ void Host_Quit_f (void)
        }
        */
        CL_Disconnect ();
-       Host_ShutdownServer(false);             
+       Host_ShutdownServer(false);
 
        Sys_Quit ();
 }
@@ -64,7 +64,7 @@ void Host_Status_f (void)
        int                     hours = 0;
        int                     j;
        void            (*print) (char *fmt, ...);
-       
+
        if (cmd_source == src_command)
        {
                if (!sv.active)
@@ -78,7 +78,7 @@ void Host_Status_f (void)
                print = SV_ClientPrintf;
 
        print ("host:    %s\n", Cvar_VariableString ("hostname"));
-       print ("version: %4.2f (build %i)\n", VERSION, buildnumber);
+       print ("version: %s build %i\n", gamename, buildnumber);
        if (tcpipAvailable)
                print ("tcp/ip:  %s\n", my_tcpip_address);
        if (ipxAvailable)
@@ -715,7 +715,7 @@ void Host_Name_f (void)
        
 void Host_Version_f (void)
 {
-       Con_Printf ("Version %4.2f (build %i)\n", VERSION, buildnumber);
+       Con_Printf ("Version: %s build %i\n", gamename, buildnumber);
        Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
 }
 
@@ -1275,58 +1275,58 @@ void Host_Give_f (void)
 
        t = Cmd_Argv(1);
        v = atoi (Cmd_Argv(2));
-       
+
        switch (t[0])
        {
-   case '0':
-   case '1':
-   case '2':
-   case '3':
-   case '4':
-   case '5':
-   case '6':
-   case '7':
-   case '8':
-   case '9':
-      // MED 01/04/97 added hipnotic give stuff
-      if (hipnotic)
-      {
-         if (t[0] == '6')
-         {
-            if (t[1] == 'a')
-               sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
-            else
-               sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
-         }
-         else if (t[0] == '9')
-            sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
-         else if (t[0] == '0')
-            sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
-         else if (t[0] >= '2')
-            sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
-      }
-      else
-      {
-         if (t[0] >= '2')
-            sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
-      }
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+               // MED 01/04/97 added hipnotic give stuff
+               if (gamemode == GAME_HIPNOTIC)
+               {
+                       if (t[0] == '6')
+                       {
+                               if (t[1] == 'a')
+                               sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
+                               else
+                               sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
+                       }
+                       else if (t[0] == '9')
+                               sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
+                       else if (t[0] == '0')
+                               sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
+                       else if (t[0] >= '2')
+                               sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
+               }
+               else
+               {
+                       if (t[0] >= '2')
+                               sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
+               }
                break;
-       
-    case 's':
-               if (rogue)
+
+       case 's':
+               if (gamemode == GAME_ROGUE)
                {
-                   if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1)))
-                           val->_float = v;
+                       if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1)))
+                               val->_float = v;
                }
 
-        sv_player->v.ammo_shells = v;
-        break;         
-    case 'n':
-               if (rogue)
+               sv_player->v.ammo_shells = v;
+               break;
+       case 'n':
+               if (gamemode == GAME_ROGUE)
                {
-                   if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1)))
+                       if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1)))
                        {
-                           val->_float = v;
+                               val->_float = v;
                                if (sv_player->v.weapon <= IT_LIGHTNING)
                                        sv_player->v.ammo_nails = v;
                        }
@@ -1335,9 +1335,9 @@ void Host_Give_f (void)
                {
                        sv_player->v.ammo_nails = v;
                }
-        break;         
-    case 'l':
-               if (rogue)
+               break;
+       case 'l':
+               if (gamemode == GAME_ROGUE)
                {
                        val = GETEDICTFIELDVALUE(sv_player, eval_ammo_lava_nails);
                        if (val)
@@ -1347,9 +1347,9 @@ void Host_Give_f (void)
                                        sv_player->v.ammo_nails = v;
                        }
                }
-        break;
-    case 'r':
-               if (rogue)
+               break;
+       case 'r':
+               if (gamemode == GAME_ROGUE)
                {
                        val = GETEDICTFIELDVALUE(sv_player, eval_ammo_rockets1);
                        if (val)
@@ -1363,9 +1363,9 @@ void Host_Give_f (void)
                {
                        sv_player->v.ammo_rockets = v;
                }
-        break;         
-    case 'm':
-               if (rogue)
+               break;
+       case 'm':
+               if (gamemode == GAME_ROGUE)
                {
                        val = GETEDICTFIELDVALUE(sv_player, eval_ammo_multi_rockets);
                        if (val)
@@ -1375,12 +1375,12 @@ void Host_Give_f (void)
                                        sv_player->v.ammo_rockets = v;
                        }
                }
-        break;         
-    case 'h':
-        sv_player->v.health = v;
-        break;         
-    case 'c':
-               if (rogue)
+               break;
+       case 'h':
+               sv_player->v.health = v;
+               break;
+       case 'c':
+               if (gamemode == GAME_ROGUE)
                {
                        val = GETEDICTFIELDVALUE(sv_player, eval_ammo_cells1);
                        if (val)
@@ -1394,9 +1394,9 @@ void Host_Give_f (void)
                {
                        sv_player->v.ammo_cells = v;
                }
-        break;         
-    case 'p':
-               if (rogue)
+               break;
+       case 'p':
+               if (gamemode == GAME_ROGUE)
                {
                        val = GETEDICTFIELDVALUE(sv_player, eval_ammo_plasma);
                        if (val)
@@ -1406,15 +1406,15 @@ void Host_Give_f (void)
                                        sv_player->v.ammo_cells = v;
                        }
                }
-        break;         
-    }
+               break;
+       }
 }
 
 edict_t        *FindViewthing (void)
 {
        int             i;
        edict_t *e;
-       
+
        for (i=0 ; i<sv.num_edicts ; i++)
        {
                e = EDICT_NUM(i);
@@ -1477,8 +1477,7 @@ void Host_Viewframe_f (void)
 void PrintFrameName (model_t *m, int frame)
 {
        int data;
-       data = (int) Mod_Extradata(m);
-       if (m->ofs_scenes && data)
+       if (m->ofs_scenes && (data = (int) Mod_Extradata(m)))
                Con_Printf("frame %i: %s\n", frame, ((animscene_t *) (m->ofs_scenes + data))[frame].name);
        else
                Con_Printf("frame %i\n", frame);
@@ -1620,7 +1619,7 @@ void Host_InitCommands (void)
 {
        Cmd_AddCommand ("status", Host_Status_f);
        Cmd_AddCommand ("quit", Host_Quit_f);
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                Cmd_AddCommand ("max", Host_God_f);
                Cmd_AddCommand ("monster", Host_Notarget_f);
diff --git a/image.c b/image.c
index acfdf77bd66281d0336f0a40b36dff766786b8f7..6023e91b9927b4a358deb58304b49c5f1b62010d 100644 (file)
--- a/image.c
+++ b/image.c
@@ -4,6 +4,18 @@
 int            image_width;
 int            image_height;
 
+void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab)
+{
+       while (pixels--)
+       {
+               out[0] = gammar[in[0]];
+               out[1] = gammag[in[1]];
+               out[2] = gammab[in[2]];
+               in += 3;
+               out += 3;
+       }
+}
+
 // note: pal must be 32bit color
 void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal)
 {
diff --git a/image.h b/image.h
index 9fc65f0db855bfeb257ff018675dd50594ff2bcc..0a1d73fd97bfcee28094a7f2bcdca24510406b2f 100644 (file)
--- a/image.h
+++ b/image.h
@@ -1,4 +1,5 @@
 
+void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab);
 void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
 void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
 int image_makemask (byte *in, byte *out, int size);
diff --git a/keys.c b/keys.c
index 9632ed637722f9b4848965f96aff376a72d9922a..6fe4a86f2bc125ef26537a79d06afb526a4b0ffd 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -279,8 +279,8 @@ void Key_Console (int key)
        if (key == K_PGUP || key==K_MWHEELUP)
        {
                con_backscroll += 2;
-               if (con_backscroll > con_totallines - (vid.height>>3) - 1)
-                       con_backscroll = con_totallines - (vid.height>>3) - 1;
+               if (con_backscroll > con_totallines - (vid.conheight>>3) - 1)
+                       con_backscroll = con_totallines - (vid.conheight>>3) - 1;
                return;
        }
 
@@ -294,7 +294,7 @@ void Key_Console (int key)
 
        if (key == K_HOME)
        {
-               con_backscroll = con_totallines - (vid.height>>3) - 1;
+               con_backscroll = con_totallines - (vid.conheight>>3) - 1;
                return;
        }
 
index f30f40ac09621e940fc923df86a814a9111fae8e..a6f6e42381dead199d49606e5ec07f997b19fa7b 100644 (file)
--- a/makefile
+++ b/makefile
@@ -9,7 +9,7 @@ SOUNDLIB=-lasound
 #SND=snd_oss.o
 #SOUNDLIB=
 
-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 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 protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.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 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 protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o
 
 #K6/athlon optimizations
 CPUOPTIMIZATIONS=-march=k6
@@ -37,9 +37,17 @@ CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -I/usr/include/glide $(OPTIMIZATI
 LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl $(SOUNDLIB) -lz $(PROFILEOPTION)
 
 #most people can't build the -3dfx version (-3dfx version needs some updates for new mesa)
-all: darkplaces-glx
+all: buildnum darkplaces-glx
 #all: darkplaces-glx darkplaces-3dfx
 
+buildnum/buildnum:
+       cd buildnum
+       make
+       cd ..
+
+buildnum: buildnum/buildnum
+       buildnum/buildnum buildnumber.c
+
 .c.o:
        gcc $(CFLAGS) -c $*.c
 
@@ -54,6 +62,6 @@ clean:
        -rm -f darkplaces-glx darkplaces-3dfx
        -rm -f vid_glx.o in_svgalib.o vid_3dfxsvga.o $(OBJECTS) *.d
 
-.PHONY: clean
+.PHONY: clean buildnum
 
 -include *.d
index 6709b1e54b478dfdeb15513334804c4dc658d4f8..726cd089590a16dc992d46479d4d74d020c5404e 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -631,7 +631,7 @@ int VectorCompare (vec3_t v1, vec3_t v2)
        return 1;
 }
 
-void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
+void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
 {
        vecc[0] = veca[0] + scale*vecb[0];
        vecc[1] = veca[1] + scale*vecb[1];
index d3cfe5eed9af64d588443beeaf1079b37af8fe20..96497960fb508d9fb55a0528d995363b60354cb0 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -63,7 +63,7 @@ extern        int nanmask;
 #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
 #define VectorLength(a) sqrt(DotProduct(a, a))
 #define VectorScale(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);}
-#define VectorMAQuick(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];}
+#define VectorMA(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];}
 #define VectorNormalizeFast(_v)\
 {\
        float _y, _number;\
@@ -74,10 +74,11 @@ extern      int nanmask;
                _y = _y * (1.5f - (_number * 0.5f * _y * _y));\
                VectorScale(_v, _y, _v);\
        }\
-}\
+}
+#define VectorRandom(v) {do{(v)[0] = lhrandom(-1, 1);(v)[1] = lhrandom(-1, 1);(v)[2] = lhrandom(-1, 1);}while(DotProduct(v, v) > 1);}
 
 
-void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
+void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
 
 vec_t _DotProduct (vec3_t v1, vec3_t v2);
 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
@@ -152,3 +153,5 @@ typedef struct
 {
        double  normal[3], dist;
 } tinydoubleplane_t;
+
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
diff --git a/menu.c b/menu.c
index e768754171cd7f2d9703d6a0dc1d2a51b4d99939..c4d80a5bee9182a751e85657a1027f6d5abd4b59 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -119,7 +119,7 @@ Draws one solid graphics character
 */
 void M_DrawCharacter (int cx, int line, int num)
 {
-       Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
+       Draw_Character ( cx + ((vid.conwidth - 320)>>1), line, num);
 }
 
 void M_Print (int cx, int cy, char *str)
@@ -144,7 +144,7 @@ void M_PrintWhite (int cx, int cy, char *str)
 
 void M_DrawPic (int x, int y, qpic_t *pic)
 {
-       Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
+       Draw_Pic (x + ((vid.conwidth - 320)>>1), y, pic);
 }
 
 byte identityTable[256];
@@ -179,7 +179,7 @@ void M_BuildTranslationTable(int top, int bottom)
 
 void M_DrawPicTranslate (int x, int y, qpic_t *pic)
 {
-       Draw_PicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
+       Draw_PicTranslate (x + ((vid.conwidth - 320)>>1), y, pic, translationTable);
 }
 
 
@@ -420,7 +420,7 @@ int MAIN_ITEMS = 4; // Nehahra: Menu Disable
 
 void M_Menu_Main_f (void)
 {
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                if (NehGameType == TYPE_DEMO)
                        MAIN_ITEMS = 4;
@@ -452,7 +452,7 @@ void M_Main_Draw (void)
        p = Draw_CachePic ("gfx/ttl_main.lmp");
        M_DrawPic ( (320-p->width)/2, 4, p);
 // Nehahra
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                if (NehGameType == TYPE_BOTH)
                        M_DrawPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp"));
@@ -497,7 +497,7 @@ void M_Main_Key (int key)
        case K_ENTER:
                m_entersound = true;
 
-               if (nehahra)
+               if (gamemode == GAME_NEHAHRA)
                {
                        switch (NehGameType)
                        {
@@ -673,7 +673,7 @@ void M_SinglePlayer_Key (int key)
                        if (sv.active)
                                Cbuf_AddText ("disconnect\n");
                        Cbuf_AddText ("maxplayers 1\n");
-                       if (nehahra)
+                       if (gamemode == GAME_NEHAHRA)
                                Cbuf_AddText ("map nehstart\n");
                        else
                                Cbuf_AddText ("map start\n");
@@ -1758,7 +1758,7 @@ char *quitMessage [] =
   "  this game just like   ",
   "   everything else?     ",
   "                        ",
+
   " Milord, methinks that  ",
   "   thou art a lowly     ",
   " quitter. Is this true? ",
@@ -2335,7 +2335,7 @@ void M_GameOptions_Draw (void)
                M_Print (160, 64, "Deathmatch");
 
        M_Print (0, 72, "        Teamplay");
-       if (rogue)
+       if (gamemode == GAME_ROGUE)
        {
                char *msg;
 
@@ -2387,40 +2387,40 @@ void M_GameOptions_Draw (void)
                M_Print (160, 96, va("%i minutes", (int)timelimit.value));
 
        M_Print (0, 112, "         Episode");
-   //MED 01/06/97 added hipnotic episodes
-   if (hipnotic)
-      M_Print (160, 112, hipnoticepisodes[startepisode].description);
-   //PGM 01/07/97 added rogue episodes
-   else if (rogue)
-      M_Print (160, 112, rogueepisodes[startepisode].description);
-   else if (nehahra)
-      M_Print (160, 112, nehahraepisodes[startepisode].description);
-   else
-      M_Print (160, 112, episodes[startepisode].description);
+       //MED 01/06/97 added hipnotic episodes
+       if (gamemode == GAME_HIPNOTIC)
+               M_Print (160, 112, hipnoticepisodes[startepisode].description);
+       //PGM 01/07/97 added rogue episodes
+       else if (gamemode == GAME_ROGUE)
+               M_Print (160, 112, rogueepisodes[startepisode].description);
+       else if (gamemode == GAME_NEHAHRA)
+               M_Print (160, 112, nehahraepisodes[startepisode].description);
+       else
+               M_Print (160, 112, episodes[startepisode].description);
 
        M_Print (0, 120, "           Level");
-   //MED 01/06/97 added hipnotic episodes
-   if (hipnotic)
-   {
-      M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
-      M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
-   }
-   //PGM 01/07/97 added rogue episodes
-   else if (rogue)
-   {
-      M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
-      M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
-   }
-   else if (nehahra)
-   {
-      M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description);
-      M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name);
-   }
-   else
-   {
-      M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
-      M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
-   }
+       //MED 01/06/97 added hipnotic episodes
+       if (gamemode == GAME_HIPNOTIC)
+       {
+               M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
+               M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
+       }
+       //PGM 01/07/97 added rogue episodes
+       else if (gamemode == GAME_ROGUE)
+       {
+               M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
+               M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
+       }
+       else if (gamemode == GAME_NEHAHRA)
+       {
+               M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description);
+               M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name);
+       }
+       else
+       {
+               M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
+               M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
+       }
 
 // line cursor
        M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
@@ -2483,7 +2483,7 @@ void M_NetStart_Change (int dir)
                break;
 
        case 3:
-               if (rogue)
+               if (gamemode == GAME_ROGUE)
                        count = 6;
                else
                        count = 2;
@@ -2522,13 +2522,13 @@ void M_NetStart_Change (int dir)
        case 7:
                startepisode += dir;
        //MED 01/06/97 added hipnotic count
-               if (hipnotic)
+               if (gamemode == GAME_HIPNOTIC)
                        count = 6;
        //PGM 01/07/97 added rogue count
        //PGM 03/02/97 added 1 for dmatch episode
-               else if (rogue)
+               else if (gamemode == GAME_ROGUE)
                        count = 4;
-               else if (nehahra)
+               else if (gamemode == GAME_NEHAHRA)
                        count = 4;
                else if (registered.value)
                        count = 7;
@@ -2547,12 +2547,12 @@ void M_NetStart_Change (int dir)
        case 8:
                startlevel += dir;
     //MED 01/06/97 added hipnotic episodes
-               if (hipnotic)
+               if (gamemode == GAME_HIPNOTIC)
                        count = hipnoticepisodes[startepisode].levels;
        //PGM 01/06/97 added hipnotic episodes
-               else if (rogue)
+               else if (gamemode == GAME_ROGUE)
                        count = rogueepisodes[startepisode].levels;
-               else if (nehahra)
+               else if (gamemode == GAME_NEHAHRA)
                        count = nehahraepisodes[startepisode].levels;
                else
                        count = episodes[startepisode].levels;
@@ -2612,11 +2612,11 @@ void M_GameOptions_Key (int key)
                        Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
 //                     SCR_BeginLoadingPlaque ();
 
-                       if (hipnotic)
+                       if (gamemode == GAME_HIPNOTIC)
                                Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) );
-                       else if (rogue)
+                       else if (gamemode == GAME_ROGUE)
                                Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) );
-                       else if (nehahra)
+                       else if (gamemode == GAME_NEHAHRA)
                                Cbuf_AddText ( va ("map %s\n", nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name) );
                        else
                                Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
@@ -2812,7 +2812,7 @@ void M_Init (void)
        Cmd_AddCommand ("help", M_Menu_Help_f);
        Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
 
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                if (COM_FileExists("maps/neh1m4.bsp"))
                {
@@ -2854,7 +2854,7 @@ void M_Draw (void)
        {
                if (scr_con_current)
                {
-                       Draw_ConsoleBackground (vid.height);
+                       Draw_ConsoleBackground (vid.conheight);
                        S_ExtraUpdate ();
                }
        }
index 103260262fe2dbb7880f3c63d9e1782ccfb17fcd..edca9f90b45a33ebfd52b33c7a7e744cac9614ba 100644 (file)
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "1"};
+static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
 
 /*
 ===============
@@ -32,19 +32,26 @@ void Mod_AliasInit (void)
        Cvar_RegisterVariable(&r_mipskins);
 }
 
-int                    posenum;
+static void Mod_Alias_SERAddEntity(void)
+{
+       R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
+}
+
+static int posenum;
 
-float          aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations
+// LordHavoc: proper bounding box considerations
+static float aliasbboxmin[3], aliasbboxmax[3], modelyawradius, modelradius;
 
-float vertst[MAXALIASVERTS][2];
-int vertusage[MAXALIASVERTS];
-int vertonseam[MAXALIASVERTS];
-int vertremap[MAXALIASVERTS];
-unsigned short temptris[MAXALIASTRIS][3];
+static float vertst[MAXALIASVERTS][2];
+static int vertusage[MAXALIASVERTS];
+static int vertonseam[MAXALIASVERTS];
+static int vertremap[MAXALIASVERTS];
+static unsigned short temptris[MAXALIASTRIS][3];
 
-void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
+static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
 {
        int i, j, invalidnormals = 0;
+       float dist;
        vec3_t temp;
        for (i = 0;i < inverts;i++)
        {
@@ -60,6 +67,12 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert
                if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
                if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
                if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+               dist = temp[0]*temp[0]+temp[1]*temp[1];
+               if (modelyawradius < dist)
+                       modelyawradius = dist;
+               dist += temp[2]*temp[2];
+               if (modelradius < dist)
+                       modelradius = dist;
                j = vertremap[i]; // not onseam
                if (j >= 0)
                {
@@ -92,11 +105,11 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert
 Mod_LoadAliasFrame
 =================
 */
-void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
+static void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
 {
        trivertx_t              *pinframe;
        daliasframe_t   *pdaliasframe;
-       
+
        pdaliasframe = (daliasframe_t *)pin;
 
        strcpy(scene->name, pdaliasframe->name);
@@ -122,12 +135,12 @@ void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int out
 Mod_LoadAliasGroup
 =================
 */
-void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
+static void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
 {
        int             i, numframes;
        void    *ptemp;
        float   interval;
-       
+
        numframes = LittleLong (((daliasgroup_t *)pin)->numframes);
 
        strcpy(scene->name, ((daliasframe_t *) (sizeof(daliasinterval_t) * numframes + sizeof(daliasgroup_t) + (int) pin))->name);
@@ -155,81 +168,7 @@ void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outv
 
 //=========================================================
 
-/*
-=================
-Mod_FloodFillSkin
-
-Fill background pixels so mipmapping doesn't have haloes - Ed
-=================
-*/
-
-typedef struct
-{
-       short           x, y;
-} floodfill_t;
-
-// must be a power of 2
-#define FLOODFILL_FIFO_SIZE 0x1000
-#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
-
-#define FLOODFILL_STEP( off, dx, dy ) \
-{ \
-       if (pos[off] == fillcolor) \
-       { \
-               pos[off] = 255; \
-               fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
-               inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
-       } \
-       else if (pos[off] != 255) fdc = pos[off]; \
-}
-
-void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
-{
-       byte                            fillcolor = *skin; // assume this is the pixel to fill
-       floodfill_t                     fifo[FLOODFILL_FIFO_SIZE];
-       int                                     inpt = 0, outpt = 0;
-       int                                     filledcolor = -1;
-       int                                     i;
-
-       if (filledcolor == -1)
-       {
-               filledcolor = 0;
-               // attempt to find opaque black
-               for (i = 0; i < 256; ++i)
-                       if (d_8to24table[i] == (255 << 0)) // alpha 1.0
-                       {
-                               filledcolor = i;
-                               break;
-                       }
-       }
-
-       // can't fill to filled color or to transparent color (used as visited marker)
-       if ((fillcolor == filledcolor) || (fillcolor == 255))
-       {
-               //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
-               return;
-       }
-
-       fifo[inpt].x = 0, fifo[inpt].y = 0;
-       inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
-
-       while (outpt != inpt)
-       {
-               int                     x = fifo[outpt].x, y = fifo[outpt].y;
-               int                     fdc = filledcolor;
-               byte            *pos = &skin[x + skinwidth * y];
-
-               outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
-
-               if (x > 0)                              FLOODFILL_STEP( -1, -1, 0 );
-               if (x < skinwidth - 1)  FLOODFILL_STEP( 1, 1, 0 );
-               if (y > 0)                              FLOODFILL_STEP( -skinwidth, 0, -1 );
-               if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
-               skin[x + skinwidth * y] = fdc;
-       }
-}
-
-rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
+static rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
 {
        int i, pixels, passed;
        byte pixeltest[16];
@@ -259,7 +198,7 @@ rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsign
                return NULL;
 }
 
-rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
+static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
 {
        int i, pixels, passed;
        byte pixeltest[16];
@@ -285,7 +224,7 @@ rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned sh
                return NULL;
 }
 
-int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
+static int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
 {
        int i, pixels, passed;
        byte pixeltest[16];
@@ -302,7 +241,7 @@ int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
        return false;
 }
 
-void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex)
+static void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex)
 {
        skintex[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, r_mipskins.value, true);
        skintex[1] = NULL;
@@ -340,7 +279,7 @@ void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *s
 Mod_LoadAllSkins
 ===============
 */
-void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height)
+static void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height)
 {
        int             i, j;
        char    name[32];
@@ -353,7 +292,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
        rtexture_t **skintex;
        void    *temp;
        byte    *skintemp = NULL;
-       
+
        skin = (byte *)(pskintype + 1);
 
        if (numskins < 1 || numskins > MAX_SKINS)
@@ -429,7 +368,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
        return (void *)pskintype;
 }
 
-void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
+static void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
 {
        int             i;
        for (i = 0;i < numskins;i++)
@@ -468,6 +407,9 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        trivertx_t                      *posevert;
        animscene_t                     *animscenes;
 
+       modelyawradius = 0;
+       modelradius = 0;
+
        start = Hunk_LowMark ();
 
        pinmodel = (mdl_t *)buffer;
@@ -632,11 +574,24 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        // LordHavoc: fixed model bbox - was //FIXME: do this right
        //mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
        //mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+       modelyawradius = sqrt(modelyawradius);
+       modelradius = sqrt(modelradius);
+//     mod->modelradius = modelradius;
        for (j = 0;j < 3;j++)
        {
-               mod->mins[j] = aliasbboxmin[j];
-               mod->maxs[j] = aliasbboxmax[j];
+               mod->normalmins[j] = aliasbboxmin[j];
+               mod->normalmaxs[j] = aliasbboxmax[j];
+               mod->rotatedmins[j] = -modelradius;
+               mod->rotatedmaxs[j] = modelradius;
        }
+       mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+       mod->yawmins[2] = mod->normalmins[2];
+       mod->yawmaxs[2] = mod->normalmaxs[2];
+
+       mod->SERAddEntity = Mod_Alias_SERAddEntity;
+       mod->DrawEarly = NULL;
+       mod->DrawLate = R_DrawAliasModel;
+       mod->DrawShadow = NULL;
 
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
@@ -650,9 +605,10 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        Hunk_FreeToLowMark (start);
 }
 
-void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
+static void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
 {
        int i, invalidnormals = 0;
+       float dist;
        vec3_t temp;
        for (i = 0;i < numverts;i++)
        {
@@ -667,6 +623,12 @@ void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, triv
                if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
                if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
                if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+               dist = temp[0]*temp[0]+temp[1]*temp[1];
+               if (modelyawradius < dist)
+                       modelyawradius = dist;
+               dist += temp[2]*temp[2];
+               if (modelradius < dist)
+                       modelradius = dist;
                out[i].lightnormalindex = v[i].lightnormalindex;
                if (out[i].lightnormalindex >= NUMVERTEXNORMALS)
                {
@@ -695,6 +657,9 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 //     temptris_t                      *tris;
        animscene_t                     *animscenes;
 
+       modelyawradius = 0;
+       modelradius = 0;
+
        start = Hunk_LowMark ();
 
 //     if (!temptris)
@@ -705,7 +670,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        version = LittleLong (pinmodel->version);
        if (version != MD2ALIAS_VERSION)
                Host_Error ("%s has wrong version number (%i should be %i)",
-                                mod->name, version, MD2ALIAS_VERSION);
+                       mod->name, version, MD2ALIAS_VERSION);
 
        mod->type = mod_alias;
        mod->aliastype = ALIASTYPE_MD2;
@@ -720,7 +685,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        if (size <= 0 || size >= MD2MAX_SIZE)
                Host_Error ("%s is not a valid model", mod->name);
        pheader = Hunk_AllocName (size, va("%s Quake2 model", loadname));
-       
+
        mod->flags = 0; // there are no MD2 flags
        mod->numframes = LittleLong(pinmodel->num_frames);
        mod->synctype = ST_RAND;
@@ -761,7 +726,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                int *skinrange;
                skinrange = loadmodel->skinanimrange;
                skin = loadmodel->skinanim;
-//             skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);  
+//             skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
 //             skin = skinrange + pheader->num_skins * 2;
 //             loadmodel->skinanimrange = (int) skinrange - (int) pheader;
 //             loadmodel->skinanim = (int) skin - (int) pheader;
@@ -835,11 +800,19 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        mod->ofs_scenes = (int) animscenes - (int) pheader;
 
        // LordHavoc: model bbox
+       modelyawradius = sqrt(modelyawradius);
+       modelradius = sqrt(modelradius);
+//     mod->modelradius = modelradius;
        for (j = 0;j < 3;j++)
        {
-               mod->mins[j] = aliasbboxmin[j];
-               mod->maxs[j] = aliasbboxmax[j];
+               mod->normalmins[j] = aliasbboxmin[j];
+               mod->normalmaxs[j] = aliasbboxmax[j];
+               mod->rotatedmins[j] = -modelradius;
+               mod->rotatedmaxs[j] = modelradius;
        }
+       mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+       mod->yawmins[2] = mod->normalmins[2];
+       mod->yawmaxs[2] = mod->normalmaxs[2];
 
        // load the draw list
        pinglcmd = (void*) ((int) pinmodel + LittleLong(pinmodel->ofs_glcmds));
@@ -848,6 +821,11 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        for (i = 0;i < pheader->num_glcmds;i++)
                *poutglcmd++ = LittleLong(*pinglcmd++);
 
+       mod->SERAddEntity = Mod_Alias_SERAddEntity;
+       mod->DrawEarly = NULL;
+       mod->DrawLate = R_DrawAliasModel;
+       mod->DrawShadow = NULL;
+
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
        mod->cachesize = total = end - start;
@@ -860,7 +838,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        Hunk_FreeToLowMark (start);
 }
 
-void swapintblock(int *m, int size)
+static void swapintblock(int *m, int size)
 {
        size /= 4;
        while(size--)
@@ -879,6 +857,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
        zymscene_t *scene;
        zymbone_t *bone;
        animscene_t *animscenes;
+       float corner[2], modelradius;
 
        start = Hunk_LowMark ();
 
@@ -936,7 +915,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
 // load the skins
        skinrange = loadmodel->skinanimrange;
        skin = loadmodel->skinanim;
-//     skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);  
+//     skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
 //     skin = skinrange + pheader->num_skins * 2;
 //     loadmodel->skinanimrange = (int) skinrange - (int) pheader;
 //     loadmodel->skinanim = (int) skin - (int) pheader;
@@ -1017,16 +996,33 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
        swapintblock((void *) (pheader->lump_trizone.start + pbase), pheader->lump_trizone.length);
 
        // model bbox
+       modelradius = pheader->radius;
+//     mod->modelradius = pheader->radius;
        for (i = 0;i < 3;i++)
        {
-               mod->mins[i] = pheader->mins[i];
-               mod->maxs[i] = pheader->maxs[i];
+               mod->normalmins[i] = pheader->mins[i];
+               mod->normalmaxs[i] = pheader->maxs[i];
+               mod->rotatedmins[i] = -modelradius;
+               mod->rotatedmaxs[i] = modelradius;
        }
+       corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
+       corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
+       mod->yawmaxs[0] = mod->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
+       if (mod->yawmaxs[0] > modelradius)
+               mod->yawmaxs[0] = mod->yawmaxs[1] = modelradius;
+       mod->yawmins[0] = mod->yawmins[1] = -mod->yawmaxs[0];
+       mod->yawmins[2] = mod->normalmins[2];
+       mod->yawmaxs[2] = mod->normalmaxs[2];
+
+       mod->SERAddEntity = Mod_Alias_SERAddEntity;
+       mod->DrawEarly = NULL;
+       mod->DrawLate = R_DrawAliasModel;
+       mod->DrawShadow = NULL;
 
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
        mod->cachesize = total = end - start;
-       
+
        Cache_Alloc (&mod->cache, total, loadname);
        if (!mod->cache.data)
                return;
index d2cee3f5fcdd1d92de8dc4161ff52656e9b51d4d..b005563b02b4630bdd9d04c91a5c7e9c5de5c697 100644 (file)
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-byte   mod_novis[MAX_MAP_LEAFS/8];
+byte mod_novis[(MAX_MAP_LEAFS + 7)/ 8];
 
 qboolean       hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30)
 
@@ -38,7 +38,12 @@ void Mod_BrushInit (void)
        Cvar_RegisterVariable (&gl_subdivide_size);
        Cvar_RegisterVariable (&halflifebsp);
        Cvar_RegisterVariable (&r_novis);
-       memset (mod_novis, 0xff, sizeof(mod_novis));
+       memset(mod_novis, 0xff, sizeof(mod_novis));
+}
+
+void Mod_Brush_SERAddEntity(void)
+{
+       R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
 }
 
 /*
@@ -49,7 +54,7 @@ Mod_PointInLeaf
 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
 {
        mnode_t         *node;
-       
+
 //     if (!model || !model->nodes)
 //             Sys_Error ("Mod_PointInLeaf: bad model");
 
@@ -66,7 +71,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
        mnode_t         *node;
        float           d;
        mplane_t        *plane;
-       
+
        if (!model || !model->nodes)
                Sys_Error ("Mod_PointInLeaf: bad model");
 
@@ -92,7 +97,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
 Mod_DecompressVis
 ===================
 */
-byte *Mod_DecompressVis (byte *in, model_t *model)
+static byte *Mod_DecompressVis (byte *in, model_t *model)
 {
        static byte     decompressed[MAX_MAP_LEAFS/8];
        int             c;
@@ -110,7 +115,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
                        *out++ = 0xff;
                        row--;
                }
-               return decompressed;            
+               return decompressed;
        }
        */
 
@@ -121,7 +126,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
                        *out++ = *in++;
                        continue;
                }
-       
+
                c = in[1];
                in += 2;
                while (c)
@@ -130,7 +135,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model)
                        c--;
                }
        } while (out - decompressed < row);
-       
+
        return decompressed;
 }
 
@@ -187,7 +192,7 @@ void Mod_SetupNoTexture(void)
 Mod_LoadTextures
 =================
 */
-void Mod_LoadTextures (lump_t *l)
+static void Mod_LoadTextures (lump_t *l)
 {
        int                             i, j, k, num, max, altmax, mtwidth, mtheight, *dofs;
        miptex_t                *dmiptex;
@@ -204,7 +209,7 @@ void Mod_LoadTextures (lump_t *l)
        m = (dmiptexlump_t *)(mod_base + l->fileofs);
        
        m->nummiptex = LittleLong (m->nummiptex);
-       
+
        loadmodel->numtextures = m->nummiptex;
        loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname));
 
@@ -227,11 +232,14 @@ void Mod_LoadTextures (lump_t *l)
                                Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name);
                        mtdata = (byte *)dmiptex + j;
                }
-               
+
                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));
+               memset(tx, 0, sizeof(texture_t));
+               tx->anim_total = 0;
+               tx->alternate_anims = NULL;
                loadmodel->textures[i] = tx;
 
                // LordHavoc: force all names to lowercase and make sure they are terminated while copying
@@ -394,53 +402,31 @@ void Mod_LoadTextures (lump_t *l)
                // find the number of frames in the animation
                memset (anims, 0, sizeof(anims));
                memset (altanims, 0, sizeof(altanims));
+               max = altmax = 0;
 
-               max = tx->name[1];
-               altmax = 0;
-               if (max >= '0' && max <= '9')
-               {
-                       max -= '0';
-                       altmax = 0;
-                       anims[max] = tx;
-                       max++;
-               }
-               else if (max >= 'a' && max <= 'j')
-               {
-                       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;j < m->nummiptex;j++)
                {
                        tx2 = loadmodel->textures[j];
-                       if (!tx2 || tx2->name[0] != '+')
-                               continue;
-                       if (strcmp (tx2->name+2, tx->name+2))
+                       if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2))
                                continue;
 
                        num = tx2->name[1];
                        if (num >= '0' && num <= '9')
-                       {
-                               num -= '0';
-                               anims[num] = tx2;
-                               if (num+1 > max)
-                                       max = num + 1;
-                       }
+                               anims[num - '0'] = tx2;
                        else if (num >= 'a' && num <= 'j')
-                       {
-                               num = num - 'a';
-                               altanims[num] = tx2;
-                               if (num+1 > altmax)
-                                       altmax = num+1;
-                       }
+                               altanims[num - 'a'] = tx2;
                        else
                                Host_Error ("Bad animating texture %s", tx->name);
                }
 
+               for (j = 0;j < 10;j++)
+               {
+                       if (anims[j] != NULL)
+                               max = j + 1;
+                       if (altanims[j] != NULL)
+                               altmax = j + 1;
+               }
+
                // link them all together
                for (j = 0;j < max;j++)
                {
@@ -448,21 +434,20 @@ void Mod_LoadTextures (lump_t *l)
                        if (!tx2)
                                Host_Error ("Missing frame %i of %s", j, tx->name);
                        tx2->anim_total = max;
-                       if (altmax)
-                               tx2->alternate_anims = altanims[0];
+                       tx2->alternate_anims = altanims[0]; // NULL if there is no alternate
                        for (k = 0;k < 10;k++)
-                               tx2->anim_frames[k] = anims[j];
+                               tx2->anim_frames[k] = anims[k];
                }
+
                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;
-                       if (max)
-                               tx2->alternate_anims = anims[0];
+                       tx2->alternate_anims = anims[0]; // NULL if there is no alternate
                        for (k = 0;k < 10;k++)
-                               tx2->anim_frames[k] = altanims[j];
+                               tx2->anim_frames[k] = altanims[k];
                }
        }
 }
@@ -472,7 +457,7 @@ void Mod_LoadTextures (lump_t *l)
 Mod_LoadLighting
 =================
 */
-void Mod_LoadLighting (lump_t *l)
+static void Mod_LoadLighting (lump_t *l)
 {
        int i;
        byte *in, *out, *data;
@@ -531,7 +516,7 @@ void Mod_LoadLighting (lump_t *l)
 Mod_LoadVisibility
 =================
 */
-void Mod_LoadVisibility (lump_t *l)
+static void Mod_LoadVisibility (lump_t *l)
 {
        if (!l->filelen)
        {
@@ -547,7 +532,7 @@ void Mod_LoadVisibility (lump_t *l)
 Mod_LoadEntities
 =================
 */
-void Mod_LoadEntities (lump_t *l)
+static void Mod_LoadEntities (lump_t *l)
 {
        if (!l->filelen)
        {
@@ -567,7 +552,7 @@ void Mod_LoadEntities (lump_t *l)
 Mod_LoadVertexes
 =================
 */
-void Mod_LoadVertexes (lump_t *l)
+static void Mod_LoadVertexes (lump_t *l)
 {
        dvertex_t       *in;
        mvertex_t       *out;
@@ -595,7 +580,7 @@ void Mod_LoadVertexes (lump_t *l)
 Mod_LoadSubmodels
 =================
 */
-void Mod_LoadSubmodels (lump_t *l)
+static void Mod_LoadSubmodels (lump_t *l)
 {
        dmodel_t        *in;
        dmodel_t        *out;
@@ -632,7 +617,7 @@ void Mod_LoadSubmodels (lump_t *l)
 Mod_LoadEdges
 =================
 */
-void Mod_LoadEdges (lump_t *l)
+static void Mod_LoadEdges (lump_t *l)
 {
        dedge_t *in;
        medge_t *out;
@@ -659,7 +644,7 @@ void Mod_LoadEdges (lump_t *l)
 Mod_LoadTexinfo
 =================
 */
-void Mod_LoadTexinfo (lump_t *l)
+static void Mod_LoadTexinfo (lump_t *l)
 {
        texinfo_t *in;
        mtexinfo_t *out;
@@ -683,7 +668,7 @@ void Mod_LoadTexinfo (lump_t *l)
 
                miptex = LittleLong (in->miptex);
                out->flags = LittleLong (in->flags);
-       
+
                if (!loadmodel->textures)
                {
                        out->texture = &r_notexture_mip;        // checkerboard texture
@@ -710,7 +695,7 @@ CalcSurfaceExtents
 Fills in s->texturemins[] and s->extents[]
 ================
 */
-void CalcSurfaceExtents (msurface_t *s)
+static void CalcSurfaceExtents (msurface_t *s)
 {
        float   mins[2], maxs[2], val;
        int             i,j, e;
@@ -722,7 +707,7 @@ void CalcSurfaceExtents (msurface_t *s)
        maxs[0] = maxs[1] = -99999;
 
        tex = s->texinfo;
-       
+
        for (i=0 ; i<s->numedges ; i++)
        {
                e = loadmodel->surfedges[s->firstedge+i];
@@ -764,7 +749,7 @@ void GL_SubdivideSurface (msurface_t *fa);
 Mod_LoadFaces
 =================
 */
-void Mod_LoadFaces (lump_t *l)
+static void Mod_LoadFaces (lump_t *l)
 {
        dface_t         *in;
        msurface_t      *out;
@@ -783,13 +768,13 @@ void Mod_LoadFaces (lump_t *l)
        for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
        {
                out->firstedge = LittleLong(in->firstedge);
-               out->numedges = LittleShort(in->numedges);              
+               out->numedges = LittleShort(in->numedges);
                out->flags = 0;
 
                planenum = LittleShort(in->planenum);
                side = LittleShort(in->side);
                if (side)
-                       out->flags |= SURF_PLANEBACK;                   
+                       out->flags |= SURF_PLANEBACK;
 
                out->plane = loadmodel->planes + planenum;
 
@@ -807,10 +792,10 @@ void Mod_LoadFaces (lump_t *l)
                else if (hlbsp) // LordHavoc: HalfLife map (bsp version 30)
                        out->samples = loadmodel->lightdata + i;
                else // LordHavoc: white lighting (bsp version 29)
-                       out->samples = loadmodel->lightdata + (i * 3); 
-               
+                       out->samples = loadmodel->lightdata + (i * 3);
+
        // set the drawing flags flag
-               
+
 //             if (!strncmp(out->texinfo->texture->name,"sky",3))      // sky
                // LordHavoc: faster check
                if ((out->texinfo->texture->name[0] == 's' || out->texinfo->texture->name[0] == 'S')
@@ -822,7 +807,7 @@ void Mod_LoadFaces (lump_t *l)
                        GL_SubdivideSurface (out);      // cut up polygon for warps
                        continue;
                }
-               
+
 //             if (!strncmp(out->texinfo->texture->name,"*",1))                // turbulent
                if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
                {
@@ -831,7 +816,7 @@ void Mod_LoadFaces (lump_t *l)
                        if (!strncmp(out->texinfo->texture->name,"*lava",5)
                         || !strncmp(out->texinfo->texture->name,"*teleport",9)
                         || !strncmp(out->texinfo->texture->name,"*rift",5)) // Scourge of Armagon texture
-                               out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+                               out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
                        for (i=0 ; i<2 ; i++)
                        {
                                out->extents[i] = 16384;
@@ -840,8 +825,9 @@ void Mod_LoadFaces (lump_t *l)
                        GL_SubdivideSurface (out);      // cut up polygon for warps
                        continue;
                }
-               
-               out->flags |= SURF_CLIPSOLID;
+
+               if (!out->texinfo->texture->transparent)
+                       out->flags |= SURF_CLIPSOLID;
        }
 }
 
@@ -851,7 +837,7 @@ void Mod_LoadFaces (lump_t *l)
 Mod_SetParent
 =================
 */
-void Mod_SetParent (mnode_t *node, mnode_t *parent)
+static void Mod_SetParent (mnode_t *node, mnode_t *parent)
 {
        node->parent = parent;
        if (node->contents < 0)
@@ -865,7 +851,7 @@ void Mod_SetParent (mnode_t *node, mnode_t *parent)
 Mod_LoadNodes
 =================
 */
-void Mod_LoadNodes (lump_t *l)
+static void Mod_LoadNodes (lump_t *l)
 {
        int                     i, j, count, p;
        dnode_t         *in;
@@ -912,7 +898,7 @@ void Mod_LoadNodes (lump_t *l)
 Mod_LoadLeafs
 =================
 */
-void Mod_LoadLeafs (lump_t *l)
+static void Mod_LoadLeafs (lump_t *l)
 {
        dleaf_t         *in;
        mleaf_t         *out;
@@ -941,7 +927,7 @@ void Mod_LoadLeafs (lump_t *l)
                out->firstmarksurface = loadmodel->marksurfaces +
                        LittleShort(in->firstmarksurface);
                out->nummarksurfaces = LittleShort(in->nummarksurfaces);
-               
+
                p = LittleLong(in->visofs);
                if (p == -1)
                        out->compressed_vis = NULL;
@@ -968,7 +954,7 @@ void Mod_LoadLeafs (lump_t *l)
 Mod_LoadClipnodes
 =================
 */
-void Mod_LoadClipnodes (lump_t *l)
+static void Mod_LoadClipnodes (lump_t *l)
 {
        dclipnode_t *in, *out;
        int                     i, count;
@@ -1065,7 +1051,7 @@ Mod_MakeHull0
 Duplicate the drawing hull structure as a clipping hull
 =================
 */
-void Mod_MakeHull0 (void)
+static void Mod_MakeHull0 (void)
 {
        mnode_t         *in;
        dclipnode_t *out;
@@ -1073,7 +1059,7 @@ void Mod_MakeHull0 (void)
        hull_t          *hull;
        
        hull = &loadmodel->hulls[0];    
-       
+
        in = loadmodel->nodes;
        count = loadmodel->numnodes;
        out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname));
@@ -1096,12 +1082,12 @@ void Mod_MakeHull0 (void)
 Mod_LoadMarksurfaces
 =================
 */
-void Mod_LoadMarksurfaces (lump_t *l)
-{      
+static void Mod_LoadMarksurfaces (lump_t *l)
+{
        int             i, j, count;
        short           *in;
        msurface_t **out;
-       
+
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
@@ -1125,8 +1111,8 @@ void Mod_LoadMarksurfaces (lump_t *l)
 Mod_LoadSurfedges
 =================
 */
-void Mod_LoadSurfedges (lump_t *l)
-{      
+static void Mod_LoadSurfedges (lump_t *l)
+{
        int             i, count;
        int             *in, *out;
        
@@ -1149,13 +1135,13 @@ void Mod_LoadSurfedges (lump_t *l)
 Mod_LoadPlanes
 =================
 */
-void Mod_LoadPlanes (lump_t *l)
+static void Mod_LoadPlanes (lump_t *l)
 {
        int                     i, j;
        mplane_t        *out;
        dplane_t        *in;
        int                     count;
-       
+
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
                Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
@@ -1191,7 +1177,7 @@ winding_t;
 NewWinding
 ==================
 */
-winding_t *NewWinding (int points)
+static winding_t *NewWinding (int points)
 {
        winding_t *w;
        int size;
@@ -1206,7 +1192,7 @@ winding_t *NewWinding (int points)
        return w;
 }
 
-void FreeWinding (winding_t *w)
+static void FreeWinding (winding_t *w)
 {
        qfree (w);
 }
@@ -1216,7 +1202,7 @@ void FreeWinding (winding_t *w)
 BaseWindingForPlane
 =================
 */
-winding_t *BaseWindingForPlane (mplane_t *p)
+static winding_t *BaseWindingForPlane (mplane_t *p)
 {
        vec3_t  org, vright, vup;
        winding_t       *w;
@@ -1258,7 +1244,7 @@ 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)
+static 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];
@@ -1359,7 +1345,7 @@ 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)
+static 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];
@@ -1473,7 +1459,7 @@ static portal_t *portalchain;
 AllocPortal
 ===========
 */
-portal_t *AllocPortal (void)
+static portal_t *AllocPortal (void)
 {
        portal_t *p;
        p = qmalloc(sizeof(portal_t));
@@ -1483,7 +1469,7 @@ portal_t *AllocPortal (void)
        return p;
 }
 
-void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
+static void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
 {
        // calculate children first
        if (node->children[0]->contents >= 0)
@@ -1500,7 +1486,7 @@ void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
        node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]);
 }
 
-void Mod_FinalizePortals(void)
+static void Mod_FinalizePortals(void)
 {
        int i, j, numportals, numpoints;
        portal_t *p, *pnext;
@@ -1643,7 +1629,7 @@ void Mod_FinalizePortals(void)
 AddPortalToNodes
 =============
 */
-void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
+static void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
 {
        if (!front)
                Host_Error ("AddPortalToNodes: NULL front node");
@@ -1667,7 +1653,7 @@ void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
 RemovePortalFromNode
 =============
 */
-void RemovePortalFromNodes(portal_t *portal)
+static void RemovePortalFromNodes(portal_t *portal)
 {
        int i;
        mnode_t *node;
@@ -1711,7 +1697,7 @@ void RemovePortalFromNodes(portal_t *portal)
        }
 }
 
-void Mod_RecursiveNodePortals (mnode_t *node)
+static void Mod_RecursiveNodePortals (mnode_t *node)
 {
        int side;
        mnode_t *front, *back, *other_node;
@@ -1872,7 +1858,7 @@ void Mod_MakeOutsidePortals(mnode_t *node)
 }
 */
 
-void Mod_MakePortals(void)
+static void Mod_MakePortals(void)
 {
 //     Con_Printf("building portals for %s\n", loadmodel->name);
 
@@ -1941,6 +1927,15 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
 //
        for (i = 0;i < mod->numsubmodels;i++)
        {
+               int k, l;
+               float dist, modelyawradius, modelradius, *vec;
+               msurface_t *surf;
+
+               mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+               mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+               modelyawradius = 0;
+               modelradius = 0;
+
                bm = &mod->submodels[i];
 
                mod->hulls[0].firstclipnode = bm->headnode[0];
@@ -1953,13 +1948,51 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->firstmodelsurface = bm->firstface;
                mod->nummodelsurfaces = bm->numfaces;
 
-               VectorCopy (bm->maxs, mod->maxs);
-               VectorCopy (bm->mins, mod->mins);
+               // LordHavoc: calculate bmodel bounding box rather than trusting what it says
+               for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
+               {
+                       for (k = 0;k < surf->numedges;k++)
+                       {
+                               l = mod->surfedges[k + surf->firstedge];
+                               if (l > 0)
+                                       vec = mod->vertexes[mod->edges[l].v[0]].position;
+                               else
+                                       vec = mod->vertexes[mod->edges[-l].v[1]].position;
+                               if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
+                               if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
+                               if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
+                               if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
+                               if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
+                               if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
+                               dist = vec[0]*vec[0]+vec[1]*vec[1];
+                               if (modelyawradius < dist)
+                                       modelyawradius = dist;
+                               dist += vec[2]*vec[2];
+                               if (modelradius < dist)
+                                       modelradius = dist;
+                       }
+               }
+               modelyawradius = sqrt(modelyawradius);
+               modelradius = sqrt(modelradius);
+               mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+               mod->yawmins[2] = mod->normalmins[2];
+               mod->yawmaxs[2] = mod->normalmaxs[2];
+               mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
+               mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
+//             mod->modelradius = modelradius;
+
+//             VectorCopy (bm->maxs, mod->maxs);
+//             VectorCopy (bm->mins, mod->mins);
 
-               mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+//             mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
 
                mod->numleafs = bm->visleafs;
 
+               mod->SERAddEntity = Mod_Brush_SERAddEntity;
+               mod->DrawEarly = R_DrawBrushModel;
+               mod->DrawLate = NULL;
+               mod->DrawShadow = NULL;
+
                if (isworldmodel && i < (mod->numsubmodels - 1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels)
                {       // duplicate the basic information
                        char    name[10];
index bd233df27923d2812f84728f9a41762a6e0d5523..15f73d9c1d215e29de869d0f1087b6bcb809ccec 100644 (file)
@@ -102,7 +102,6 @@ typedef struct glpolysizeof_s
 {
        struct  glpoly_s        *next;
        int             numverts;
-       int             flags;                  // for SURF_UNDERWATER
 } glpolysizeof_t;
 
 typedef struct msurface_s
index 41b23104d9108f4bb6cde7faa896179916606c26..4160766475f58f7f3345c743050c83456ca81a52 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -69,8 +69,10 @@ typedef struct model_s
        int                     flags2; // engine calculated flags, ones that can not be set in the file
 
 // volume occupied by the model graphics
-       vec3_t          mins, maxs;
-       float           radius;
+       vec3_t          normalmins, normalmaxs; // bounding box at angles '0 0 0'
+       vec3_t          yawmins, yawmaxs; // bounding box if yaw angle is not 0, but pitch and roll are
+       vec3_t          rotatedmins, rotatedmaxs; // bounding box if pitch or roll are used
+//     float           modelradius; // usable at any angles
 
 // solid volume for clipping
        qboolean        clipbox;
@@ -130,13 +132,20 @@ typedef struct model_s
        // LordHavoc: useful for sprites and models
        int                     numtris;
        int                     numskins;
+
        int                     skinanimrange[MAX_SKINS*2]; // array of start and length pairs
        rtexture_t      *skinanim[MAX_SKINS*5]; // texture numbers for each frame (indexed by animrange), note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow)
+
        int                     ofs_scenes; // offset from Mod_ExtraData(model) memory to array of animscene_t structs
        // these are used simply to simplify model/sprite/whatever processing and are specific to each type
        int                     ofs_frames; // offset from Mod_ExtraData(model) memory to array of model specific frame structs
        int                     framesize; // size of model specific frame structs
 
+       void (*SERAddEntity)(void);
+       void (*DrawEarly)(void);
+       void (*DrawLate)(void);
+       void (*DrawShadow)(void);
+
 // additional model data
        cache_user_t    cache;          // only access through Mod_Extradata
        int                     cachesize;              // size of cached data (zero if not cached)
index d2509037263453cea54c4f494f39a154c1e60554..53dbb7c97162b8e2447eddeae37425188fb6555d 100644 (file)
@@ -56,16 +56,19 @@ void Mod_Sprite_StripExtension(char *in, char *out)
 Mod_LoadSpriteFrame
 =================
 */
-void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette)
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette, float *modelradius)
 {
        dspriteframe_t          *pinframe;
        mspriteframe_t          *pspriteframe;
+       float                           dist;
        int                                     i, width, height, size, origin[2];
        char                            name[256], tempname[256];
        byte                            *pixbuf, *pixel, *inpixel;
 
        pinframe = (dspriteframe_t *)pin;
 
+       origin[0] = LittleLong (pinframe->origin[0]);
+       origin[1] = LittleLong (pinframe->origin[1]);
        width = LittleLong (pinframe->width);
        height = LittleLong (pinframe->height);
        size = width * height * bytesperpixel;
@@ -74,15 +77,17 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int
 
        memset (pspriteframe, 0, sizeof (mspriteframe_t));
 
-//     pspriteframe->width = width;
-//     pspriteframe->height = height;
-       origin[0] = LittleLong (pinframe->origin[0]);
-       origin[1] = LittleLong (pinframe->origin[1]);
-
+       pspriteframe->left = origin[0];
+       pspriteframe->right = origin[0] + width;
        pspriteframe->up = origin[1];
        pspriteframe->down = origin[1] - height;
-       pspriteframe->left = origin[0];
-       pspriteframe->right = width + origin[0];
+
+       dist = pspriteframe->left*pspriteframe->left+pspriteframe->up*pspriteframe->up;
+       if (*modelradius < dist)
+               *modelradius = dist;
+       dist = pspriteframe->right*pspriteframe->right+pspriteframe->down*pspriteframe->down;
+       if (*modelradius < dist)
+               *modelradius = dist;
 
        Mod_Sprite_StripExtension(loadmodel->name, tempname);
        sprintf (name, "%s_%i", tempname, framenum);
@@ -151,7 +156,7 @@ void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int
 // this actually handles both quake sprite and darkplaces sprite32
 void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
 {
-       int                                     i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight;
+       int                                     i, j, version, numframes, realframes, size, bytesperpixel, start, end, total;
        dsprite_t                       *pin;
        msprite_t                       *psprite;
        dspriteframetype_t      *pframetype;
@@ -159,6 +164,9 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
        animscene_t                     *animscenes;
        mspriteframe_t          *frames;
        dspriteframe_t          **framedata;
+       float                           modelradius;
+
+       modelradius = 0;
 
        start = Hunk_LowMark ();
 
@@ -191,16 +199,16 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
 //     mod->cache.data = psprite;
 
        psprite->type = LittleLong (pin->type);
-       maxwidth = LittleLong (pin->width);
-       maxheight = LittleLong (pin->height);
+//     maxwidth = LittleLong (pin->width);
+//     maxheight = LittleLong (pin->height);
 //     psprite->beamlength = LittleFloat (pin->beamlength);
        mod->synctype = LittleLong (pin->synctype);
 //     psprite->numframes = numframes;
 
-       mod->mins[0] = mod->mins[1] = -maxwidth/2;
-       mod->maxs[0] = mod->maxs[1] = maxwidth/2;
-       mod->mins[2] = -maxheight/2;
-       mod->maxs[2] = maxheight/2;
+//     mod->mins[0] = mod->mins[1] = -maxwidth/2;
+//     mod->maxs[0] = mod->maxs[1] = maxwidth/2;
+//     mod->mins[2] = -maxheight/2;
+//     mod->maxs[2] = maxheight/2;
 
 //
 // load the frames
@@ -262,7 +270,7 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
        {
                for (j = 0;j < animscenes[i].framecount;j++)
                {
-                       Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table);
+                       Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table, &modelradius);
                        realframes++;
                }
        }
@@ -273,6 +281,14 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
 
        mod->type = mod_sprite;
 
+       modelradius = sqrt(modelradius);
+       for (i = 0;i < 3;i++)
+       {
+               mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
+               mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
+       }
+//     mod->modelradius = modelradius;
+
 // move the complete, relocatable sprite model to the cache
        end = Hunk_LowMark ();
        mod->cachesize = total = end - start;
@@ -287,7 +303,7 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
 
 void Mod_LoadHLSprite (model_t *mod, void *buffer)
 {
-       int                                     i, j, numframes, realframes, size, start, end, total, maxwidth, maxheight, rendermode;
+       int                                     i, j, numframes, realframes, size, start, end, total, rendermode;
        byte                            palette[256][4], *in;
        dspritehl_t                     *pin;
        msprite_t                       *psprite;
@@ -296,6 +312,9 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer)
        animscene_t                     *animscenes;
        mspriteframe_t          *frames;
        dspriteframe_t          **framedata;
+       float                           modelradius;
+
+       modelradius = 0;
 
        start = Hunk_LowMark ();
 
@@ -311,15 +330,15 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer)
        psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
 
        psprite->type = LittleLong (pin->type);
-       maxwidth = LittleLong (pin->width);
-       maxheight = LittleLong (pin->height);
+//     maxwidth = LittleLong (pin->width);
+//     maxheight = LittleLong (pin->height);
        mod->synctype = LittleLong (pin->synctype);
        rendermode = pin->rendermode;
 
-       mod->mins[0] = mod->mins[1] = -maxwidth/2;
-       mod->maxs[0] = mod->maxs[1] = maxwidth/2;
-       mod->mins[2] = -maxheight/2;
-       mod->maxs[2] = maxheight/2;
+//     mod->mins[0] = mod->mins[1] = -maxwidth/2;
+//     mod->maxs[0] = mod->maxs[1] = maxwidth/2;
+//     mod->mins[2] = -maxheight/2;
+//     mod->maxs[2] = maxheight/2;
 
 //
 // load the frames
@@ -434,7 +453,7 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer)
        {
                for (j = 0;j < animscenes[i].framecount;j++)
                {
-                       Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0]);
+                       Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0], &modelradius);
                        realframes++;
                }
        }
@@ -445,6 +464,13 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer)
 
        mod->type = mod_sprite;
 
+       modelradius = sqrt(modelradius);
+       for (i = 0;i < 3;i++)
+       {
+               mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
+               mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
+       }
+
 // move the complete, relocatable sprite model to the cache
        end = Hunk_LowMark ();
        mod->cachesize = total = end - start;
@@ -457,6 +483,11 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer)
        Hunk_FreeToLowMark (start);
 }
 
+void Mod_Sprite_SERAddEntity(void)
+{
+       R_ClipSprite();
+}
+
 
 /*
 =================
@@ -480,4 +511,8 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
                Host_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be 1 (quake) or 32 (sprite32) or 2 (halflife)", mod->name, version);
                break;
        }
+       mod->SERAddEntity = Mod_Sprite_SERAddEntity;
+       mod->DrawEarly = R_DrawSpriteModel;
+       mod->DrawLate = NULL;
+       mod->DrawShadow = NULL;
 }
index 742f6d36d04ff88355d49d59c5fceaa3bd74aaac..3575298868ee88bd1d2bd16673c597f0b7b57661 100644 (file)
--- a/portals.c
+++ b/portals.c
@@ -14,7 +14,7 @@ static int portal_markid = 0;
 //float viewportalpoints[16*3];
 static float boxpoints[4*3];
 
-int R_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p)
+int Portal_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p)
 {
        int i, outpoints, prevside, side;
        float *prevpoint, prevdist, dist, dot;
@@ -67,7 +67,7 @@ begin:
 }
 
 /*
-void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
+void Portal_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
 {
        vec3_t v1, v2;
        VectorSubtract(point1, point2, v1);
@@ -79,7 +79,7 @@ void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t
 }
 */
 
-int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints)
+int Portal_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints)
 {
        int numpoints, i;
        if (targnumpoints < 3)
@@ -90,7 +90,7 @@ int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, floa
        memcpy(&portaltemppoints[0][0][0], targpoints, numpoints * 3 * sizeof(float));
        for (i = 0;i < clipnumplanes;i++)
        {
-               numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i);
+               numpoints = Portal_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i);
                if (numpoints < 3)
                        return numpoints;
                memcpy(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float));
@@ -117,7 +117,7 @@ int Portal_RecursiveFlowSearch (mleaf_t *leaf, vec3_t eye, int firstclipplane, i
                // only flow through portals facing away from the viewer
                if (PlaneDiff(eye, (&p->plane)) < 0)
                {
-                       newpoints = R_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256);
+                       newpoints = Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256);
                        if (newpoints < 3)
                                continue;
                        else if (firstclipplane + numclipplanes + newpoints > MAXRECURSIVEPORTALPLANES)
@@ -134,7 +134,7 @@ int Portal_RecursiveFlowSearch (mleaf_t *leaf, vec3_t eye, int firstclipplane, i
                                newplanes = &portalplanes[firstclipplane + numclipplanes];
                                for (prev = newpoints - 1, i = 0;i < newpoints;prev = i, i++)
                                {
-//                                     R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
+//                                     Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
                                        VectorSubtract(eye, portaltemppoints2[i], v1);
                                        VectorSubtract(portaltemppoints2[prev], portaltemppoints2[i], v2);
                                        CrossProduct(v1, v2, newplanes[i].normal);
@@ -217,7 +217,7 @@ int Portal_CheckPolygon(model_t *model, vec3_t eye, float *polypoints, int numpo
        // calculate the planes, and make sure the polygon can see it's own center
        for (prev = numpoints - 1, i = 0;i < numpoints;prev = i, i++)
        {
-//             R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
+//             Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
                VectorSubtract(eye, (&polypoints[i * 3]), v1);
                VectorSubtract((&polypoints[prev * 3]), (&polypoints[i * 3]), v2);
                CrossProduct(v1, v2, portalplanes[i].normal);
index 49cc08d2fb54d776b52b059b2882b5b9c808e4da..d5ba332975b11b4b8803da9959995014b2b8001d 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -262,7 +262,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
                
                VectorCopy (min, bounds[0]);
                VectorCopy (max, bounds[1]);
-               
+
                rmin[0] = rmin[1] = rmin[2] = 9999;
                rmax[0] = rmax[1] = rmax[2] = -9999;
                
@@ -350,16 +350,16 @@ void PF_setmodel (void)
        for (i=0, check = sv.model_precache ; *check ; i++, check++)
                if (!strcmp(*check, m))
                        break;
-                       
+
        if (!*check)
                PR_RunError ("no precache: %s\n", m);
-               
+
 
        e->v.model = m - pr_strings;
        e->v.modelindex = i; //SV_ModelIndex (m);
 
        mod = sv.models[ (int)e->v.modelindex];  // Mod_ForName (m, true);
-       
+
        if (mod)
        /*
        { // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here
@@ -374,7 +374,7 @@ void PF_setmodel (void)
                        SetMinMaxSize (e, mod->mins, mod->maxs, true);
        }
        */
-               SetMinMaxSize (e, mod->mins, mod->maxs, true);
+               SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
        else
                SetMinMaxSize (e, vec3_origin, vec3_origin, true);
 }
@@ -764,11 +764,12 @@ void PF_traceline (void)
        pr_global_struct->trace_inopen = trace.inopen;
        VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
        VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
-       pr_global_struct->trace_plane_dist =  trace.plane.dist; 
+       pr_global_struct->trace_plane_dist =  trace.plane.dist;
        if (trace.ent)
                pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
        else
                pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
+       // FIXME: add trace_endcontents
 }
 
 
index c7e722abed5b5bfe761afcfe202c1f3e082c8a6a..5b348ff59e464fc91427082cccd82d824aaff481 100644 (file)
@@ -454,7 +454,7 @@ char *PR_UglyValueString (etype_t type, eval_t *val)
        case ev_string:
                sprintf (line, "%s", pr_strings + val->string);
                break;
-       case ev_entity: 
+       case ev_entity:
                sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
                break;
        case ev_function:
@@ -501,7 +501,7 @@ char *PR_GlobalString (int ofs)
        val = (void *)&pr_globals[ofs];
        def = ED_GlobalAtOfs(ofs);
        if (!def)
-               sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph
+               sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
        else
        {
                s = PR_ValueString (def->type, val);
@@ -524,7 +524,7 @@ char *PR_GlobalStringNoContents (int ofs)
 
        def = ED_GlobalAtOfs(ofs);
        if (!def)
-               sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph
+               sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
        else
                sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
 
@@ -849,7 +849,7 @@ char *ED_NewString (char *string)
                else
                        *new_p++ = string[i];
        }
-       
+
        return new;
 }
 
@@ -870,9 +870,9 @@ qboolean    ED_ParseEpair (void *base, ddef_t *key, char *s)
        char    *v, *w;
        void    *d;
        dfunction_t     *func;
-       
+
        d = (void *)((int *)base + key->ofs);
-       
+
        switch (key->type & ~DEF_SAVEGLOBAL)
        {
        case ev_string:
@@ -986,7 +986,7 @@ if (!strcmp(com_token, "light"))
                        n--;
                }
 
-       // parse value  
+       // parse value
                data = COM_Parse (data);
                if (!data)
                        Host_Error ("ED_ParseEntity: EOF without closing brace");
@@ -1113,12 +1113,59 @@ void ED_LoadFromFile (char *data)
 
                pr_global_struct->self = EDICT_TO_PROG(ent);
                PR_ExecuteProgram (func - pr_functions, "");
-       }       
+       }
 
        Con_DPrintf ("%i entities inhibited\n", inhibit);
 }
 
 
+typedef struct dpfield_s
+{
+       int type;
+       char *string;
+}
+dpfield_t;
+
+#define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
+
+dpfield_t dpfields[] =
+{
+       {ev_float, "gravity"},
+       {ev_float, "button3"},
+       {ev_float, "button4"},
+       {ev_float, "button5"},
+       {ev_float, "button6"},
+       {ev_float, "button7"},
+       {ev_float, "button8"},
+       {ev_float, "glow_size"},
+       {ev_float, "glow_trail"},
+       {ev_float, "glow_color"},
+       {ev_float, "items2"},
+       {ev_float, "scale"},
+       {ev_float, "alpha"},
+       {ev_float, "renderamt"},
+       {ev_float, "rendermode"},
+       {ev_float, "fullbright"},
+       {ev_float, "ammo_shells1"},
+       {ev_float, "ammo_nails1"},
+       {ev_float, "ammo_lava_nails"},
+       {ev_float, "ammo_rockets1"},
+       {ev_float, "ammo_multi_rockets"},
+       {ev_float, "ammo_cells1"},
+       {ev_float, "ammo_plasma"},
+       {ev_float, "idealpitch"},
+       {ev_float, "pitch_speed"},
+       {ev_entity, "viewmodelforclient"},
+       {ev_entity, "nodrawtoclient"},
+       {ev_entity, "exteriormodeltoclient"},
+       {ev_entity, "drawonlytoclient"},
+       {ev_vector, "colormod"},
+       {ev_float, "ping"},
+       {ev_vector, "movement"},
+       {ev_float, "pmodel"},
+       {ev_vector, "punchvector"}
+};
+
 /*
 ===============
 PR_LoadProgs
@@ -1126,8 +1173,9 @@ PR_LoadProgs
 */
 void PR_LoadProgs (void)
 {
-       int             i;
+       int i;
        dstatement_t *st;
+       ddef_t *infielddefs;
 
 // flush the non-C variable lookup cache
        for (i=0 ; i<GEFV_CACHESIZE ; i++)
@@ -1142,7 +1190,7 @@ void PR_LoadProgs (void)
 
 // byte swap the header
        for (i=0 ; i<sizeof(*progs)/4 ; i++)
-               ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );           
+               ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
 
        if (progs->version != PROG_VERSION)
                Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
@@ -1152,15 +1200,18 @@ void PR_LoadProgs (void)
        pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
        pr_strings = (char *)progs + progs->ofs_strings;
        pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
-       pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
+
+       // we need to expand the fielddefs list to include all the engine fields,
+       // so allocate a new place for it
+       infielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
+       pr_fielddefs = Hunk_AllocName((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t), "progs fields\n");
+
        pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
 
+       // moved edict_size calculation down below field adding code
+
        pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
        pr_globals = (float *)pr_global_struct;
-       
-       pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
-
-       pr_edictareasize = pr_edict_size * MAX_EDICTS;
 
 // byte swap the lumps
        for (i=0 ; i<progs->numstatements ; i++)
@@ -1179,7 +1230,7 @@ void PR_LoadProgs (void)
                pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
                pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
                pr_functions[i].locals = LittleLong (pr_functions[i].locals);
-       }       
+       }
 
        for (i=0 ; i<progs->numglobaldefs ; i++)
        {
@@ -1188,18 +1239,37 @@ void PR_LoadProgs (void)
                pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
        }
 
-       for (i=0 ; i<progs->numfielddefs ; i++)
+       // copy the progs fields to the new fields list
+       for (i = 0;i < progs->numfielddefs;i++)
        {
-               pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
+               pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
                if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
                        Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
-               pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
-               pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
+               pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
+               pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
+       }
+
+       // append the darkplaces fields
+       for (i = 0;i < DPFIELDS;i++)
+       {
+               pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
+               pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
+               pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
+               if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
+                       progs->entityfields += 3;
+               else
+                       progs->entityfields++;
+               progs->numfielddefs++;
        }
 
        for (i=0 ; i<progs->numglobals ; i++)
                ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
 
+       // moved edict_size calculation down here, below field adding code
+       pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
+
+       pr_edictareasize = pr_edict_size * MAX_EDICTS;
+
        // LordHavoc: bounds check anything static
        for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
        {
@@ -1357,7 +1427,7 @@ void PR_Init (void)
        // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
        Cvar_RegisterVariable (&decors);
        // LordHavoc: Nehahra uses these to pass data around cutscene demos
-       if (nehahra)
+       if (gamemode == GAME_NEHAHRA)
        {
                Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
                Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
index 24025549fa6dec3f1d761cedbf6a095cd4a53d3d..f9fbe204e860afb2fcee50b6f5d5e61bb1d27c0d 100644 (file)
@@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define QUAKE_GAME // as opposed to utilities
 
-#define VERSION 1.50
-
 extern int buildnumber;
 
 #ifndef FALSE
index 1f59dc320185e3cd06832d8f70ba13f700e626e8..eb5f6fa6f5da91f5af21e737a933791f62f9eb84 100644 (file)
--- a/r_clip.c
+++ b/r_clip.c
@@ -100,8 +100,8 @@ void R_Clip_StartFrame(void)
 {
        int i;
        int newwidth, newheight, newmaxedges, newmaxsurfs;
-       newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2);
-       newheight = bound(60, (int) r_clipheight.value, vid.height * 2);
+       newwidth = bound(80, (int) r_clipwidth.value, vid.realwidth * 2);
+       newheight = bound(60, (int) r_clipheight.value, vid.realheight * 2);
        newmaxedges = bound(128, (int) r_clipedges.value, 262144);
        newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536);
        if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs)
@@ -910,10 +910,10 @@ void R_Clip_DisplayBuffer(void)
        }
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
        glBegin (GL_QUADS);
-       glTexCoord2f (0                 , 0                  );glVertex2f (0        , 0         );
-       glTexCoord2f (clipwidth / 256.0f, 0                  );glVertex2f (vid.width, 0         );
-       glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height);
-       glTexCoord2f (0                 , clipheight / 256.0f);glVertex2f (0        , vid.height);
+       glTexCoord2f (0                 , 0                  );glVertex2f (0           , 0            );
+       glTexCoord2f (clipwidth / 256.0f, 0                  );glVertex2f (vid.conwidth, 0            );
+       glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.conwidth, vid.conheight);
+       glTexCoord2f (0                 , clipheight / 256.0f);glVertex2f (0           , vid.conheight);
        glEnd ();
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 //     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
index de0c1a08b56a70acd9e6ad55499741fec721ca24..5872d5697a287416338b054c717eae911e6c7410 100644 (file)
@@ -138,7 +138,6 @@ void DrawCrosshair(int num)
 {
        byte *color;
        float scale, base;
-//     Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
        if (num < 0 || num >= NUMCROSSHAIRS)
                num = 0;
        if (cl.viewentity)
@@ -158,6 +157,6 @@ void DrawCrosshair(int num)
        else
                base = 0.0f;
        scale = crosshair_brightness.value / 255.0f;
-       Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, r_refdef.vrect.x + r_refdef.vrect.width * 0.5f - 8.0f, r_refdef.vrect.y + r_refdef.vrect.height * 0.5f - 8.0f, 16.0f, 16.0f);
+       Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, vid.conwidth * 0.5f - 8.0f, vid.conheight * 0.5f - 8.0f, 16.0f, 16.0f);
 }
 
index 8f8176aac2a10c4f04127c8e1afa8b0d06ad5de1..6c45f70e5a89893918291c772312f9a70f898381 100644 (file)
@@ -26,6 +26,7 @@ typedef struct decal_s
 {
        vec3_t          org;
        vec3_t          direction;
+       vec2_t          texcoord[4];
        vec3_t          vert[4];
        byte            color[4];
        rtexture_t      *tex;
@@ -85,7 +86,7 @@ loc0:
                return;
 
        ndist = PlaneDiff(decalorg, node->plane);
-       
+
        if (ndist > 16)
        {
                node = node->children[0];
@@ -155,7 +156,7 @@ loc0:
        }
 }
 
-void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha)
+void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha)
 {
        vec3_t center, right, up;
        decal_t *decal;
@@ -194,16 +195,24 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int
        // set up the 4 corners
        scale *= 0.5f;
        VectorVectors(decal->direction, right, up);
-       decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; // texcoords 0 1
+       decal->texcoord[0][0] = s1;
+       decal->texcoord[0][1] = t1;
+       decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale;
        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->texcoord[1][0] = s1;
+       decal->texcoord[1][1] = t2;
+       decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale;
        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->texcoord[2][0] = s2;
+       decal->texcoord[2][1] = t2;
+       decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale;
        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->texcoord[3][0] = s2;
+       decal->texcoord[3][1] = t1;
+       decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale;
        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
@@ -223,8 +232,8 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int
 void GL_DrawDecals (void)
 {
        decal_t *p;
-       int i, j, k, dynamiclight, bits, texnum;
-       float scale, fr, fg, fb, dist, rad, mindist;
+       int i, j, k, dynamiclight, bits, texnum, iscale, ir, ig, ib, lit, cr, cg, cb;
+       float /*fscale, */fr, fg, fb, dist, rad, mindist;
        byte *lightmap;
        vec3_t v;
        msurface_t *surf;
@@ -241,7 +250,7 @@ void GL_DrawDecals (void)
        {
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                glEnable(GL_BLEND);
-               glShadeModel(GL_FLAT);
+//             glShadeModel(GL_FLAT);
                glDepthMask(0); // disable zbuffer updates
                glDisable(GL_ALPHA_TEST);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -268,54 +277,11 @@ void GL_DrawDecals (void)
                // get the surface lighting
                surf = p->surface;
                lightmap = p->lightmapaddress;
-               fr = fg = fb = 0.0f;
-               if (lightmap)
-               {
-                       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[j]] * (1.0f / 256.0f);
-                               fr += lightmap[0] * scale;
-                               fg += lightmap[1] * scale;
-                               fb += lightmap[2] * scale;
-                               lightmap += p->lightmapstep;
-                       }
-                       */
-               }
                // dynamic lighting
+               lit = false;
                if (dynamiclight)
                {
+                       fr = fg = fb = 0.0f;
                        if (surf->dlightframe == r_framecount)
                        {
                                for (j = 0;j < 8;j++)
@@ -337,6 +303,7 @@ void GL_DrawDecals (void)
                                                                        fr += rad * dl->color[0];
                                                                        fg += rad * dl->color[1];
                                                                        fb += rad * dl->color[2];
+                                                                       lit = true;
                                                                }
                                                        }
                                                }
@@ -344,6 +311,105 @@ void GL_DrawDecals (void)
                                }
                        }
                }
+               if (lit)
+               {
+#if SLOWMATH
+                       ir = fr * 256.0f;
+                       ig = fg * 256.0f;
+                       ib = fb * 256.0f;
+#else
+                       fr += 8388608.0f;
+                       fg += 8388608.0f;
+                       fb += 8388608.0f;
+                       ir = (*((long *)&fr) & 0x7FFFFF) << 8;
+                       ig = (*((long *)&fg) & 0x7FFFFF) << 8;
+                       ib = (*((long *)&fb) & 0x7FFFFF) << 8;
+#endif
+               }
+               else
+                       ir = ig = ib = 0;
+#if 1
+               if (lightmap)
+               {
+                       if (surf->styles[0] != 255)
+                       {
+                               iscale = d_lightstylevalue[surf->styles[0]];
+                               ir += lightmap[0] * iscale;
+                               ig += lightmap[1] * iscale;
+                               ib += lightmap[2] * iscale;
+                               if (surf->styles[1] != 255)
+                               {
+                                       lightmap += p->lightmapstep;
+                                       iscale = d_lightstylevalue[surf->styles[1]];
+                                       ir += lightmap[0] * iscale;
+                                       ig += lightmap[1] * iscale;
+                                       ib += lightmap[2] * iscale;
+                                       if (surf->styles[2] != 255)
+                                       {
+                                               lightmap += p->lightmapstep;
+                                               iscale = d_lightstylevalue[surf->styles[2]];
+                                               ir += lightmap[0] * iscale;
+                                               ig += lightmap[1] * iscale;
+                                               ib += lightmap[2] * iscale;
+                                               if (surf->styles[3] != 255)
+                                               {
+                                                       lightmap += p->lightmapstep;
+                                                       iscale = d_lightstylevalue[surf->styles[3]];
+                                                       ir += lightmap[0] * iscale;
+                                                       ig += lightmap[1] * iscale;
+                                                       ib += lightmap[2] * iscale;
+                                               }
+                                       }
+                               }
+                       }
+               }
+#else
+               fr = fg = fb = 0.0f;
+               if (lightmap)
+               {
+                       if (surf->styles[0] != 255)
+                       {
+                               fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f);
+                               fr += lightmap[0] * fscale;
+                               fg += lightmap[1] * fscale;
+                               fb += lightmap[2] * fscale;
+                               if (surf->styles[1] != 255)
+                               {
+                                       lightmap += p->lightmapstep;
+                                       fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f);
+                                       fr += lightmap[0] * fscale;
+                                       fg += lightmap[1] * fscale;
+                                       fb += lightmap[2] * fscale;
+                                       if (surf->styles[2] != 255)
+                                       {
+                                               lightmap += p->lightmapstep;
+                                               fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f);
+                                               fr += lightmap[0] * fscale;
+                                               fg += lightmap[1] * fscale;
+                                               fb += lightmap[2] * fscale;
+                                               if (surf->styles[3] != 255)
+                                               {
+                                                       lightmap += p->lightmapstep;
+                                                       fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f);
+                                                       fr += lightmap[0] * fscale;
+                                                       fg += lightmap[1] * fscale;
+                                                       fb += lightmap[2] * fscale;
+                                               }
+                                       }
+                               }
+                       }
+                       /*
+                       for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++)
+                       {
+                               fscale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f);
+                               fr += lightmap[0] * fscale;
+                               fg += lightmap[1] * fscale;
+                               fb += lightmap[2] * fscale;
+                               lightmap += p->lightmapstep;
+                       }
+                       */
+               }
+#endif
                /*
                {
                        int ir, ig, ib;
@@ -376,21 +442,40 @@ void GL_DrawDecals (void)
                                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);
+                       */
+                       if (lighthalf)
+                       {
+                               cr = (ir * p->color[0]) >> 16;
+                               cg = (ig * p->color[1]) >> 16;
+                               cb = (ib * p->color[2]) >> 16;
+                       }
+                       else
+                       {
+                               cr = (ir * p->color[0]) >> 15;
+                               cg = (ig * p->color[1]) >> 15;
+                               cb = (ib * p->color[2]) >> 15;
+                       }
+                       cr = min(cr, 255);
+                       cg = min(cg, 255);
+                       cb = min(cb, 255);
+                       glColor4ub(cr, cg, cb, p->color[3]);
+
+                       glTexCoord2f(p->texcoord[0][0], p->texcoord[0][1]);
                        glVertex3fv(p->vert[0]);
-                       glTexCoord2f(0, 0);
+                       glTexCoord2f(p->texcoord[1][0], p->texcoord[1][1]);
                        glVertex3fv(p->vert[1]);
-                       glTexCoord2f(1, 0);
+                       glTexCoord2f(p->texcoord[2][0], p->texcoord[2][1]);
                        glVertex3fv(p->vert[2]);
-                       glTexCoord2f(1, 1);
+                       glTexCoord2f(p->texcoord[3][0], p->texcoord[3][1]);
                        glVertex3fv(p->vert[3]);
                }
        }
-       
+
        if (r_render.value)
        {
                glEnd();
index 9d2924cbe338f44d59dc40ca4a8f302d38fac79b..879396583ac80286f140aba8f8b460689655d847 100644 (file)
@@ -3,4 +3,4 @@ void R_Decals_Init(void);
 
 void GL_DrawDecals(void);
 
-void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha);
+void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha);
index db67b390a9ae634dae1b98242ce3c987759a0496..8061b6062acd65b3fd929b014be899a695be6def 100644 (file)
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -20,16 +20,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
-
 #define MAX_EXPLOSIONS 64
 #define EXPLOSIONGRID 16
 #define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1))
 #define EXPLOSIONTRIS (EXPLOSIONVERTS*2)
-#define EXPLOSIONSTARTRADIUS (0.0f)
-#define EXPLOSIONSTARTVELOCITY (500.0f)
+#define EXPLOSIONSTARTRADIUS (20.0f)
+#define EXPLOSIONSTARTVELOCITY (256.0f)
 #define EXPLOSIONFADESTART (1.5f)
-#define EXPLOSIONFADERATE (6.0f)
+#define EXPLOSIONFADERATE (4.5f)
+/*
+#define MAX_EXPLOSIONGAS (MAX_EXPLOSIONS * EXPLOSIONGAS)
+#define EXPLOSIONGAS 8
+#define EXPLOSIONGASSTARTRADIUS (15.0f)
+#define EXPLOSIONGASSTARTVELOCITY (50.0f)
+#define GASDENSITY_SCALER (32768.0f / EXPLOSIONGAS)
+#define GASFADERATE (GASDENSITY_SCALER * EXPLOSIONGAS * 2)
+
+typedef struct explosiongas_s
+{
+       float pressure;
+       vec3_t origin;
+       vec3_t velocity;
+}
+explosiongas_t;
+
+explosiongas_t explosiongas[MAX_EXPLOSIONGAS];
+*/
 
 vec3_t explosionspherevert[EXPLOSIONVERTS];
 vec3_t explosionspherevertvel[EXPLOSIONVERTS];
@@ -47,7 +63,7 @@ typedef struct explosion_s
 }
 explosion_t;
 
-explosion_t explosion[128];
+explosion_t explosion[MAX_EXPLOSIONS];
 
 rtexture_t     *explosiontexture;
 rtexture_t     *explosiontexturefog;
@@ -75,19 +91,20 @@ int R_ExplosionVert(int column, int row)
 void r_explosion_start(void)
 {
        int x, y;
-       byte noise1[128][128], noise2[128][128], data[128][128][4];
-       fractalnoise(&noise1[0][0], 128, 2);
-       fractalnoise(&noise2[0][0], 128, 2);
+       byte noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4];
+       fractalnoise(&noise1[0][0], 128, 32);
+       fractalnoise(&noise2[0][0], 128, 4);
+       fractalnoise(&noise3[0][0], 128, 4);
        for (y = 0;y < 128;y++)
        {
                for (x = 0;x < 128;x++)
                {
                        int j, r, g, b, a;
-                       j = noise1[y][x] * 3 - 128;
+                       j = (noise1[y][x] * noise2[y][x]) * 3 / 256 - 128;
                        r = (j * 512) / 256;
                        g = (j * 256) / 256;
                        b = (j * 128) / 256;
-                       a = noise2[y][x];
+                       a = noise3[y][x] * 3 - 128;
                        data[y][x][0] = bound(0, r, 255);
                        data[y][x][1] = bound(0, g, 255);
                        data[y][x][2] = bound(0, b, 255);
@@ -108,6 +125,7 @@ void r_explosion_shutdown(void)
 void r_explosion_newmap(void)
 {
        memset(explosion, 0, sizeof(explosion));
+//     memset(explosiongas, 0, sizeof(explosiongas));
 }
 
 void R_Explosion_Init(void)
@@ -147,9 +165,9 @@ void R_Explosion_Init(void)
 void R_NewExplosion(vec3_t org)
 {
        int i, j;
-       float dist;
+       float dist, v[3];
        byte noise[EXPLOSIONGRID*EXPLOSIONGRID];
-       fractalnoise(noise, EXPLOSIONGRID, 2);
+       fractalnoise(noise, EXPLOSIONGRID, 4);
        for (i = 0;i < MAX_EXPLOSIONS;i++)
        {
                if (explosion[i].alpha <= 0.0f)
@@ -157,17 +175,35 @@ void R_NewExplosion(vec3_t org)
                        explosion[i].alpha = EXPLOSIONFADESTART;
                        for (j = 0;j < EXPLOSIONVERTS;j++)
                        {
-                               dist = noise[explosionnoiseindex[j]] * (1.0f / 512.0f) + 0.5;
-                               explosion[i].vert[j][0] = explosionspherevert[j][0] * dist + org[0];
-                               explosion[i].vert[j][1] = explosionspherevert[j][1] * dist + org[1];
-                               explosion[i].vert[j][2] = explosionspherevert[j][2] * dist + org[2];
-                               explosion[i].vertvel[j][0] = explosionspherevertvel[j][0] * dist;
-                               explosion[i].vertvel[j][1] = explosionspherevertvel[j][1] * dist;
-                               explosion[i].vertvel[j][2] = explosionspherevertvel[j][2] * dist;
+                               dist = noise[explosionnoiseindex[j]] * (1.0f / 256.0f) + 0.5;
+                               VectorMA(org, dist, explosionspherevert[j], v);
+                               TraceLine(org, v, explosion[i].vert[j], NULL, 0);
+                               VectorScale(explosionspherevertvel[j], dist, explosion[i].vertvel[j]);
                        }
                        break;
                }
        }
+
+       /*
+       i = 0;
+       j = EXPLOSIONGAS;
+       while (i < MAX_EXPLOSIONGAS && j > 0)
+       {
+               while (explosiongas[i].pressure > 0)
+               {
+                       i++;
+                       if (i >= MAX_EXPLOSIONGAS)
+                               return;
+               }
+               VectorRandom(v);
+               VectorMA(org, EXPLOSIONGASSTARTRADIUS, v, v);
+               TraceLine(org, v, explosiongas[i].origin, NULL, 0);
+               VectorRandom(v);
+               VectorScale(v, EXPLOSIONGASSTARTVELOCITY, explosiongas[i].velocity);
+               explosiongas[i].pressure = j * GASDENSITY_SCALER;
+               j--;
+       }
+       */
 }
 
 void R_DrawExplosion(explosion_t *e)
@@ -205,11 +241,19 @@ void R_DrawExplosion(explosion_t *e)
        }
 }
 
-void R_MoveExplosion(explosion_t *e, float frametime)
+void R_MoveExplosion(explosion_t *e, /*explosiongas_t **list, explosiongas_t **listend, */float frametime)
 {
        int i;
        vec3_t end;
+       vec_t frictionscale;
+       /*
+       vec3_t diff;
+       vec_t dist;
+       explosiongas_t **l;
+       */
        e->alpha -= frametime * EXPLOSIONFADERATE;
+       frictionscale = 1 - frametime;
+       frictionscale = bound(0, frictionscale, 1);
        for (i = 0;i < EXPLOSIONVERTS;i++)
        {
                if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2])
@@ -221,12 +265,12 @@ void R_MoveExplosion(explosion_t *e, float frametime)
                        {
                                float f, dot;
                                vec3_t impact, normal;
-                               f = TraceLine(e->vert[i], end, impact, normal);
+                               f = TraceLine(e->vert[i], end, impact, normal, 0);
                                VectorCopy(impact, e->vert[i]);
                                if (f < 1)
                                {
                                        // clip velocity against the wall
-                                       dot = -DotProduct(e->vertvel[i], normal);
+                                       dot = DotProduct(e->vertvel[i], normal) * -1.125f;
                                        e->vertvel[i][0] += normal[0] * dot;
                                        e->vertvel[i][1] += normal[1] * dot;
                                        e->vertvel[i][2] += normal[2] * dot;
@@ -236,15 +280,97 @@ void R_MoveExplosion(explosion_t *e, float frametime)
                        {
                                VectorCopy(end, e->vert[i]);
                        }
+                       e->vertvel[i][2] += sv_gravity.value * frametime * -0.25f;
+                       VectorScale(e->vertvel[i], frictionscale, e->vertvel[i]);
+               }
+               /*
+               for (l = list;l < listend;l++)
+               {
+                       VectorSubtract(e->vert[i], (*l)->origin, diff);
+                       dist = DotProduct(diff, diff);
+                       if (dist < 4096 && dist >= 1)
+                       {
+                               dist = (*l)->pressure * frametime / dist;
+                               VectorMA(e->vertvel[i], dist, diff, e->vertvel[i]);
+                       }
+               }
+               */
+       }
+}
+
+/*
+void R_MoveExplosionGas(explosiongas_t *e, explosiongas_t **list, explosiongas_t **listend, float frametime)
+{
+       vec3_t end, diff;
+       vec_t dist, frictionscale;
+       explosiongas_t **l;
+       frictionscale = 1 - frametime;
+       frictionscale = bound(0, frictionscale, 1);
+       if (e->velocity[0] || e->velocity[1] || e->velocity[2])
+       {
+               end[0] = e->origin[0] + frametime * e->velocity[0];
+               end[1] = e->origin[1] + frametime * e->velocity[1];
+               end[2] = e->origin[2] + frametime * e->velocity[2];
+               if (r_explosionclip.value)
+               {
+                       float f, dot;
+                       vec3_t impact, normal;
+                       f = TraceLine(e->origin, end, impact, normal, 0);
+                       VectorCopy(impact, e->origin);
+                       if (f < 1)
+                       {
+                               // clip velocity against the wall
+                               dot = DotProduct(e->velocity, normal) * -1.3f;
+                               e->velocity[0] += normal[0] * dot;
+                               e->velocity[1] += normal[1] * dot;
+                               e->velocity[2] += normal[2] * dot;
+                       }
+               }
+               else
+               {
+                       VectorCopy(end, e->origin);
+               }
+               e->velocity[2] += sv_gravity.value * frametime;
+               VectorScale(e->velocity, frictionscale, e->velocity);
+       }
+       for (l = list;l < listend;l++)
+       {
+               if (*l != e)
+               {
+                       VectorSubtract(e->origin, (*l)->origin, diff);
+                       dist = DotProduct(diff, diff);
+                       if (dist < 4096 && dist >= 1)
+                       {
+                               dist = (*l)->pressure * frametime / dist;
+                               VectorMA(e->velocity, dist, diff, e->velocity);
+                       }
                }
        }
 }
+*/
 
 void R_MoveExplosions(void)
 {
        int i;
        float frametime;
+//     explosiongas_t *gaslist[MAX_EXPLOSIONGAS], **l, **end;
        frametime = cl.time - cl.oldtime;
+       /*
+       l = &gaslist[0];
+       for (i = 0;i < MAX_EXPLOSIONGAS;i++)
+       {
+               if (explosiongas[i].pressure > 0)
+               {
+                       explosiongas[i].pressure -= frametime * GASFADERATE;
+                       if (explosiongas[i].pressure > 0)
+                               *l++ = &explosiongas[i];
+               }
+       }
+       end = l;
+       for (l = gaslist;l < end;l++)
+               R_MoveExplosionGas(*l, gaslist, end, frametime);
+       */
+
        for (i = 0;i < MAX_EXPLOSIONS;i++)
        {
                if (explosion[i].alpha > 0.0f)
@@ -254,7 +380,7 @@ void R_MoveExplosions(void)
                                explosion[i].alpha = 0;
                                continue;
                        }
-                       R_MoveExplosion(&explosion[i], frametime);
+                       R_MoveExplosion(&explosion[i], /*gaslist, end, */frametime);
                }
        }
 }
index 7ac1c62e0154bdc64a17f346ab88b4ffcd8359d0..7e44e373f3e3bd7f1d082ef6b88608548e4b93e8 100644 (file)
-
 #include "quakedef.h"
 
 // LordHavoc: quite tempting to break apart this function to reuse the
 //            duplicated code, but I suspect it is better for performance
 //            this way
-void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend)
+// LordHavoc: later note: made FRAMEBLENDINSERT macro
+void R_LerpAnimation(entity_render_t *r)
 {
        int sub1, sub2, numframes, f, i, data;
-       double sublerp, lerp, l;
+       double sublerp, lerp, d;
        animscene_t *scene, *scenes;
+       frameblend_t *blend;
+       blend = r->frameblend;
 
-       data = (int) Mod_Extradata(mod);
-       if (!data)
-               Host_Error("R_LerpAnimation: model not loaded\n");
-       scenes = (animscene_t *) (mod->ofs_scenes + data);
-
-       numframes = mod->numframes;
+       numframes = r->model->numframes;
 
-       if ((frame1 >= numframes))
+       if ((r->frame1 >= numframes))
        {
-               Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1);
-               frame1 = 0;
+               Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame1);
+               r->frame1 = 0;
        }
 
-       if ((frame2 >= numframes))
+       if ((r->frame2 >= numframes))
        {
-               Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2);
-               frame2 = 0;
+               Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame2);
+               r->frame2 = 0;
        }
 
-       if (frame1 < 0)
-               Host_Error ("R_LerpAnimation: frame1 is NULL\n");
+       // note: this could be removed, if the rendering code allows an empty blend array
+       if (r->frame1 < 0)
+               Host_Error ("CL_LerpAnimation: frame1 is NULL\n");
 
        // round off very close blend percentages
-       if (framelerp < (1.0f / 65536.0f))
-               framelerp = 0;
-       if (framelerp >= (65535.0f / 65536.0f))
-               framelerp = 1;
+       if (r->framelerp < (1.0f / 65536.0f))
+               r->framelerp = 0;
+       if (r->framelerp >= (65535.0f / 65536.0f))
+               r->framelerp = 1;
 
        blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = -1;
        blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0;
-       if (framelerp < 1)
+       if (r->model->ofs_scenes)
        {
-               scene = scenes + frame1;
-               lerp = 1 - framelerp;
+               if (r->model->cachesize)
+               {
+                       data = (int) Mod_Extradata(r->model);
+                       if (!data)
+                               Host_Error("CL_LerpAnimation: model not loaded\n");
+                       scenes = (animscene_t *) (r->model->ofs_scenes + data);
+               }
+               else
+                       scenes = (animscene_t *) r->model->ofs_scenes;
 
-               if (scene->framecount > 1)
+               if (r->framelerp < 1 && r->frame1 >= 0)
                {
-                       sublerp = scene->framerate * (cl.time - frame1start);
-                       sub1 = (int) (sublerp);
-                       sub2 = sub1 + 1;
-                       sublerp -= sub1;
-                       if (sublerp < (1.0f / 65536.0f))
-                               sublerp = 0;
-                       if (sublerp >= (65535.0f / 65536.0f))
-                               sublerp = 1;
-                       if (scene->loop)
+                       scene = scenes + r->frame1;
+                       lerp = 1 - r->framelerp;
+
+                       if (scene->framecount > 1)
                        {
-                               sub1 = (sub1 % scene->framecount) + scene->firstframe;
-                               sub2 = (sub2 % scene->framecount) + scene->firstframe;
+                               sublerp = scene->framerate * (cl.time - r->frame1time);
+                               sub1 = (int) (sublerp);
+                               sub2 = sub1 + 1;
+                               sublerp -= sub1;
+                               if (sublerp < (1.0f / 65536.0f))
+                                       sublerp = 0;
+                               if (sublerp >= (65535.0f / 65536.0f))
+                                       sublerp = 1;
+                               if (scene->loop)
+                               {
+                                       sub1 = (sub1 % scene->framecount) + scene->firstframe;
+                                       sub2 = (sub2 % scene->framecount) + scene->firstframe;
+                               }
+                               else
+                               {
+                                       sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
+                                       sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
+                               }
+                               f = sub1;
+                               d = (1 - sublerp) * lerp;
+#define FRAMEBLENDINSERT\
+                               if (d > 0)\
+                               {\
+                                       for (i = 0;i < 4;i++)\
+                                       {\
+                                               if (blend[i].frame == f)\
+                                               {\
+                                                       blend[i].lerp += d;\
+                                                       break;\
+                                               }\
+                                               if (blend[i].lerp <= 0)\
+                                               {\
+                                                       blend[i].frame = f;\
+                                                       blend[i].lerp = d;\
+                                                       break;\
+                                               }\
+                                       }\
+                               }
+                               FRAMEBLENDINSERT
+                               f = sub2;
+                               d = sublerp * lerp;
                        }
                        else
                        {
-                               sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
-                               sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
-                       }
-                       f = sub1;
-                       l = (1 - sublerp) * lerp;
-                       if (l > 0)
-                       {
-                               for (i = 0;i < 4;i++)
-                               {
-                                       if (blend[i].frame == f)
-                                       {
-                                               blend[i].lerp += l;
-                                               break;
-                                       }
-                                       if (blend[i].lerp <= 0)
-                                       {
-                                               blend[i].frame = f;
-                                               blend[i].lerp = l;
-                                               break;
-                                       }
-                               }
+                               f = scene->firstframe;
+                               d = lerp;
                        }
-                       f = sub2;
-                       l = sublerp * lerp;
+                       FRAMEBLENDINSERT
                }
-               else
-               {
-                       f = scene->firstframe;
-                       l = lerp;
-               }
-               if (l > 0)
+               if (r->framelerp > 0 && r->frame2 >= 0)
                {
-                       for (i = 0;i < 4;i++)
+                       scene = scenes + r->frame2;
+                       lerp = r->framelerp;
+
+                       if (scene->framecount > 1)
                        {
-                               if (blend[i].frame == f)
+                               sublerp = scene->framerate * (cl.time - r->frame1time);
+                               sub1 = (int) (sublerp);
+                               sub2 = sub1 + 1;
+                               sublerp -= sub1;
+                               if (sublerp < (1.0f / 65536.0f))
+                                       sublerp = 0;
+                               if (sublerp >= (65535.0f / 65536.0f))
+                                       sublerp = 1;
+                               if (scene->loop)
                                {
-                                       blend[i].lerp += l;
-                                       break;
+                                       sub1 = (sub1 % scene->framecount) + scene->firstframe;
+                                       sub2 = (sub2 % scene->framecount) + scene->firstframe;
                                }
-                               if (blend[i].lerp <= 0)
+                               else
                                {
-                                       blend[i].frame = f;
-                                       blend[i].lerp = l;
-                                       break;
+                                       sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
+                                       sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
                                }
-                       }
-               }
-       }
-       if (framelerp > 0 && frame2 >= 0)
-       {
-               scene = scenes + frame2;
-               lerp = framelerp;
-
-               if (scene->framecount > 1)
-               {
-                       sublerp = scene->framerate * (cl.time - frame1start);
-                       sub1 = (int) (sublerp);
-                       sub2 = sub1 + 1;
-                       sublerp -= sub1;
-                       if (sublerp < (1.0f / 65536.0f))
-                               sublerp = 0;
-                       if (sublerp >= (65535.0f / 65536.0f))
-                               sublerp = 1;
-                       if (scene->loop)
-                       {
-                               sub1 = (sub1 % scene->framecount) + scene->firstframe;
-                               sub2 = (sub2 % scene->framecount) + scene->firstframe;
+                               f = sub1;
+                               d = (1 - sublerp) * lerp;
+                               FRAMEBLENDINSERT
+                               f = sub2;
+                               d = sublerp * lerp;
                        }
                        else
                        {
-                               sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
-                               sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
-                       }
-                       f = sub1;
-                       l = (1 - sublerp) * lerp;
-                       if (l > 0)
-                       {
-                               for (i = 0;i < 4;i++)
-                               {
-                                       if (blend[i].frame == f)
-                                       {
-                                               blend[i].lerp += l;
-                                               break;
-                                       }
-                                       if (blend[i].lerp <= 0)
-                                       {
-                                               blend[i].frame = f;
-                                               blend[i].lerp = l;
-                                               break;
-                                       }
-                               }
+                               f = scene->firstframe;
+                               d = lerp;
                        }
-                       f = sub2;
-                       l = sublerp * lerp;
+                       FRAMEBLENDINSERT
                }
-               else
+       }
+       else
+       {
+               // if there are no scenes, assume it is all single-frame groups
+               if (r->framelerp < 1 && r->frame1 >= 0)
                {
-                       f = scene->firstframe;
-                       l = lerp;
+                       f = r->frame1;
+                       d = 1 - r->framelerp;
+                       FRAMEBLENDINSERT
                }
-               if (l > 0)
+               if (r->framelerp > 0 && r->frame2 >= 0)
                {
-                       for (i = 0;i < 4;i++)
-                       {
-                               if (blend[i].frame == f)
-                               {
-                                       blend[i].lerp += l;
-                                       break;
-                               }
-                               if (blend[i].lerp <= 0)
-                               {
-                                       blend[i].frame = f;
-                                       blend[i].lerp = l;
-                                       break;
-                               }
-                       }
+                       f = r->frame2;
+                       d = r->framelerp;
+                       FRAMEBLENDINSERT
                }
        }
 }
+
index 83eec6f7bf41a7a4afdb9a1ba8ce3e07fa31e44b..a90101cfa3a54375310e1e1abac9fbb4c9e93202 100644 (file)
@@ -1,9 +1,2 @@
 
-typedef struct
-{
-       int frame;
-       float lerp;
-}
-frameblend_t;
-
-void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend);
+void R_LerpAnimation(entity_render_t *r);
index f8f797c4b4c71ef95e9639ce92869f6c498d6e35..db05fdea5b56a4a8909aff607ab5cde408b8bf79 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -49,7 +49,7 @@ R_AnimateLight
 void R_AnimateLight (void)
 {
        int                     i,j,k;
-       
+
 //
 // light animations
 // 'm' is normal light, 'a' is no light, 'z' is double bright
@@ -131,7 +131,7 @@ loc0:
        surf = cl.worldmodel->surfaces + node->firstsurface;
        for (i=0 ; i<node->numsurfaces ; i++, surf++)
        {
-               int d;
+               int d, impacts, impactt;
                float dist, dist2, impact[3];
                if (surf->visframe != r_framecount)
                        continue;
@@ -150,6 +150,22 @@ loc0:
                impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
                impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
 
+               impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+               d = bound(0, impacts, surf->extents[0] + 16) - impacts;
+               dist2 += d * d;
+               if (dist2 > maxdist)
+                       continue;
+
+               impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+               d = bound(0, impactt, surf->extents[1] + 16) - impactt;
+               dist2 += d * d;
+               if (dist2 > maxdist)
+                       continue;
+
+
+               /*
                d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
 
                if (d < 0)
@@ -187,6 +203,7 @@ loc0:
                                        continue;
                        }
                }
+               */
 
                if (surf->dlightframe != r_framecount) // not dynamic until now
                {
@@ -280,6 +297,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                {
                                        if (c & (1<<i))
                                        {
+                                               // warning to the clumsy: numleafs is one less than it should be, it only counts leafs with vis bits (skips leaf 0)
                                                leafnum = (k << 3)+i+1;
                                                if (leafnum > model->numleafs)
                                                        return;
@@ -317,7 +335,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                                // LordHavoc: make sure it is infront of the surface and not too far away
                                                                if (dist < radius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -radius)))
                                                                {
-                                                                       int d;
+                                                                       int d, impacts, impactt;
                                                                        float dist2, impact[3];
 
                                                                        dist2 = dist * dist;
@@ -326,6 +344,21 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                                        impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
                                                                        impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
 
+                                                                       impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+                                                                       d = bound(0, impacts, surf->extents[0] + 16) - impacts;
+                                                                       dist2 += d * d;
+                                                                       if (dist2 > maxdist)
+                                                                               continue;
+
+                                                                       impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+                                                                       d = bound(0, impactt, surf->extents[1] + 16) - impactt;
+                                                                       dist2 += d * d;
+                                                                       if (dist2 > maxdist)
+                                                                               continue;
+
+                                                                       /*
                                                                        d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
 
                                                                        if (d < 0)
@@ -363,6 +396,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                                                                continue;
                                                                                }
                                                                        }
+                                                                       */
 
                                                                        if (surf->dlightframe != r_framecount) // not dynamic until now
                                                                        {
@@ -379,7 +413,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                k++;
                                continue;
                        }
-               
+
                        k += *in++;
                }
        }
@@ -624,10 +658,10 @@ loc0:
 
                                if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
                                        continue;
-                               
+
                                ds -= surf->texturemins[0];
                                dt -= surf->texturemins[1];
-                               
+
                                if (ds > surf->extents[0] || dt > surf->extents[1])
                                        continue;
 
@@ -730,10 +764,11 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
        }
 }
 
-void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic)
+void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf)
 {
-       mleaf_t *leaf;
-       leaf = Mod_PointInLeaf(p, cl.worldmodel);
+       if (leaf == NULL)
+               leaf = Mod_PointInLeaf(p, cl.worldmodel);
+
        if (leaf->contents == CONTENTS_SOLID)
        {
                color[0] = color[1] = color[2] = 0;
@@ -770,7 +805,7 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits)
                dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
                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);
 
@@ -819,12 +854,12 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
 }
 */
 
-void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
+void R_LightModel(int numverts)
 {
        // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
        int i, j, nearlights = 0, color;
-       vec3_t dist, mod;
-       float t, t1, t2, t3, *avn;
+       vec3_t dist, mod, basecolor, center;
+       float t, t1, t2, t3, *avn, number;
        byte r,g,b,a, *avc;
        struct
        {
@@ -834,29 +869,35 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
        int modeldlightbits[8];
        avc = aliasvertcolor;
        avn = aliasvertnorm;
-       a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
+       VectorCopy(currentrenderentity->origin, center);
+       a = (byte) bound((int) 0, (int) (currentrenderentity->alpha * 255.0f), (int) 255);
        if (lighthalf)
        {
-               mod[0] = ent->render.colormod[0] * 0.5f;
-               mod[1] = ent->render.colormod[1] * 0.5f;
-               mod[2] = ent->render.colormod[2] * 0.5f;
+               mod[0] = currentrenderentity->colormod[0] * 0.5f;
+               mod[1] = currentrenderentity->colormod[1] * 0.5f;
+               mod[2] = currentrenderentity->colormod[2] * 0.5f;
        }
        else
        {
-               mod[0] = ent->render.colormod[0];
-               mod[1] = ent->render.colormod[1];
-               mod[2] = ent->render.colormod[2];
+               mod[0] = currentrenderentity->colormod[0];
+               mod[1] = currentrenderentity->colormod[1];
+               mod[2] = currentrenderentity->colormod[2];
        }
-       if (ent->render.effects & EF_FULLBRIGHT)
+       if (currentrenderentity->effects & EF_FULLBRIGHT)
        {
-               ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
-               ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
-               ((byte *)&color)[2] = (byte) (255.0f * mod[2]);
-               ((byte *)&color)[3] = a;
-               for (i = 0;i < numverts;i++)
+               if (a == 255)
+                       memset(avc, 0, 4 * numverts);
+               else
                {
-                       *((int *)avc) = color;
-                       avc += 4;
+                       ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
+                       ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
+                       ((byte *)&color)[2] = (byte) (255.0f * mod[2]);
+                       ((byte *)&color)[3] = a;
+                       for (i = 0;i < numverts;i++)
+                       {
+                               *((int *)avc) = color;
+                               avc += 4;
+                       }
                }
                return;
        }
@@ -879,24 +920,36 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
                t1 = cl_dlights[i].radius*cl_dlights[i].radius;
                if (t2 < t1)
                {
-                       // transform the light into the model's coordinate system
-                       if (gl_transform.value)
-                               softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin);
-                       else
-                       {
-                               VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
-                       }
-                       nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
-                       nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
-                       nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
-                       if (r_lightmodels.value && (ent == NULL || ent != cl_dlights[i].ent))
-                               nearlights++;
-                       else
+                       if (TraceLine(center, cl_dlights[i].origin, NULL, NULL, 0))
                        {
-                               t1 = 1.0f / t2;
-                               basecolor[0] += nearlight[nearlights].color[0] * t1;
-                               basecolor[1] += nearlight[nearlights].color[1] * t1;
-                               basecolor[2] += nearlight[nearlights].color[2] * t1;
+                               // transform the light into the model's coordinate system
+                               if (gl_transform.value)
+                                       softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin);
+                               else
+                                       VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
+                               nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
+                               nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
+                               nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
+                               if (r_lightmodels.value && currentrenderentity != cl_dlights[i].ent)
+                               {
+                                       // boost color, to compensate for dark lighting calcs
+                                       VectorScale(nearlight[nearlights].color, cl_dlights[i].radius * 16.0f, nearlight[nearlights].color);
+                                       nearlights++;
+                               }
+                               else
+                               {
+#if SLOWMATH
+                                       t1 = 1.0f / sqrt(t2);
+#else
+                                       number = t1;
+                                       *((long *)&t1) = 0x5f3759df - ((* (long *) &number) >> 1);
+                                       t1 = t1 * (1.5f - (number * 0.5f * t1 * t1));
+#endif
+                                       t1 = t1 * t1;
+                                       basecolor[0] += nearlight[nearlights].color[0] * t1;
+                                       basecolor[1] += nearlight[nearlights].color[1] * t1;
+                                       basecolor[2] += nearlight[nearlights].color[2] * t1;
+                               }
                        }
                }
        }
@@ -909,73 +962,61 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
        ((byte *)&color)[3] = a;
        if (nearlights)
        {
-               int temp;
+               int i1, i2, i3;
                vec3_t v;
-               float *av;
+               float *av, number;
                av = aliasvert;
-               if (nearlights == 1)
+               for (i = 0;i < numverts;i++)
                {
-                       for (i = 0;i < numverts;i++)
+                       t1 = basecolor[0];
+                       t2 = basecolor[1];
+                       t3 = basecolor[2];
+                       for (j = 0;j < nearlights;j++)
                        {
-                               VectorSubtract(nearlight[0].origin, av, v);
+                               VectorSubtract(nearlight[j].origin, av, v);
                                t = DotProduct(avn,v);
                                if (t > 0)
                                {
-                                       t /= (DotProduct(v,v) + LIGHTOFFSET);
-                                       temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));
-                                       avc[0] = bound(0, temp, 255);
-                                       temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));
-                                       avc[1] = bound(0, temp, 255);
-                                       temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));
-                                       avc[2] = bound(0, temp, 255);
-                                       avc[3] = a;
+#if SLOWMATH
+                                       t = 1.0f / sqrt(DotProduct(v,v) + 1.0f);
+#else
+                                       number = DotProduct(v, v) + LIGHTOFFSET;
+                                       *((long *)&t) = 0x5f3759df - ((* (long *) &number) >> 1);
+                                       t = t * (1.5f - (number * 0.5f * t * t));
+#endif
+                                       t = t * t * t;
+                                       t1 += nearlight[j].color[0] * t;
+                                       t2 += nearlight[j].color[1] * t;
+                                       t3 += nearlight[j].color[2] * t;
                                }
-                               else
-                                       *((int *)avc) = color;
-                               avc += 4;
-                               av += 3;
-                               avn += 3;
-                       }
-               }
-               else
-               {
-                       for (i = 0;i < numverts;i++)
-                       {
-                               int lit;
-                               t1 = basecolor[0];
-                               t2 = basecolor[1];
-                               t3 = basecolor[2];
-                               lit = false;
-                               for (j = 0;j < nearlights;j++)
-                               {
-                                       VectorSubtract(nearlight[j].origin, av, v);
-                                       t = DotProduct(avn,v);
-                                       if (t > 0)
-                                       {
-                                               t /= (DotProduct(v,v) + LIGHTOFFSET);
-                                               t1 += nearlight[j].color[0] * t;
-                                               t2 += nearlight[j].color[1] * t;
-                                               t3 += nearlight[j].color[2] * t;
-                                               lit = true;
-                                       }
-                               }
-                               if (lit)
-                               {
-                                       int i1, i2, i3;
-                                       i1 = (int) t1;
-                                       avc[0] = bound(0, i1, 255);
-                                       i2 = (int) t2;
-                                       avc[1] = bound(0, i2, 255);
-                                       i3 = (int) t3;
-                                       avc[2] = bound(0, i3, 255);
-                                       avc[3] = a;
-                               }
-                               else // dodge the costly float -> int conversions
-                                       *((int *)avc) = color;
-                               avc += 4;
-                               av += 3;
-                               avn += 3;
                        }
+
+                       // FIXME: float to int conversions are very slow on x86 because of
+                       // mode switchs (switch from nearest rounding to down, then back,
+                       // each time), reimplement this part in assembly, SSE and 3DNow!
+                       // versions recommended as well
+#if SLOWMATH
+                       i1 = (int) t1;
+                       i2 = (int) t2;
+                       i3 = (int) t3;
+#else
+                       // later note: implemented bit hacking float to integer,
+                       // probably makes the issue irrelevant
+                       t1 += 8388608.0f;
+                       i1 = *((long *)&t1) & 0x007FFFFF;
+                       t2 += 8388608.0f;
+                       i2 = *((long *)&t2) & 0x007FFFFF;
+                       t3 += 8388608.0f;
+                       i3 = *((long *)&t3) & 0x007FFFFF;
+#endif
+
+                       avc[0] = bound(0, i1, 255);
+                       avc[1] = bound(0, i2, 255);
+                       avc[2] = bound(0, i3, 255);
+                       avc[3] = a;
+                       avc += 4;
+                       av += 3;
+                       avn += 3;
                }
        }
        else
index 6e29e589b0a65c03948e136a64174e44117751b9..0507c425eb9cb8859a538cdccb0fda334a97dc1f 100644 (file)
--- a/r_light.h
+++ b/r_light.h
@@ -1,20 +1,7 @@
 
-// LordHavoc: 256 dynamic lights
-#define        MAX_DLIGHTS             256
-typedef struct
-{
-       vec3_t  origin;
-       float   radius;
-       float   die;                            // stop lighting after this time
-       float   decay;                          // drop this each second
-       entity_t *ent;                          // the entity that spawned this light (can be NULL if it is not to be replaced repeatedly)
-       vec3_t  color;                          // LordHavoc: colored lighting
-} dlight_t;
-
-// LordHavoc: this affects the lighting scale of the whole game
-#define LIGHTOFFSET 4096.0f
-
-extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic);
+extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf);
 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 void R_AnimateLight (void);
+extern void R_LightModel (int numverts);
index 790a421859de5cd5c10306d391565b08626a50c8..9ee7f9bbfe5aa072cfff5548097a8961b9d93265 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -23,23 +23,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define MAX_PARTICLES                  16384   // default max # of particles at one time
 #define ABSOLUTE_MIN_PARTICLES 512             // no fewer than this no matter what's on the command line
 
-// LordHavoc: added dust, smoke, snow, bloodcloud, and many others
 typedef enum
 {
-       pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame/*, pt_decal*/, pt_blood, pt_oneframe, pt_lavasplash
+       pt_static, pt_grav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame, pt_blood, pt_oneframe, pt_lavasplash, pt_raindropsplash, pt_underwaterspark, pt_explosionsplash
 }
 ptype_t;
 
+typedef struct
+{
+       float s1, t1, s2, t2;
+}
+particletexture_t;
+
 typedef struct particle_s
 {
        ptype_t         type;
        vec3_t          org;
        vec3_t          vel;
-       rtexture_t      *tex;
-       byte            dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
-       byte            rendermode; // a TPOLYTYPE_ value
-       byte            color;
-       byte            pad2;
+       particletexture_t       *tex;
        float           die;
        float           scale;
        float           alpha; // 0-255
@@ -47,43 +48,80 @@ typedef struct particle_s
        float           bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
        vec3_t          oldorg;
        vec3_t          vel2; // used for snow fluttering (base velocity, wind for instance)
-//     vec3_t          direction; // used by decals
-//     vec3_t          decalright; // used by decals
-//     vec3_t          decalup; // used by decals
+       float           friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
+       float           pressure; // if non-zero, apply pressure to other particles
+       int                     dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
+       int                     rendermode; // a TPOLYTYPE_ value
+       byte            color[4];
 }
 particle_t;
 
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
-
-int            ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
-int            ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
-int            ramp3[8] = {0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
-
-rtexture_t *particletexture;
-rtexture_t *smokeparticletexture[8];
-rtexture_t *rainparticletexture;
-rtexture_t *bubbleparticletexture;
-rtexture_t *bulletholetexture[8];
-rtexture_t *rocketglowparticletexture;
-
-particle_t     *particles;
-int                    r_numparticles;
-
-vec3_t                 r_pright, r_pup, r_ppn;
-
-int                    numparticles;
-particle_t     **freeparticles; // list used only in compacting particles array
-
-cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"};
-cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
-cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"};
-cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"};
-cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"};
-cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"};
-cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"};
-cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"};
-
-byte shadebubble(float dx, float dy, vec3_t light)
+static int particlepalette[256] =
+{
+       0x000000,0x0f0f0f,0x1f1f1f,0x2f2f2f,0x3f3f3f,0x4b4b4b,0x5b5b5b,0x6b6b6b,
+       0x7b7b7b,0x8b8b8b,0x9b9b9b,0xababab,0xbbbbbb,0xcbcbcb,0xdbdbdb,0xebebeb,
+       0x0f0b07,0x170f0b,0x1f170b,0x271b0f,0x2f2313,0x372b17,0x3f2f17,0x4b371b,
+       0x533b1b,0x5b431f,0x634b1f,0x6b531f,0x73571f,0x7b5f23,0x836723,0x8f6f23,
+       0x0b0b0f,0x13131b,0x1b1b27,0x272733,0x2f2f3f,0x37374b,0x3f3f57,0x474767,
+       0x4f4f73,0x5b5b7f,0x63638b,0x6b6b97,0x7373a3,0x7b7baf,0x8383bb,0x8b8bcb,
+       0x000000,0x070700,0x0b0b00,0x131300,0x1b1b00,0x232300,0x2b2b07,0x2f2f07,
+       0x373707,0x3f3f07,0x474707,0x4b4b0b,0x53530b,0x5b5b0b,0x63630b,0x6b6b0f,
+       0x070000,0x0f0000,0x170000,0x1f0000,0x270000,0x2f0000,0x370000,0x3f0000,
+       0x470000,0x4f0000,0x570000,0x5f0000,0x670000,0x6f0000,0x770000,0x7f0000,
+       0x131300,0x1b1b00,0x232300,0x2f2b00,0x372f00,0x433700,0x4b3b07,0x574307,
+       0x5f4707,0x6b4b0b,0x77530f,0x835713,0x8b5b13,0x975f1b,0xa3631f,0xaf6723,
+       0x231307,0x2f170b,0x3b1f0f,0x4b2313,0x572b17,0x632f1f,0x733723,0x7f3b2b,
+       0x8f4333,0x9f4f33,0xaf632f,0xbf772f,0xcf8f2b,0xdfab27,0xefcb1f,0xfff31b,
+       0x0b0700,0x1b1300,0x2b230f,0x372b13,0x47331b,0x533723,0x633f2b,0x6f4733,
+       0x7f533f,0x8b5f47,0x9b6b53,0xa77b5f,0xb7876b,0xc3937b,0xd3a38b,0xe3b397,
+       0xab8ba3,0x9f7f97,0x937387,0x8b677b,0x7f5b6f,0x775363,0x6b4b57,0x5f3f4b,
+       0x573743,0x4b2f37,0x43272f,0x371f23,0x2b171b,0x231313,0x170b0b,0x0f0707,
+       0xbb739f,0xaf6b8f,0xa35f83,0x975777,0x8b4f6b,0x7f4b5f,0x734353,0x6b3b4b,
+       0x5f333f,0x532b37,0x47232b,0x3b1f23,0x2f171b,0x231313,0x170b0b,0x0f0707,
+       0xdbc3bb,0xcbb3a7,0xbfa39b,0xaf978b,0xa3877b,0x977b6f,0x876f5f,0x7b6353,
+       0x6b5747,0x5f4b3b,0x533f33,0x433327,0x372b1f,0x271f17,0x1b130f,0x0f0b07,
+       0x6f837b,0x677b6f,0x5f7367,0x576b5f,0x4f6357,0x475b4f,0x3f5347,0x374b3f,
+       0x2f4337,0x2b3b2f,0x233327,0x1f2b1f,0x172317,0x0f1b13,0x0b130b,0x070b07,
+       0xfff31b,0xefdf17,0xdbcb13,0xcbb70f,0xbba70f,0xab970b,0x9b8307,0x8b7307,
+       0x7b6307,0x6b5300,0x5b4700,0x4b3700,0x3b2b00,0x2b1f00,0x1b0f00,0x0b0700,
+       0x0000ff,0x0b0bef,0x1313df,0x1b1bcf,0x2323bf,0x2b2baf,0x2f2f9f,0x2f2f8f,
+       0x2f2f7f,0x2f2f6f,0x2f2f5f,0x2b2b4f,0x23233f,0x1b1b2f,0x13131f,0x0b0b0f,
+       0x2b0000,0x3b0000,0x4b0700,0x5f0700,0x6f0f00,0x7f1707,0x931f07,0xa3270b,
+       0xb7330f,0xc34b1b,0xcf632b,0xdb7f3b,0xe3974f,0xe7ab5f,0xefbf77,0xf7d38b,
+       0xa77b3b,0xb79b37,0xc7c337,0xe7e357,0x7fbfff,0xabe7ff,0xd7ffff,0x670000,
+       0x8b0000,0xb30000,0xd70000,0xff0000,0xfff393,0xfff7c7,0xffffff,0x9f5b53
+};
+
+static int explosparkramp[8] = {0x4b0700, 0x6f0f00, 0x931f07, 0xb7330f, 0xcf632b, 0xe3974f, 0xffe7b5, 0xffffff};
+//static int explounderwatersparkramp[8] = {0x00074b, 0x000f6f, 0x071f93, 0x0f33b7, 0x2b63cf, 0x4f97e3, 0xb5e7ff, 0xffffff};
+
+static rtexture_t *particlefonttexture;
+
+static particletexture_t particletexture;
+static particletexture_t smokeparticletexture[8];
+static particletexture_t rainparticletexture;
+static particletexture_t bubbleparticletexture;
+static particletexture_t bulletholetexture[8];
+static particletexture_t rocketglowparticletexture;
+static particletexture_t raindropsplashparticletexture[16];
+
+static particle_t      *particles;
+static int                     r_numparticles;
+
+static int                     numparticles;
+static particle_t      **freeparticles; // list used only in compacting particles array
+
+static cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"};
+static cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
+static cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"};
+static cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"};
+static cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"};
+static cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"};
+static cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"};
+static cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"};
+static cvar_t r_particles_explosions = {CVAR_SAVE, "r_particles_explosions", "0"};
+
+static byte shadebubble(float dx, float dy, vec3_t light)
 {
        float   dz, f, dot;
        vec3_t  normal;
@@ -116,12 +154,34 @@ byte shadebubble(float dx, float dy, vec3_t light)
                return 0;
 }
 
-void R_InitParticleTexture (void)
+static void R_InitParticleTexture (void)
 {
-       int             x,y,d,i,m;
-       float   dx, dy;
+       int             x,y,d,i,m, texnum;
+       float   dx, dy, radius, f, f2;
        byte    data[32][32][4], noise1[64][64], noise2[64][64];
        vec3_t  light;
+       byte    particletexturedata[256][256][4];
+
+       memset(&particletexturedata[0][0][0], 255, sizeof(particletexturedata));
+       texnum = 0;
+       #define SETUPTEX(var)\
+       {\
+               int basex, basey, y;\
+               if (texnum >= 64)\
+               {\
+                       Sys_Error("R_InitParticleTexture: ran out of textures (64)\n");\
+                       return; /* only to hush compiler */ \
+               }\
+               basex = (texnum & 7) * 32;\
+               basey = ((texnum >> 3) & 7) * 32;\
+               var.s1 = (basex + 1) / 256.0f;\
+               var.t1 = (basey + 1) / 256.0f;\
+               var.s2 = (basex + 31) / 256.0f;\
+               var.t2 = (basey + 31) / 256.0f;\
+               for (y = 0;y < 32;y++)\
+                       memcpy(&particletexturedata[basey + y][basex][0], &data[y][0][0], 32*4);\
+               texnum++;\
+       }
 
        for (y = 0;y < 32;y++)
        {
@@ -135,7 +195,8 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       SETUPTEX(particletexture)
+//     particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 
        for (i = 0;i < 8;i++)
        {
@@ -149,11 +210,11 @@ void R_InitParticleTexture (void)
                                dy = y - 16;
                                for (x = 0;x < 32;x++)
                                {
-                                       d = (noise1[y][x] - 128) * 2 + 128;
+                                       d = (noise1[y][x] - 128) * 2 + 64; // was + 128
                                        d = bound(0, d, 255);
                                        data[y][x][0] = data[y][x][1] = data[y][x][2] = d;
                                        dx = x - 16;
-                                       d = (noise2[y][x] - 128) * 4 + 128;
+                                       d = (noise2[y][x] - 128) * 3 + 192;
                                        if (d > 0)
                                                d = (d * (256 - (int) (dx*dx+dy*dy))) >> 8;
                                        d = bound(0, d, 255);
@@ -165,7 +226,8 @@ void R_InitParticleTexture (void)
                }
                while (m < 224);
 
-               smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+               SETUPTEX(smokeparticletexture[i])
+//             smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        }
 
        light[0] = 1;light[1] = 1;light[2] = 1;
@@ -178,7 +240,8 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light);
                }
        }
-       rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       SETUPTEX(rainparticletexture)
+//     rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
@@ -190,7 +253,8 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
                }
        }
-       bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       SETUPTEX(bubbleparticletexture)
+//     bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 
        for (i = 0;i < 8;i++)
        {
@@ -243,7 +307,8 @@ void R_InitParticleTexture (void)
                        }
                }
 
-               bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+               SETUPTEX(bulletholetexture[i])
+//             bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        }
 
        for (y = 0;y < 32;y++)
@@ -259,10 +324,33 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = bound(0, d * 1.0f, 255);
                }
        }
-       rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       SETUPTEX(rocketglowparticletexture)
+//     rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+
+       for (i = 0;i < 16;i++)
+       {
+               radius = i * 3.0f / 16.0f;
+               f2 = 255.0f * ((15.0f - i) / 15.0f);
+               for (y = 0;y < 32;y++)
+               {
+                       dy = (y - 16) * 0.25f;
+                       for (x = 0;x < 32;x++)
+                       {
+                               dx = (x - 16) * 0.25f;
+                               data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
+                               f = (1.0 - fabs(radius - sqrt(dx*dx+dy*dy))) * f2;
+                               f = bound(0.0f, f, 255.0f);
+                               data[y][x][3] = (int) f;
+                       }
+               }
+               SETUPTEX(raindropsplashparticletexture[i])
+//             raindropsplashparticletexture[i] = R_LoadTexture (va("raindropslashparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+       }
+
+       particlefonttexture = R_LoadTexture ("particlefont", 256, 256, &particletexturedata[0][0][0], TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
-void r_part_start(void)
+static void r_part_start(void)
 {
        particles = (particle_t *) qmalloc(r_numparticles * sizeof(particle_t));
        freeparticles = (void *) qmalloc(r_numparticles * sizeof(particle_t *));
@@ -270,14 +358,14 @@ void r_part_start(void)
        R_InitParticleTexture ();
 }
 
-void r_part_shutdown(void)
+static void r_part_shutdown(void)
 {
        numparticles = 0;
        qfree(particles);
        qfree(freeparticles);
 }
 
-void r_part_newmap(void)
+static void r_part_newmap(void)
 {
        numparticles = 0;
 }
@@ -305,7 +393,7 @@ void R_Particles_Init (void)
                r_numparticles = MAX_PARTICLES;
        }
 
-       Cmd_AddCommand ("pointfile", R_ReadPointFile_f);        
+       Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
 
        Cvar_RegisterVariable (&r_particles);
        Cvar_RegisterVariable (&r_drawparticles);
@@ -315,96 +403,26 @@ void R_Particles_Init (void)
        Cvar_RegisterVariable (&r_particles_smoke);
        Cvar_RegisterVariable (&r_particles_sparks);
        Cvar_RegisterVariable (&r_particles_bubbles);
+       Cvar_RegisterVariable (&r_particles_explosions);
 
        R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
 }
 
 //void particle(int ptype, int pcolor, int ptex, int prendermode, int plight, float pscale, float palpha, float ptime, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz)
-#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz)\
+#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
 {\
        particle_t      *part;\
+       int tempcolor;\
        if (numparticles >= r_numparticles)\
                return;\
        part = &particles[numparticles++];\
        part->type = (ptype);\
-       part->color = (pcolor);\
-       part->tex = (ptex);\
-       part->dynlight = (plight);\
-       part->rendermode = (prendermode);\
-       part->scale = (pscale);\
-       part->alpha = (palpha);\
-       part->die = cl.time + (ptime);\
-       part->bounce = (pbounce);\
-       part->org[0] = (px);\
-       part->org[1] = (py);\
-       part->org[2] = (pz);\
-       part->vel[0] = (pvx);\
-       part->vel[1] = (pvy);\
-       part->vel[2] = (pvz);\
-       part->time2 = 0;\
-       part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-/*
-#define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\
-{\
-       particle_t      *part;\
-       if (numparticles >= r_numparticles)\
-               return;\
-       part = &particles[numparticles++];\
-       part->type = (ptype);\
-       part->color = (pcolor);\
-       part->tex = (ptex);\
-       part->dynlight = (plight);\
-       part->rendermode = (prendermode);\
-       part->scale = (pscale);\
-       part->alpha = (palpha);\
-       part->die = cl.time + (ptime);\
-       part->bounce = (pbounce);\
-       part->org[0] = lhrandom(-(poscale), (poscale)) + (pbase)[0];\
-       part->org[1] = lhrandom(-(poscale), (poscale)) + (pbase)[1];\
-       part->org[2] = lhrandom(-(poscale), (poscale)) + (pbase)[2];\
-       part->vel[0] = lhrandom(-(pvscale), (pvscale));\
-       part->vel[1] = lhrandom(-(pvscale), (pvscale));\
-       part->vel[2] = lhrandom(-(pvscale), (pvscale));\
-       part->time2 = 0;\
-       part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-*/
-/*
-#define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
-{\
-       particle_t      *part;\
-       if (numparticles >= r_numparticles)\
-               return;\
-       part = &particles[numparticles++];\
-       part->type = (ptype);\
-       part->color = (pcolor);\
-       part->tex = (ptex);\
-       part->dynlight = (plight);\
-       part->rendermode = (prendermode);\
-       part->scale = (pscale);\
-       part->alpha = (palpha);\
-       part->die = cl.time + (ptime);\
-       part->bounce = (pbounce);\
-       part->org[0] = lhrandom(-(pscalex), (pscalex)) + (pbase)[0];\
-       part->org[1] = lhrandom(-(pscaley), (pscaley)) + (pbase)[1];\
-       part->org[2] = lhrandom(-(pscalez), (pscalez)) + (pbase)[2];\
-       part->vel[0] = lhrandom(-(pvscalex), (pvscalex));\
-       part->vel[1] = lhrandom(-(pvscaley), (pvscaley));\
-       part->vel[2] = lhrandom(-(pvscalez), (pvscalez));\
-       part->time2 = 0;\
-       part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-*/
-#define particle4(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2)\
-{\
-       particle_t      *part;\
-       if (numparticles >= r_numparticles)\
-               return;\
-       part = &particles[numparticles++];\
-       part->type = (ptype);\
-       part->color = (pcolor);\
-       part->tex = (ptex);\
+       tempcolor = (pcolor);\
+       part->color[0] = ((tempcolor) >> 16) & 0xFF;\
+       part->color[1] = ((tempcolor) >> 8) & 0xFF;\
+       part->color[2] = (tempcolor) & 0xFF;\
+       part->color[3] = 0xFF;\
+       part->tex = (&ptex);\
        part->dynlight = (plight);\
        part->rendermode = (prendermode);\
        part->scale = (pscale);\
@@ -421,6 +439,8 @@ void R_Particles_Init (void)
        part->vel2[0] = (pvx2);\
        part->vel2[1] = (pvy2);\
        part->vel2[2] = (pvz2);\
+       part->friction = (pfriction);\
+       part->pressure = (ppressure);\
 }
 
 /*
@@ -438,7 +458,7 @@ void R_EntityParticles (entity_t *ent)
        float           beamlength;
        static vec3_t avelocities[NUMVERTEXNORMALS];
        if (!r_particles.value) return; // LordHavoc: particles are optional
-       
+
        dist = 64;
        beamlength = 16;
 
@@ -454,12 +474,12 @@ void R_EntityParticles (entity_t *ent)
                angle = cl.time * avelocities[i][1];
                sp = sin(angle);
                cp = cos(angle);
-       
+
                forward[0] = cp*cy;
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               particle(pt_oneframe, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
+               particle(pt_oneframe, particlepalette[0x6f], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }
 }
 
@@ -471,7 +491,7 @@ void R_ReadPointFile_f (void)
        int             r;
        int             c;
        char    name[MAX_OSPATH];
-       
+
        sprintf (name,"maps/%s.pts", sv.name);
 
        COM_FOpenFile (name, &f, false, true);
@@ -480,7 +500,7 @@ void R_ReadPointFile_f (void)
                Con_Printf ("couldn't open %s\n", name);
                return;
        }
-       
+
        Con_Printf ("Reading %s...\n", name);
        c = 0;
        for (;;)
@@ -490,13 +510,13 @@ void R_ReadPointFile_f (void)
                if (r != 3)
                        break;
                c++;
-               
+
                if (numparticles >= r_numparticles)
                {
                        Con_Printf ("Not enough free particles\n");
                        break;
                }
-               particle(pt_static, (-c)&15, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0);
+               particle(pt_static, particlepalette[(-c)&15], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }
 
        Qclose (f);
@@ -514,7 +534,7 @@ void R_ParseParticleEffect (void)
 {
        vec3_t          org, dir;
        int                     i, count, msgcount, color;
-       
+
        for (i=0 ; i<3 ; i++)
                org[i] = MSG_ReadCoord ();
        for (i=0 ; i<3 ; i++)
@@ -522,14 +542,14 @@ void R_ParseParticleEffect (void)
        msgcount = MSG_ReadByte ();
        color = MSG_ReadByte ();
 
-if (msgcount == 255)
-       count = 1024;
-else
-       count = msgcount;
-       
+       if (msgcount == 255)
+               count = 1024;
+       else
+               count = msgcount;
+
        R_RunParticleEffect (org, dir, color, count);
 }
-       
+
 /*
 ===============
 R_ParticleExplosion
@@ -538,58 +558,69 @@ R_ParticleExplosion
 */
 void R_ParticleExplosion (vec3_t org, int smoke)
 {
-       int i;
-       if (!r_particles.value) return; // LordHavoc: particles are optional
-
-//     particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
+       int i, j;
+       float f;
+       vec3_t v, end, ang;
+       byte noise1[32*32], noise2[32*32];
 
-       i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
-       if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
-       {
-               for (i = 0;i < 128;i++)
-                       particle(pt_bubble, 254, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96));
-       }
-       else
-               R_NewExplosion(org);
-       /*
-       else
+       if (r_particles.value && r_particles_explosions.value)
        {
-               int j;
-//             int color;
-               float f, forg[3], fvel[3], fvel2[3];
-//             for (i = 0;i < 256;i++)
-//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(0, 384));
-//             for (i = 0;i < 256;i++)
-//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-150, 150), lhrandom(-150, 150), lhrandom(-150, 150));
-               for (i = 0;i < 32;i++)
+               i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
+               if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
+               {
+                       for (i = 0;i < 128;i++)
+                               particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, TPOLYTYPE_ALPHA, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
+
+                       ang[2] = lhrandom(0, 360);
+                       fractalnoise(noise1, 32, 4);
+                       fractalnoise(noise2, 32, 8);
+                       for (i = 0;i < 32;i++)
+                       {
+                               for (j = 0;j < 32;j++)
+                               {
+                                       VectorRandom(v);
+                                       VectorMA(org, 16, v, v);
+                                       TraceLine(org, v, end, NULL, 0);
+                                       ang[0] = (j + 0.5f) * (360.0f / 32.0f);
+                                       ang[1] = (i + 0.5f) * (360.0f / 32.0f);
+                                       AngleVectors(ang, v, NULL, NULL);
+                                       f = noise1[j*32+i] * 1.5f;
+                                       VectorScale(v, f, v);
+                                       particle(pt_underwaterspark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+                                       VectorScale(v, 0.75, v);
+                                       particle(pt_underwaterspark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+                               }
+                       }
+               }
+               else
                {
-                       fvel[0] = lhrandom(-150, 150);
-                       fvel[1] = lhrandom(-150, 150);
-                       fvel[2] = lhrandom(-150, 150) + 80;
-//                     particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 5, forg[0] + lhrandom(-5, 5), forg[1] + lhrandom(-5, 5), forg[2] + lhrandom(-5, 5), fvel2[0], fvel2[1], fvel2[2]);
-                       for (j = 0;j < 64;j++)
+                       ang[2] = lhrandom(0, 360);
+                       fractalnoise(noise1, 32, 4);
+                       fractalnoise(noise2, 32, 8);
+                       for (i = 0;i < 32;i++)
                        {
-                               forg[0] = lhrandom(-20, 20) + org[0];
-                               forg[1] = lhrandom(-20, 20) + org[1];
-                               forg[2] = lhrandom(-20, 20) + org[2];
-                               fvel2[0] = fvel[0] + lhrandom(-30, 30);
-                               fvel2[1] = fvel[1] + lhrandom(-30, 30);
-                               fvel2[2] = fvel[2] + lhrandom(-30, 30);
-                               f = lhrandom(0.2, 1);
-                               fvel2[0] *= f;
-                               fvel2[1] *= f;
-                               fvel2[2] *= f;
-                               particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]);
+                               for (j = 0;j < 32;j++)
+                               {
+                                       VectorRandom(v);
+                                       VectorMA(org, 16, v, v);
+                                       TraceLine(org, v, end, NULL, 0);
+                                       ang[0] = (j + 0.5f) * (360.0f / 32.0f);
+                                       ang[1] = (i + 0.5f) * (360.0f / 32.0f);
+                                       AngleVectors(ang, v, NULL, NULL);
+                                       f = noise1[j*32+i] * 1.5f;
+                                       VectorScale(v, f, v);
+                                       particle(pt_spark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                                       VectorScale(v, 0.75, v);
+                                       particle(pt_spark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                               //      VectorRandom(v);
+                               //      VectorScale(v, 384, v);
+                               //      particle(pt_spark, explosparkramp[rand()&7], particletexture, TPOLYTYPE_ALPHA, false, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                               }
                        }
                }
-//             for (i = 0;i < 16;i++)
-//                     particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org[0] + lhrandom(-20, 20), org[1] + lhrandom(-20, 20), org[2] + lhrandom(-20, 20), 0, 0, 0);
-//             for (i = 0;i < 50;i++)
-//                     particle(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-200, 200), lhrandom(-200, 200), lhrandom(-200, 200));
-//             for (i = 0;i < 30;i++)
-//                     particle(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-100, 100), lhrandom(-100, 100), lhrandom(-100, 100));
        }
-       */
+       else
+               R_NewExplosion(org);
 }
 
 /*
@@ -604,7 +635,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i = 0;i < 512;i++)
-               particle(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192));
+               particle(pt_fade, particlepalette[colorStart + (i % colorLength)], particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0);
 }
 
 /*
@@ -617,11 +648,11 @@ void R_BlobExplosion (vec3_t org)
 {
        int                     i;
        if (!r_particles.value) return; // LordHavoc: particles are optional
-       
+
        for (i = 0;i < 256;i++)
-               particle(pt_blob,   66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
+               particle(pt_blob , particlepalette[ 66+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
        for (i = 0;i < 256;i++)
-               particle(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
+               particle(pt_blob2, particlepalette[150+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
 }
 
 /*
@@ -633,14 +664,14 @@ R_RunParticleEffect
 void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
 {
        if (!r_particles.value) return; // LordHavoc: particles are optional
-       
+
        if (count == 1024)
        {
                R_ParticleExplosion(org, false);
                return;
        }
        while (count--)
-               particle(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15));
+               particle(pt_fade, particlepalette[color + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
 }
 
 // LordHavoc: added this for spawning sparks/dust (which have strong gravity)
@@ -651,19 +682,21 @@ R_SparkShower
 */
 void R_SparkShower (vec3_t org, vec3_t dir, int count)
 {
+       particletexture_t *tex;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       R_Decal(org, bulletholetexture[rand()&7], 16, 0, 0, 0, 255);
+       tex = &bulletholetexture[rand()&7];
+       R_Decal(org, particlefonttexture, tex->s1, tex->t1, tex->s2, tex->t2, 16, 0, 0, 0, 255);
 
        // smoke puff
        if (r_particles_smoke.value)
-               particle(pt_bulletsmoke, 10, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16));
+               particle(pt_bulletsmoke, 0xA0A0A0, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
 
        if (r_particles_sparks.value)
        {
                // sparks
                while(count--)
-                       particle(pt_spark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128));
+                       particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
        }
 }
 
@@ -679,7 +712,7 @@ void R_BloodPuff (vec3_t org, vec3_t vel, int count)
        bloodcount += count;
        while(bloodcount >= 10)
        {
-               particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+               particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                bloodcount -= 10;
        }
 }
@@ -701,7 +734,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        velscale[0] = velspeed * 2.0 / diff[0];
        velscale[1] = velspeed * 2.0 / diff[1];
        velscale[2] = velspeed * 2.0 / diff[2];
-       
+
        while (count--)
        {
                vec3_t org, vel;
@@ -711,7 +744,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
                vel[0] = (org[0] - center[0]) * velscale[0];
                vel[1] = (org[1] - center[1]) * velscale[1];
                vel[2] = (org[2] - center[2]) * velscale[2];
-               particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]);
+               particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0);
        }
 }
 
@@ -724,7 +757,7 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
        while (count--)
-               particle(gravity ? pt_grav : pt_static, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel));
+               particle(gravity ? pt_grav : pt_static, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
 }
 
 void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type)
@@ -756,7 +789,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                        vel[0] = dir[0] + lhrandom(-16, 16);
                        vel[1] = dir[1] + lhrandom(-16, 16);
                        vel[2] = dir[2] + lhrandom(-32, 32);
-                       particle4(pt_rain, colorbase + (rand()&3), rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]);
+                       particle(pt_rain, particlepalette[colorbase + (rand()&3)], rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
                }
                break;
        case 1:
@@ -765,7 +798,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                        vel[0] = dir[0] + lhrandom(-16, 16);
                        vel[1] = dir[1] + lhrandom(-16, 16);
                        vel[2] = dir[2] + lhrandom(-32, 32);
-                       particle4(pt_snow, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]);
+                       particle(pt_snow, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
                }
                break;
        default:
@@ -782,7 +815,7 @@ void R_FlameCube (vec3_t mins, vec3_t maxs, int count)
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
        while (count--)
-               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64));
+               particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0);
 }
 
 void R_Flames (vec3_t org, vec3_t vel, int count)
@@ -790,7 +823,7 @@ void R_Flames (vec3_t org, vec3_t vel, int count)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        while (count--)
-               particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128));
+               particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0);
 }
 
 
@@ -819,8 +852,7 @@ void R_LavaSplash (vec3_t origin)
                        org[1] = origin[1] + dir[1];
                        org[2] = origin[2] + lhrandom(0, 64);
                        vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
-                       particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel);
-//                     particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, origin[0] + i, origin[1] + j, origin[2] + lhrandom(0, 63), i * lhrandom(0.125, 0.25), j * lhrandom(0.125, 0.25), lhrandom(64, 128));
+                       particle(pt_lavasplash, particlepalette[224 + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
                }
        }
 }
@@ -839,7 +871,7 @@ void R_TeleportSplash (vec3_t org)
        for (i=-16 ; i<16 ; i+=8)
                for (j=-16 ; j<16 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
-                               particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5));
+                               particle(pt_fade, 0xFFFFFF, particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f);
 }
 
 void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
@@ -854,9 +886,9 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        VectorNormalize(dir);
 
        if (type == 0 && host_frametime != 0) // rocket glow
-               particle(pt_oneframe, 254, rocketglowparticletexture, TPOLYTYPE_ADD, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0);
+               particle(pt_oneframe, 0xFFFFFF, rocketglowparticletexture, TPOLYTYPE_ALPHA, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
-       t = ent->render.trail_time;
+       t = ent->persistent.trail_time;
        if (t >= cl.time)
                return; // no particles to spawn this frame (sparse trail)
 
@@ -868,7 +900,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        if (len <= 0.01f)
        {
                // advance the trail time
-               ent->render.trail_time = cl.time;
+               ent->persistent.trail_time = cl.time;
                return;
        }
        speed = len / (cl.time - cl.oldtime);
@@ -883,7 +915,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
        {
                // advance the trail time
-               ent->render.trail_time = cl.time;
+               ent->persistent.trail_time = cl.time;
                return;
        }
 
@@ -902,19 +934,19 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                        dec = cl.time - t;
                                else if (bubbles && r_particles_bubbles.value)
                                {
-                                       dec = 0.01f;
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
-                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                                       dec = 0.005f;
+                                       particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                else
                                {
-                                       dec = 0.01f;
-                                       particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
-//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-//                                     particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
+                                       dec = 0.005f;
+                                       particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
                                }
                                break;
 
@@ -925,14 +957,14 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else if (bubbles && r_particles_bubbles.value)
                                {
                                        dec = 0.02f;
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
-                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
-                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                                       particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                else
                                {
                                        dec = 0.02f;
-                                       particle(pt_smoke, 8, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                                       particle(pt_smoke, 0x808080, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                break;
 
@@ -942,8 +974,8 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                        dec = cl.time - t;
                                else
                                {
-                                       dec = 0.2f;
-                                       particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                                       dec = 0.1f;
+                                       particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                                }
                                break;
 
@@ -952,24 +984,24 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                        dec = cl.time - t;
                                else
                                {
-                                       dec = 0.3f;
-                                       particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                                       dec = 0.15f;
+                                       particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                                }
                                break;
 
                        case 3: // green tracer
                                dec = 0.02f;
-                               particle(pt_fade,  56, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                               particle(pt_fade, 0x373707, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 5: // flame tracer
                                dec = 0.02f;
-                               particle(pt_fade, 234, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                               particle(pt_fade, 0xCF632B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 6: // voor trail
                                dec = 0.05f; // sparse trail
-                               particle(pt_fade, 152 + (rand()&3), smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                               particle(pt_fade, 0x47232B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 7: // Nehahra smoke tracer
@@ -978,7 +1010,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else
                                {
                                        dec = 0.14f;
-                                       particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+                                       particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                break;
                }
@@ -988,7 +1020,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                dec *= speed;
                VectorMA (start, dec, vec, start);
        }
-       ent->render.trail_time = t;
+       ent->persistent.trail_time = t;
 }
 
 void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
@@ -1001,9 +1033,10 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        VectorSubtract (end, start, vec);
        len = (int) (VectorNormalizeLength (vec) * (1.0f / 3.0f));
        VectorScale(vec, 3, vec);
+       color = particlepalette[color];
        while (len--)
        {
-               particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+               particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                VectorAdd (start, vec, start);
        }
 }
@@ -1017,9 +1050,9 @@ R_DrawParticles
 void R_MoveParticles (void)
 {
        particle_t              *p;
-       int                             i, activeparticles, maxparticle, j, a;
-       vec3_t                  v;
-       float                   gravity, dvel, frametime;
+       int                             i, activeparticles, maxparticle, j, a, b, pressureused = false;
+       vec3_t                  v, org, o, normal;
+       float                   gravity, dvel, frametime, f;
 
        // LordHavoc: early out condition
        if (!numparticles)
@@ -1043,44 +1076,37 @@ void R_MoveParticles (void)
                }
 
                VectorCopy(p->org, p->oldorg);
-               p->org[0] += p->vel[0]*frametime;
-               p->org[1] += p->vel[1]*frametime;
-               p->org[2] += p->vel[2]*frametime;
+               VectorMA(p->org, frametime, p->vel, p->org);
+               if (p->friction)
+               {
+                       f = 1.0f - (p->friction * frametime);
+                       VectorScale(p->vel, f, p->vel);
+               }
+               VectorCopy(p->org, org);
                if (p->bounce)
                {
                        vec3_t normal;
                        float dist;
-                       if (TraceLine(p->oldorg, p->org, v, normal) < 1)
+                       if (TraceLine(p->oldorg, p->org, v, normal, 0) < 1)
                        {
                                VectorCopy(v, p->org);
                                if (p->bounce < 0)
                                {
-                                       byte *color24 = (byte *) &d_8to24table[(int)p->color];
-                                       R_Decal(v, p->tex, p->scale, color24[0], color24[1], color24[2], p->alpha);
+                                       R_Decal(v, particlefonttexture, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2, p->scale, p->color[0], p->color[1], p->color[2], p->alpha);
                                        p->die = -1;
                                        freeparticles[j++] = p;
                                        continue;
-                                       /*
-                                       VectorClear(p->vel);
-                                       p->type = pt_decal;
-                                       // have to negate the direction (why?)
-                                       VectorNegate(normal, p->direction);
-                                       VectorVectors(p->direction, p->decalright, p->decalup);
-                                       VectorSubtract(p->org, p->direction, p->org); // push off the surface a bit so it doesn't flicker
-                                       p->bounce = 0;
-                                       p->time2 = cl.time + 30;
-                                       */
                                }
                                else
                                {
                                        dist = DotProduct(p->vel, normal) * -p->bounce;
-                                       VectorMAQuick(p->vel, dist, normal, p->vel);
+                                       VectorMA(p->vel, dist, normal, p->vel);
                                        if (DotProduct(p->vel, p->vel) < 0.03)
                                                VectorClear(p->vel);
                                }
                        }
                }
-               
+
                switch (p->type)
                {
                case pt_static:
@@ -1100,9 +1126,6 @@ void R_MoveParticles (void)
                case pt_grav:
                        p->vel[2] -= gravity;
                        break;
-               case pt_slowgrav:
-                       p->vel[2] -= gravity * 0.05;
-                       break;
                case pt_lavasplash:
                        p->vel[2] -= gravity * 0.05;
                        p->alpha -= frametime * 192;
@@ -1129,23 +1152,23 @@ void R_MoveParticles (void)
                                {
                                case CONTENTS_LAVA:
                                case CONTENTS_SLIME:
-                                       p->tex = smokeparticletexture[rand()&7];
+                                       p->tex = &smokeparticletexture[rand()&7];
                                        p->type = pt_steam;
                                        p->alpha = 96;
                                        p->scale = 5;
                                        p->vel[2] = 96;
                                        break;
                                case CONTENTS_WATER:
-                                       p->tex = smokeparticletexture[rand()&7];
+                                       p->tex = &smokeparticletexture[rand()&7];
                                        p->type = pt_splash;
                                        p->alpha = 96;
                                        p->scale = 5;
                                        p->vel[2] = 96;
                                        break;
                                default: // CONTENTS_SOLID and any others
-                                       TraceLine(p->oldorg, p->org, v, normal);
+                                       TraceLine(p->oldorg, p->org, v, normal, 0);
                                        VectorCopy(v, p->org);
-                                       p->tex = smokeparticletexture[rand()&7];
+                                       p->tex = &smokeparticletexture[rand()&7];
                                        p->type = pt_fade;
                                        VectorClear(p->vel);
                                        break;
@@ -1153,16 +1176,57 @@ void R_MoveParticles (void)
                        }
                        break;
                case pt_blood:
-                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                       p->friction = 1;
+                       a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+                       if (a != CONTENTS_EMPTY)
                        {
-                               p->die = -1;
-                               break;
+                               if (a == CONTENTS_WATER || a == CONTENTS_SLIME)
+                               {
+                                       p->friction = 5;
+                                       p->scale += frametime * 32.0f;
+                                       p->alpha -= frametime * 128.0f;
+                                       p->vel[2] += gravity * 0.125f;
+                                       if (p->alpha < 1)
+                                               p->die = -1;
+                                       break;
+                               }
+                               else
+                               {
+                                       p->die = -1;
+                                       break;
+                               }
                        }
                        p->vel[2] -= gravity * 0.5;
                        break;
                case pt_spark:
-                       p->alpha -= frametime * 512;
+                       p->alpha -= frametime * p->time2;
                        p->vel[2] -= gravity;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       else if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                               p->type = pt_underwaterspark;
+                       break;
+               case pt_underwaterspark:
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+                       {
+                               p->tex = &smokeparticletexture[rand()&7];
+                               p->color[0] = p->color[1] = p->color[2] = 255;
+                               p->scale = 16;
+                               p->type = pt_explosionsplash;
+                       }
+                       else
+                               p->vel[2] += gravity * 0.5f;
+                       p->alpha -= frametime * p->time2;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
+               case pt_explosionsplash:
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+                               p->vel[2] -= gravity;
+                       else
+                               p->alpha = 0;
+                       p->scale += frametime * 64.0f;
+                       p->alpha -= frametime * 1024.0f;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
@@ -1175,7 +1239,7 @@ void R_MoveParticles (void)
                        a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
                        if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
                        {
-                               p->tex = smokeparticletexture[rand()&7];
+                               p->tex = &smokeparticletexture[rand()&7];
                                p->type = pt_splashpuff;
                                p->scale = 4;
                                p->vel[0] = p->vel[1] = p->vel[2] = 0;
@@ -1199,14 +1263,14 @@ void R_MoveParticles (void)
                case pt_bulletsmoke:
                        p->scale += frametime * 16;
                        p->alpha -= frametime * 1024;
-                       p->vel[2] += gravity * 0.05;
+                       p->vel[2] += gravity * 0.1;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_smoke:
-                       p->scale += frametime * 32;
-                       p->alpha -= frametime * 512;
-                       p->vel[2] += gravity * 0.05;
+                       p->scale += frametime * 24;
+                       p->alpha -= frametime * 256;
+                       p->vel[2] += gravity * 0.1;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
@@ -1218,97 +1282,60 @@ void R_MoveParticles (void)
                                p->die = -1;
                        break;
                case pt_splashpuff:
-//                     p->scale += frametime * 24;
                        p->alpha -= frametime * 1024;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_rain:
-                       a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
-                       if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
+                       f = 0;
+                       b = Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents;
+                       VectorCopy(p->oldorg, o);
+                       while (f < 1)
                        {
-                               vec3_t normal;
-                               if (a == CONTENTS_SOLID && Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents == CONTENTS_SOLID)
-                                       break; // still in solid
-                               p->die = cl.time + 1000;
-                               p->vel[0] = p->vel[1] = p->vel[2] = 0;
-                               switch (a)
+                               a = b;
+                               f = TraceLine(o, p->org, v, normal, a);
+                               b = traceline_endcontents;
+                               if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY)
                                {
-                               case CONTENTS_LAVA:
-                               case CONTENTS_SLIME:
-                                       p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_steam;
-                                       p->scale = 3;
-                                       p->vel[2] = 96;
-                                       break;
-                               case CONTENTS_WATER:
-                                       p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_splashpuff;
-                                       p->scale = 4;
-                                       break;
-                               default: // CONTENTS_SOLID and any others
-                                       TraceLine(p->oldorg, p->org, v, normal);
+                                       p->die = cl.time + 1000;
+                                       p->vel[0] = p->vel[1] = p->vel[2] = 0;
                                        VectorCopy(v, p->org);
-                                       p->tex = smokeparticletexture[rand()&7];
-                                       p->type = pt_splashpuff;
-                                       p->scale = 4;
-                                       break;
+                                       switch (b)
+                                       {
+                                       case CONTENTS_LAVA:
+                                       case CONTENTS_SLIME:
+                                               p->tex = &smokeparticletexture[rand()&7];
+                                               p->type = pt_steam;
+                                               p->scale = 3;
+                                               p->vel[2] = 96;
+                                               break;
+                                       default: // water, solid, and anything else
+                                               p->tex = &raindropsplashparticletexture[0];
+                                               p->time2 = 0;
+                                               VectorCopy(normal, p->vel2);
+                                       //      VectorAdd(p->org, normal, p->org);
+                                               p->type = pt_raindropsplash;
+                                               p->scale = 8;
+                                               break;
+                                       }
                                }
                        }
                        break;
-               case pt_flame:
-                       p->alpha -= frametime * 512;
-                       p->vel[2] += gravity;
-//                     p->scale -= frametime * 16;
-                       if (p->alpha < 16)
-                               p->die = -1;
-                       break;
-                       /*
-               case pt_flamingdebris:
-                       if (cl.time >= p->time2)
+               case pt_raindropsplash:
+                       p->time2 += frametime * 64.0f;
+                       if (p->time2 >= 16.0f)
                        {
-                               p->time2 = cl.time + 0.01;
-                               particle(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
-                       }
-                       p->alpha -= frametime * 512;
-                       p->vel[2] -= gravity * 0.5f;
-                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
-                               p->die = -1;
-                       if (p->alpha < 1)
                                p->die = -1;
-                       break;
-               case pt_smokingdebris:
-                       if (cl.time >= p->time2)
-                       {
-                               p->time2 = cl.time + 0.01;
-                               particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
+                               break;
                        }
-                       p->alpha -= frametime * 512;
-                       p->vel[2] -= gravity * 0.5f;
-                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
-                               p->die = -1;
-                       if (p->alpha < 1)
-                               p->die = -1;
+                       p->tex = &raindropsplashparticletexture[(int) p->time2];
                        break;
-               case pt_flamefall:
+               case pt_flame:
                        p->alpha -= frametime * 512;
-                       p->vel[2] -= gravity * 0.5f;
-                       if (p->alpha < 1)
-                               p->die = -1;
-                       break;
-                       */
-                       /*
-               case pt_decal:
-                       if (cl.time > p->time2)
-                       {
-                               p->alpha -= frametime * 256;
-                               if (p->alpha < 1)
-                                       p->die = -1;
-                       }
-                       if (p->alpha < 64)
+                       p->vel[2] += gravity;
+                       if (p->alpha < 16)
                                p->die = -1;
                        break;
-                       */
                case pt_oneframe:
                        if (p->time2)
                                p->die = -1;
@@ -1327,6 +1354,8 @@ void R_MoveParticles (void)
                {
                        maxparticle = i;
                        activeparticles++;
+                       if (p->pressure)
+                               pressureused = true;
                }
        }
        // fill in gaps to compact the array
@@ -1338,17 +1367,46 @@ void R_MoveParticles (void)
                        maxparticle--;
        }
        numparticles = activeparticles;
+
+       if (pressureused)
+       {
+               activeparticles = 0;
+               for (i = 0, p = particles;i < numparticles;i++, p++)
+                       if (p->pressure)
+                               freeparticles[activeparticles++] = p;
+
+               if (activeparticles)
+               {
+                       for (i = 0, p = particles;i < numparticles;i++, p++)
+                       {
+                               for (j = 0;j < activeparticles;j++)
+                               {
+                                       if (freeparticles[j] != p)
+                                       {
+                                               float dist, diff[3];
+                                               VectorSubtract(p->org, freeparticles[j]->org, diff);
+                                               dist = DotProduct(diff, diff);
+                                               if (dist < 4096 && dist >= 1)
+                                               {
+                                                       dist = freeparticles[j]->scale * 4.0f * frametime / sqrt(dist);
+                                                       VectorMA(p->vel, dist, diff, p->vel);
+                                                       //dist = freeparticles[j]->scale * 4.0f * frametime / dist;
+                                                       //VectorMA(p->vel, dist, freeparticles[j]->vel, p->vel);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
 }
 
 void R_DrawParticles (void)
 {
        particle_t              *p;
-       int                             i, dynamiclight, staticlight, r, g, b;
-       byte                    br, bg, bb, ba;
-       float                   scale, scale2, minparticledist;
-       byte                    *color24;
-       vec3_t                  uprightangles, up2, right2, tempcolor, corner;
-//     mleaf_t                 *leaf;
+       int                             i, dynamiclight, staticlight, r, g, b, texnum;
+       float                   minparticledist;
+       vec3_t                  uprightangles, up2, right2, v, right, up;
+       mleaf_t                 *leaf;
 
        // LordHavoc: early out condition
        if ((!numparticles) || (!r_drawparticles.value))
@@ -1366,78 +1424,55 @@ void R_DrawParticles (void)
 
        minparticledist = DotProduct(r_origin, vpn) + 16.0f;
 
+       texnum = R_GetTexture(particlefonttexture);
        for (i = 0, p = particles;i < numparticles;i++, p++)
        {
-               // LordHavoc: unnecessary (array was already compacted)
-//             if (p->die < cl.time)
-//                     continue;
+               if (p->tex == NULL || p->alpha < 1 || p->scale < 0.1f)
+                       continue;
 
                // LordHavoc: only render if not too close
                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)
-               {
-                       VectorSubtract(p->org, r_origin, v);
-                       if (DotProduct(p->direction, v) < 0)
-                               continue;
-               }
-               */
+               leaf = leaf = Mod_PointInLeaf(p->org, cl.worldmodel);
+               if (leaf->visframe != r_framecount)
+                       continue;
 
-               color24 = (byte *) &d_8to24table[(int)p->color];
-               r = color24[0];
-               g = color24[1];
-               b = color24[2];
+               r = p->color[0];
+               g = p->color[1];
+               b = p->color[2];
                if (staticlight && (p->dynlight || staticlight >= 2)) // LordHavoc: only light blood and smoke
                {
-                       R_CompleteLightPoint(tempcolor, p->org, dynamiclight);
-                       r = (r * (int) tempcolor[0]) >> 7;
-                       g = (g * (int) tempcolor[1]) >> 7;
-                       b = (b * (int) tempcolor[2]) >> 7;
+                       R_CompleteLightPoint(v, p->org, dynamiclight, leaf);
+#if SLOWMATH
+                       r = (r * (int) v[0]) >> 7;
+                       g = (g * (int) v[1]) >> 7;
+                       b = (b * (int) v[2]) >> 7;
+#else
+                       v[0] += 8388608.0f;
+                       v[1] += 8388608.0f;
+                       v[2] += 8388608.0f;
+                       r = (r * (*((long *) &v[0]) & 0x7FFFFF)) >> 7;
+                       g = (g * (*((long *) &v[1]) & 0x7FFFFF)) >> 7;
+                       b = (b * (*((long *) &v[2]) & 0x7FFFFF)) >> 7;
+#endif
                }
-               br = (byte) min(r, 255);
-               bg = (byte) min(g, 255);
-               bb = (byte) min(b, 255);
-               ba = (byte) p->alpha;
-               transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), p->rendermode);
-               scale = p->scale * -0.5;scale2 = p->scale;
-               /*
-               if (p->type == pt_decal)
+               if (p->type == pt_raindropsplash)
                {
-                       corner[0] = p->org[0] + p->decalup[0]*scale + p->decalright[0]*scale;
-                       corner[1] = p->org[1] + p->decalup[1]*scale + p->decalright[1]*scale;
-                       corner[2] = p->org[2] + p->decalup[2]*scale + p->decalright[2]*scale;
-                       transpolyvertub(corner[0]                                                 , corner[1]                                                 , corner[2]                                                 , 0,1,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + p->decalup[0]*scale2                          , corner[1] + p->decalup[1]*scale2                          , corner[2] + p->decalup[2]*scale2                          , 0,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + p->decalup[0]*scale2 + p->decalright[0]*scale2, corner[1] + p->decalup[1]*scale2 + p->decalright[1]*scale2, corner[2] + p->decalup[2]*scale2 + p->decalright[2]*scale2, 1,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0]                        + p->decalright[0]*scale2, corner[1]                        + p->decalright[1]*scale2, corner[2]                        + p->decalright[2]*scale2, 1,1,br,bg,bb,ba);
-               }
-               else*/ if (p->tex == rainparticletexture) // rain streak
-               {
-                       corner[0] = p->org[0] + up2[0]*scale + right2[0]*scale;
-                       corner[1] = p->org[1] + up2[1]*scale + right2[1]*scale;
-                       corner[2] = p->org[2] + up2[2]*scale + right2[2]*scale;
-                       transpolyvertub(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + up2[0]*scale2                   , corner[1] + up2[1]*scale2                   , corner[2] + up2[2]*scale2                   , 0,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + up2[0]*scale2 + right2[0]*scale2, corner[1] + up2[1]*scale2 + right2[1]*scale2, corner[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0]                 + right2[0]*scale2, corner[1]                 + right2[1]*scale2, corner[2]                 + right2[2]*scale2, 1,1,br,bg,bb,ba);
+                       // treat as double-sided
+                       if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, p->org))
+                       {
+                               VectorNegate(p->vel2, v);
+                               VectorVectors(v, right, up);
+                       }
+                       else
+                               VectorVectors(p->vel2, right, up);
+                       transpolyparticle(p->org, right, up, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
                }
+               else if (p->tex == &rainparticletexture) // rain streak
+                       transpolyparticle(p->org, right2, up2, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
                else
-               {
-                       corner[0] = p->org[0] + vup[0]*scale + vright[0]*scale;
-                       corner[1] = p->org[1] + vup[1]*scale + vright[1]*scale;
-                       corner[2] = p->org[2] + vup[2]*scale + vright[2]*scale;
-                       transpolyvertub(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + vup[0]*scale2                   , corner[1] + vup[1]*scale2                   , corner[2] + vup[2]*scale2                   , 0,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0] + vup[0]*scale2 + vright[0]*scale2, corner[1] + vup[1]*scale2 + vright[1]*scale2, corner[2] + vup[2]*scale2 + vright[2]*scale2, 1,0,br,bg,bb,ba);
-                       transpolyvertub(corner[0]                 + vright[0]*scale2, corner[1]                 + vright[1]*scale2, corner[2]                 + vright[2]*scale2, 1,1,br,bg,bb,ba);
-               }
-               transpolyend();
+                       transpolyparticle(p->org, vright, vup, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
        }
 }
index e7f561179493f4903c9ab1d5bd13e1808995af2d..f9b43eadd4b6f32b9d0a6bca91b9eb18b7b36e2a 100644 (file)
@@ -1,19 +1,19 @@
 #include "quakedef.h"
 
-void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, vec3_t origin, vec3_t up, vec3_t right)
+void R_ClipSpriteImage (msprite_t *psprite, vec3_t origin, vec3_t right, vec3_t up)
 {
        int i;
        mspriteframe_t *frame;
        vec3_t points[4];
        float fleft, fright, fdown, fup;
-       frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame;
+       frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[0].frame;
        fleft  = frame->left;
        fdown  = frame->down;
        fright = frame->right;
        fup    = frame->up;
-       for (i = 1;i < 4 && blend[i].lerp;i++)
+       for (i = 1;i < 4 && currentrenderentity->frameblend[i].lerp;i++)
        {
-               frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[i].frame;
+               frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame;
                fleft  = min(fleft , frame->left );
                fdown  = min(fdown , frame->down );
                fright = max(fright, frame->right);
@@ -23,56 +23,97 @@ void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, ve
        points[1][0] = origin[0] + fup   * up[0] + fleft  * right[0];points[1][1] = origin[1] + fup   * up[1] + fleft  * right[1];points[1][2] = origin[2] + fup   * up[2] + fleft  * right[2];
        points[2][0] = origin[0] + fup   * up[0] + fright * right[0];points[2][1] = origin[1] + fup   * up[1] + fright * right[1];points[2][2] = origin[2] + fup   * up[2] + fright * right[2];
        points[3][0] = origin[0] + fdown * up[0] + fright * right[0];points[3][1] = origin[1] + fdown * up[1] + fright * right[1];points[3][2] = origin[2] + fdown * up[2] + fright * right[2];
-       R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, e, NULL, NULL);
+       R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, currentrenderentity, NULL, NULL);
 }
 
-void R_ClipSprite (entity_t *e, frameblend_t *blend)
+int R_SpriteSetup (int type, float org[3], float right[3], float up[3])
 {
-       vec3_t forward, right, up, org;
-       msprite_t *psprite;
-
-       if (!blend[0].lerp)
-               return;
-
-       psprite = Mod_Extradata(e->render.model);
+       float matrix1[3][3], matrix2[3][3], matrix3[3][3];
 
-       if (psprite->type == SPR_ORIENTED)
+       VectorCopy(currentrenderentity->origin, org);
+       switch(type)
        {
+       case SPR_VP_PARALLEL_UPRIGHT:
+               // flames and such
+               // vertical beam sprite, faces view plane
+               VectorNegate(vpn, matrix3[0]);
+               matrix3[0][2] = 0;
+               VectorNormalizeFast(matrix3[0]);
+               VectorVectors(matrix3[0], matrix3[1], matrix3[2]);
+               break;
+       case SPR_FACING_UPRIGHT:
+               // flames and such
+               // vertical beam sprite, faces viewer's origin (not the view plane)
+               VectorSubtract(r_origin, currentrenderentity->origin, matrix3[0]);
+               matrix3[0][2] = 0;
+               VectorNormalizeFast(matrix3[0]);
+               VectorVectors(matrix3[0], matrix3[1], matrix3[2]);
+               break;
+       default:
+               Con_Printf("R_SpriteSetup: unknown sprite type %i\n", type);
+               // fall through to normal sprite
+       case SPR_VP_PARALLEL:
+               // normal sprite
+               // faces view plane
+               VectorCopy(vpn, matrix3[0]);
+               VectorCopy(vright, matrix3[1]);
+               VectorCopy(vup, matrix3[2]);
+               break;
+       case SPR_ORIENTED:
                // bullet marks on walls
-               AngleVectors (e->render.angles, forward, right, up);
+               // ignores viewer entirely
+               AngleVectors (currentrenderentity->angles, matrix3[0], matrix3[1], matrix3[2]);
                // nudge it toward the view, so it will be infront of the wall
-               VectorSubtract(e->render.origin, vpn, org);
-               // don't draw if it's a backface
-               if (DotProduct(r_origin, forward) > (DotProduct(org, forward) - 1.0f))
-                       return;
-       }
-       else
-       {
-               // normal sprite
-               VectorCopy(vup, up);
-               VectorCopy(vright, right);
-               VectorCopy(e->render.origin, org);
-               // don't draw if it's a backface
-               if (DotProduct(org, vpn) < (DotProduct(r_origin, vpn) + 1.0f))
-                       return;
+               VectorSubtract(org, vpn, org);
+               break;
+       case SPR_VP_PARALLEL_ORIENTED:
+               // I have no idea what people would use this for
+               // oriented relative to view space
+               // FIXME: test this and make sure it mimicks software
+               AngleVectors (currentrenderentity->angles, matrix1[0], matrix1[1], matrix1[2]);
+               VectorCopy(vpn, matrix2[0]);
+               VectorCopy(vright, matrix2[1]);
+               VectorCopy(vup, matrix2[2]);
+               R_ConcatRotations (matrix1, matrix2, matrix3);
+               break;
        }
 
+       // don't draw if view origin is behind it
+       if (DotProduct(org, matrix3[0]) < (DotProduct(r_origin, matrix3[0]) - 1.0f))
+               return true;
 
-       if (e->render.scale != 1)
+       if (currentrenderentity->scale != 1)
        {
-               VectorScale(up, e->render.scale, up);
-               VectorScale(right, e->render.scale, right);
+               VectorScale(matrix3[1], currentrenderentity->scale, matrix3[1]);
+               VectorScale(matrix3[2], currentrenderentity->scale, matrix3[2]);
        }
 
+       VectorCopy(matrix3[1], right);
+       VectorCopy(matrix3[2], up);
+       return false;
+}
+
+void R_ClipSprite (void)
+{
+       vec3_t org, right, up;
+       msprite_t *psprite;
+
+       if (currentrenderentity->frameblend[0].frame < 0)
+               return;
+
+       psprite = Mod_Extradata(currentrenderentity->model);
+       if (R_SpriteSetup(psprite->type, org, right, up))
+               return;
+
        // LordHavoc: interpolated sprite rendering
-       R_ClipSpriteImage(e, psprite, blend, org, up, right);
+       R_ClipSpriteImage(psprite, org, right, up);
 }
 
 void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha)
 {
        byte alphaub;
        alphaub = bound(0, alpha, 255);
-       transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currententity->render.effects & EF_ADDITIVE) || (currententity->render.model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+       transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currentrenderentity->effects & EF_ADDITIVE) || (currentrenderentity->model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
        transpolyvertub(origin[0] + frame->down * up[0] + frame->left  * right[0], origin[1] + frame->down * up[1] + frame->left  * right[1], origin[2] + frame->down * up[2] + frame->left  * right[2], 0, 1, red, green, blue, alphaub);
        transpolyvertub(origin[0] + frame->up   * up[0] + frame->left  * right[0], origin[1] + frame->up   * up[1] + frame->left  * right[1], origin[2] + frame->up   * up[2] + frame->left  * right[2], 0, 0, red, green, blue, alphaub);
        transpolyvertub(origin[0] + frame->up   * up[0] + frame->right * right[0], origin[1] + frame->up   * up[1] + frame->right * right[1], origin[2] + frame->up   * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
@@ -85,67 +126,38 @@ void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t
 R_DrawSpriteModel
 =================
 */
-void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
+void R_DrawSpriteModel ()
 {
-       vec3_t          forward, right, up, org, color, mins, maxs;
+       int                     i;
+       vec3_t          right, up, org, color;
        byte            colorub[4];
        msprite_t       *psprite;
 
-       if (!blend[0].lerp)
+       if (currentrenderentity->frameblend[0].frame < 0)
                return;
 
-       VectorAdd (e->render.origin, e->render.model->mins, mins);
-       VectorAdd (e->render.origin, e->render.model->maxs, maxs);
-
-//     if (R_CullBox (mins, maxs))
-//             return;
+       psprite = Mod_Extradata(currentrenderentity->model);
+       if (R_SpriteSetup(psprite->type, org, right, up))
+               return;
 
        c_sprites++;
 
-       psprite = Mod_Extradata(e->render.model);
-       //psprite = e->model->cache.data;
-
-       if (psprite->type == SPR_ORIENTED)
-       {
-               // bullet marks on walls
-               AngleVectors (e->render.angles, forward, right, up);
-               VectorSubtract(e->render.origin, vpn, org);
-       }
-       else
-       {
-               // normal sprite
-               VectorCopy(vup, up);
-               VectorCopy(vright, right);
-               VectorCopy(e->render.origin, org);
-       }
-
-       if (e->render.scale != 1)
-       {
-               VectorScale(up, e->render.scale, up);
-               VectorScale(right, e->render.scale, right);
-       }
-
-       if (e->render.model->flags & EF_FULLBRIGHT || e->render.effects & EF_FULLBRIGHT)
+       if ((currentrenderentity->model->flags & EF_FULLBRIGHT) || (currentrenderentity->effects & EF_FULLBRIGHT))
        {
-               color[0] = e->render.colormod[0] * 255;
-               color[1] = e->render.colormod[1] * 255;
-               color[2] = e->render.colormod[2] * 255;
+               color[0] = currentrenderentity->colormod[0] * 255;
+               color[1] = currentrenderentity->colormod[1] * 255;
+               color[2] = currentrenderentity->colormod[2] * 255;
        }
        else
-               R_CompleteLightPoint(color, e->render.origin, true);
+               R_CompleteLightPoint(color, currentrenderentity->origin, true, NULL);
 
        colorub[0] = bound(0, color[0], 255);
        colorub[1] = bound(0, color[1], 255);
        colorub[2] = bound(0, color[2], 255);
 
        // LordHavoc: interpolated sprite rendering
-       if (blend[0].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[0].lerp);
-       if (blend[1].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[1].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[1].lerp);
-       if (blend[2].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[2].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[2].lerp);
-       if (blend[3].lerp)
-               GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[3].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[3].lerp);
+       for (i = 0;i < 4;i++)
+               if (currentrenderentity->frameblend[i].lerp)
+                       GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame, org, up, right, colorub[0],colorub[1],colorub[2], currentrenderentity->alpha*255*currentrenderentity->frameblend[i].lerp);
 }
 
index 9d1fb636a633c389f516da7895399f607596c9da..7950e9f6e35a4e6954771c724868c79fe7991fb8 100644 (file)
--- a/render.h
+++ b/render.h
@@ -48,7 +48,6 @@ extern float lightscale;
 extern float *aliasvert;
 extern float *aliasvertnorm;
 extern byte *aliasvertcolor;
-extern float modelalpha;
 
 // vis stuff
 extern cvar_t r_novis;
@@ -64,67 +63,121 @@ extern float ixtable[4096];
 
 //=============================================================================
 
-typedef struct entity_render_s
+typedef struct frameblend_s
 {
-       vec3_t  origin;
-       vec3_t  angles;
+       int frame;
+       float lerp;
+}
+frameblend_t;
 
-       int             visframe;               // last frame this entity was found in an active leaf
+// LordHavoc: nothing in this structure is persistant, it may be overwritten by the client every frame, for persistant data use entity_lerp_t.
+typedef struct entity_render_s
+{
+       vec3_t  origin;                 // location
+       vec3_t  angles;                 // orientation
+       float   colormod[3];    // color tint for model
+       float   alpha;                  // opacity (alpha) of the model
+       float   scale;                  // size the model is shown
 
        model_t *model;                 // NULL = no model
-       int             frame;                  // current desired frame (usually identical to frame2, but frame2 is not always used)
+       int             frame;                  // current uninterpolated animation frame (for things which do not use interpolation)
        int             colormap;               // entity shirt and pants colors
        int             effects;                // light, particles, etc
        int             skinnum;                // for Alias models
        int             flags;                  // render flags
 
-       float   alpha;                  // opacity (alpha) of the model
-       float   scale;                  // size the model is shown
-       float   trail_time;             // last time for trail rendering
-       float   colormod[3];    // color tint for model
-
-       model_t *lerp_model;    // lerp resets when model changes
+       // these are copied from the persistent data
        int             frame1;                 // frame that the model is interpolating from
        int             frame2;                 // frame that the model is interpolating to
-       double  lerp_starttime; // start of this transition
-       double  framelerp;              // interpolation factor, usually computed from lerp_starttime
-       double  frame1start;    // time frame1 began playing (for framegroup animations)
-       double  frame2start;    // time frame2 began playing (for framegroup animations)
+       double  framelerp;              // interpolation factor, usually computed from frame2time
+       double  frame1time;             // time frame1 began playing (for framegroup animations)
+       double  frame2time;             // time frame2 began playing (for framegroup animations)
+
+       // calculated by the renderer (but not persistent)
+       int             visframe;               // if visframe == r_framecount, it is visible
+       vec3_t  mins, maxs;             // calculated during R_AddModelEntities
+       frameblend_t    frameblend[4]; // 4 frame numbers (-1 if not used) and their blending scalers (0-1), if interpolation is not desired, use frame instead
 }
 entity_render_t;
 
+typedef struct entity_persistent_s
+{
+       // particles
+       vec3_t  trail_origin;   // trail rendering
+       float   trail_time;             // trail rendering
+
+       // interpolated animation
+       int             modelindex;             // lerp resets when model changes
+       int             frame1;                 // frame that the model is interpolating from
+       int             frame2;                 // frame that the model is interpolating to
+       double  framelerp;              // interpolation factor, usually computed from frame2time
+       double  frame1time;             // time frame1 began playing (for framegroup animations)
+       double  frame2time;             // time frame2 began playing (for framegroup animations)
+}
+entity_persistent_t;
+
 typedef struct entity_s
 {
-       entity_state_t state_baseline;  // baseline for entity
+       entity_state_t state_baseline;  // baseline state (default values)
        entity_state_t state_previous;  // previous state (interpolating from this)
        entity_state_t state_current;   // current state (interpolating to this)
 
-       entity_render_t render;
-} entity_t;
+       entity_persistent_t persistent; // used for regenerating parts of render
+
+       entity_render_t render; // the only data the renderer should know about
+}
+entity_t;
 
 typedef struct
 {
-       vrect_t         vrect;                          // subwindow in video for refresh
+       // area to render in
+       int             x, y, width, height;
+       float   fov_x, fov_y;
 
-       vec3_t          vieworg;
-       vec3_t          viewangles;
+       // view point
+       vec3_t  vieworg;
+       vec3_t  viewangles;
+}
+refdef_t;
 
-       float           fov_x, fov_y;
-} refdef_t;
+extern qboolean hlbsp;
+//extern       qboolean        r_cache_thrash;         // compatability
+extern vec3_t          modelorg;
+extern entity_render_t *currentrenderentity;
+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;
 
 
 //
-// refresh
+// view origin
 //
+extern vec3_t  vup;
+extern vec3_t  vpn;
+extern vec3_t  vright;
+extern vec3_t  r_origin;
 
-
+//
+// screen size info
+//
 extern refdef_t        r_refdef;
-extern vec3_t  r_origin, vpn, vright, vup;
-extern qboolean hlbsp;
+extern mleaf_t         *r_viewleaf, *r_oldviewleaf;
+extern unsigned short  d_lightstylevalue[256]; // 8.8 fraction of base light value
+
+extern qboolean        envmap;
+
+extern cvar_t  r_drawentities;
+extern cvar_t  r_drawviewmodel;
+extern cvar_t  r_speeds;
+extern cvar_t  r_fullbright;
+extern cvar_t  r_wateralpha;
+extern cvar_t  r_dynamic;
+extern cvar_t  r_waterripple;
+
+//extern       float   r_world_matrix[16];
 
 void R_Init (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
 
 // LordHavoc: changed this for sake of GLQuake
 void R_InitSky (byte *src, int bytesperpixel); // called at level load
@@ -194,14 +247,19 @@ extern qboolean lighthalf;
 void GL_LockArray(int first, int count);
 void GL_UnlockArray(void);
 
-void R_DrawBrushModel (entity_t *e);
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap);
-void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
+void R_DrawBrushModel (void);
+void R_DrawAliasModel (void);
+void R_DrawSpriteModel (void);
 
-void R_ClipSprite (entity_t *e, frameblend_t *blend);
+void R_ClipSprite (void);
 void R_Entity_Callback(void *data, void *junk);
 
 extern cvar_t r_render;
 extern cvar_t r_upload;
 extern cvar_t r_ser;
 #include "image.h"
+
+// if contents is not zero, it will impact on content changes
+// (leafs matching contents are considered empty, others are solid)
+extern int traceline_endcontents; // set by TraceLine
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents);
diff --git a/sbar.c b/sbar.c
index 73e51ca788f97bc38aabc63d90dff25820c0c88e..018cbf9eb3863054860fc3d3aefd2a0dc329cd29 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -182,34 +182,34 @@ void Sbar_Init (void)
        sb_scorebar = Draw_PicFromWad ("scorebar");
 
 //MED 01/04/97 added new hipnotic weapons
-       if (hipnotic)
+       if (gamemode == GAME_HIPNOTIC)
        {
-         hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
-         hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
-         hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
-         hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
-         hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
-
-         hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
-         hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
-         hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
-         hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
-         hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
-
-         for (i=0 ; i<5 ; i++)
-         {
-                hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
-                hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
-                hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
-                hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
-                hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
-         }
-
-         hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
-         hsb_items[1] = Draw_PicFromWad ("sb_eshld");
+               hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
+               hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
+               hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
+               hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
+               hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
+
+               hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
+               hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
+               hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
+               hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
+               hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
+
+               for (i=0 ; i<5 ; i++)
+               {
+                       hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
+                       hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
+                       hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
+                       hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
+                       hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
+               }
+
+               hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
+               hsb_items[1] = Draw_PicFromWad ("sb_eshld");
        }
 
-       if (rogue)
+       else if (gamemode == GAME_ROGUE)
        {
                rsb_invbar[0] = Draw_PicFromWad ("r_invbar1");
                rsb_invbar[1] = Draw_PicFromWad ("r_invbar2");
@@ -221,10 +221,10 @@ void Sbar_Init (void)
                rsb_weapons[4] = Draw_PicFromWad ("r_plasma");
 
                rsb_items[0] = Draw_PicFromWad ("r_shield1");
-        rsb_items[1] = Draw_PicFromWad ("r_agrav1");
+               rsb_items[1] = Draw_PicFromWad ("r_agrav1");
 
 // PGM 01/19/97 - team color border
-        rsb_teambord = Draw_PicFromWad ("r_teambord");
+               rsb_teambord = Draw_PicFromWad ("r_teambord");
 // PGM 01/19/97 - team color border
 
                rsb_ammo[0] = Draw_PicFromWad ("r_ammolava");
@@ -246,18 +246,18 @@ Sbar_DrawPic
 void Sbar_DrawPic (int x, int y, qpic_t *pic)
 {
        if (cl.gametype == GAME_DEATHMATCH)
-               Draw_Pic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
+               Draw_Pic (x, y + (vid.conheight-SBAR_HEIGHT), pic);
        else
-               Draw_Pic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
+               Draw_Pic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic);
 }
 
 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha);
 void Sbar_DrawAlphaPic (int x, int y, qpic_t *pic, float alpha)
 {
        if (cl.gametype == GAME_DEATHMATCH)
-               Draw_AlphaPic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic, alpha);
+               Draw_AlphaPic (x, y + (vid.conheight-SBAR_HEIGHT), pic, alpha);
        else
-               Draw_AlphaPic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic, alpha);
+               Draw_AlphaPic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic, alpha);
 }
 
 /*
@@ -270,9 +270,9 @@ Draws one solid graphics character
 void Sbar_DrawCharacter (int x, int y, int num)
 {
        if (cl.gametype == GAME_DEATHMATCH)
-               Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4 , y + vid.height-SBAR_HEIGHT, num);
+               Draw_Character ( x + 4 , y + vid.conheight-SBAR_HEIGHT, num);
        else
-               Draw_Character ( x + ((vid.width - 320)>>1) + 4 , y + vid.height-SBAR_HEIGHT, num);
+               Draw_Character ( x + ((vid.conwidth - 320)>>1) + 4 , y + vid.conheight-SBAR_HEIGHT, num);
 }
 
 /*
@@ -283,9 +283,9 @@ Sbar_DrawString
 void Sbar_DrawString (int x, int y, char *str)
 {
        if (cl.gametype == GAME_DEATHMATCH)
-               Draw_String (x /*+ ((vid.width - 320)>>1)*/, y+ vid.height-SBAR_HEIGHT, str, 0);
+               Draw_String (x, y+ vid.conheight-SBAR_HEIGHT, str, 0);
        else
-               Draw_String (x + ((vid.width - 320)>>1), y+ vid.height-SBAR_HEIGHT, str, 0);
+               Draw_String (x + ((vid.conwidth - 320)>>1), y+ vid.conheight-SBAR_HEIGHT, str, 0);
 }
 
 /*
@@ -482,7 +482,7 @@ void Sbar_DrawInventory (void)
        float   time;
        int             flashon;
 
-       if (rogue)
+       if (gamemode == GAME_ROGUE)
        {
                if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
                        Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], 0.4);
@@ -515,7 +515,7 @@ void Sbar_DrawInventory (void)
 
        // MED 01/04/97
        // hipnotic weapons
-       if (hipnotic)
+       if (gamemode == GAME_HIPNOTIC)
        {
                int grenadeflashing=0;
                for (i=0 ; i<4 ; i++)
@@ -562,7 +562,7 @@ void Sbar_DrawInventory (void)
                }
        }
 
-       if (rogue)
+       if (gamemode == GAME_ROGUE)
        {
                // check for powered up weapon.
                if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
@@ -583,56 +583,37 @@ void Sbar_DrawInventory (void)
                        Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
        }
 
-       flashon = 0;
        // items
        for (i=0 ; i<6 ; i++)
                if (cl.items & (1<<(17+i)))
                {
-                       time = cl.item_gettime[17+i];
-                       if (time && time > cl.time - 2 && flashon )
-                       {  // flash frame
-                       }
-                       else
                        //MED 01/04/97 changed keys
-                               if (!hipnotic || (i>1))
-                                       Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
+                       if (gamemode != GAME_HIPNOTIC || (i>1))
+                               Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
                }
+
        //MED 01/04/97 added hipnotic items
        // hipnotic items
-       if (hipnotic)
+       if (gamemode == GAME_HIPNOTIC)
        {
                for (i=0 ; i<2 ; i++)
                        if (cl.items & (1<<(24+i)))
-                       {
-                               time = cl.item_gettime[24+i];
-                               if (!time || time <= cl.time - 2 || !flashon)
-                                       Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
-                       }
+                               Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
        }
 
-       if (rogue)
+       if (gamemode == GAME_ROGUE)
        {
                // new rogue items
                for (i=0 ; i<2 ; i++)
                        if (cl.items & (1<<(29+i)))
-                       {
-                               time = cl.item_gettime[29+i];
-                               if (!time || time <= cl.time - 2 || !flashon)
-                                       Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
-                       }
+                               Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
        }
        else
        {
                // sigils
                for (i=0 ; i<4 ; i++)
-               {
                        if (cl.items & (1<<(28+i)))
-                       {
-                               time = cl.item_gettime[28+i];
-                               if (!time || time <= cl.time - 2 || !flashon)
-                                       Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
-                       }
-               }
+                               Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
        }
 }
 
@@ -661,8 +642,8 @@ void Sbar_DrawFrags (void)
        if (cl.gametype == GAME_DEATHMATCH)
                xofs = 0;
        else
-               xofs = (vid.width - 320)>>1;
-       y = vid.height - SBAR_HEIGHT - 23;
+               xofs = (vid.conwidth - 320)>>1;
+       y = vid.conheight - SBAR_HEIGHT - 23;
 
        for (i=0 ; i<l ; i++)
        {
@@ -705,20 +686,17 @@ Sbar_DrawFace
 */
 void Sbar_DrawFace (void)
 {
-       int             f, anim;
+       int f;
 
 // PGM 01/19/97 - team color drawing
 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
-       if (rogue &&
-        (cl.maxclients != 1) &&
-        (teamplay.value>3) &&
-        (teamplay.value<7))
+       if (gamemode == GAME_ROGUE && (cl.maxclients != 1) && (teamplay.value > 3) && (teamplay.value < 7))
        {
                int                             top, bottom;
                int                             xofs;
                char                    num[12];
                scoreboard_t    *s;
-               
+
                s = &cl.scores[cl.viewentity - 1];
                // draw background
                top = (s->colors & 0xf0) + 8;
@@ -727,11 +705,11 @@ void Sbar_DrawFace (void)
                if (cl.gametype == GAME_DEATHMATCH)
                        xofs = 113;
                else
-                       xofs = ((vid.width - 320)>>1) + 113;
+                       xofs = ((vid.conwidth - 320)>>1) + 113;
 
                Sbar_DrawPic (112, 0, rsb_teambord);
-               Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top);
-               Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom);
+               Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+3, 22, 9, top);
+               Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+12, 22, 9, bottom);
 
                // draw number
                f = s->frags;
@@ -752,49 +730,25 @@ void Sbar_DrawFace (void)
                        Sbar_DrawCharacter ( 116, 3, num[1]);
                        Sbar_DrawCharacter ( 123, 3, num[2]);
                }
-               
+
                return;
        }
 // PGM 01/19/97 - team color drawing
 
-       if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) )
-       == (IT_INVISIBILITY | IT_INVULNERABILITY) )
-       {
+       if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
                Sbar_DrawPic (112, 0, sb_face_invis_invuln);
-               return;
-       }
-       if (cl.items & IT_QUAD)
-       {
+       else if (cl.items & IT_QUAD)
                Sbar_DrawPic (112, 0, sb_face_quad );
-               return;
-       }
-       if (cl.items & IT_INVISIBILITY)
-       {
+       else if (cl.items & IT_INVISIBILITY)
                Sbar_DrawPic (112, 0, sb_face_invis );
-               return;
-       }
-       if (cl.items & IT_INVULNERABILITY)
-       {
+       else if (cl.items & IT_INVULNERABILITY)
                Sbar_DrawPic (112, 0, sb_face_invuln);
-               return;
-       }
-
-       if (cl.stats[STAT_HEALTH] >= 100)
-               f = 4;
        else
-               f = cl.stats[STAT_HEALTH] / 20;
-       // LordHavoc: I don't even know how the game didn't crash without this
-       if (f < 0)
-               f = 0;
-
-       if (cl.time <= cl.faceanimtime)
        {
-               anim = 1;
-//             sb_updates = 0;         // make sure the anim gets drawn over
+               f = cl.stats[STAT_HEALTH] / 20;
+               f = bound(0, f, 4);
+               Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
        }
-       else
-               anim = 0;
-       Sbar_DrawPic (112, 0, sb_faces[f][anim]);
 }
 
 /*
@@ -804,11 +758,9 @@ Sbar_Draw
 */
 void Sbar_Draw (void)
 {
-       if (scr_con_current == vid.height)
+       if (scr_con_current == vid.conheight)
                return;         // console is full screen
 
-//     sb_updates++;
-
        if (sb_lines > 24)
        {
                Sbar_DrawInventory ();
@@ -820,22 +772,21 @@ void Sbar_Draw (void)
        {
                Sbar_DrawAlphaPic (0, 0, sb_scorebar, 0.4);
                Sbar_DrawScoreboard ();
-//             sb_updates = 0;
        }
        else if (sb_lines)
        {
                Sbar_DrawAlphaPic (0, 0, sb_sbar, 0.4);
 
-   // keys (hipnotic only)
-      //MED 01/04/97 moved keys here so they would not be overwritten
-      if (hipnotic)
-      {
-         if (cl.items & IT_KEY1)
-            Sbar_DrawPic (209, 3, sb_items[0]);
-         if (cl.items & IT_KEY2)
-            Sbar_DrawPic (209, 12, sb_items[1]);
-      }
-   // armor
+// keys (hipnotic only)
+               //MED 01/04/97 moved keys here so they would not be overwritten
+               if (gamemode == GAME_HIPNOTIC)
+               {
+                       if (cl.items & IT_KEY1)
+                               Sbar_DrawPic (209, 3, sb_items[0]);
+                       if (cl.items & IT_KEY2)
+                               Sbar_DrawPic (209, 12, sb_items[1]);
+               }
+// armor
                if (cl.items & IT_INVULNERABILITY)
                {
                        Sbar_DrawNum (24, 0, 666, 3, 1);
@@ -843,10 +794,9 @@ void Sbar_Draw (void)
                }
                else
                {
-                       if (rogue)
+                       if (gamemode == GAME_ROGUE)
                        {
-                               Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3,
-                                                               cl.stats[STAT_ARMOR] <= 25);
+                               Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
                                if (cl.items & RIT_ARMOR3)
                                        Sbar_DrawPic (0, 0, sb_armor[2]);
                                else if (cl.items & RIT_ARMOR2)
@@ -856,8 +806,7 @@ void Sbar_Draw (void)
                        }
                        else
                        {
-                               Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3
-                               , cl.stats[STAT_ARMOR] <= 25);
+                               Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
                                if (cl.items & IT_ARMOR3)
                                        Sbar_DrawPic (0, 0, sb_armor[2]);
                                else if (cl.items & IT_ARMOR2)
@@ -871,11 +820,10 @@ void Sbar_Draw (void)
                Sbar_DrawFace ();
 
        // health
-               Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3
-               , cl.stats[STAT_HEALTH] <= 25);
+               Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
 
        // ammo icon
-               if (rogue)
+               if (gamemode == GAME_ROGUE)
                {
                        if (cl.items & RIT_SHELLS)
                                Sbar_DrawPic (224, 0, sb_ammo[0]);
@@ -904,14 +852,11 @@ void Sbar_Draw (void)
                                Sbar_DrawPic (224, 0, sb_ammo[3]);
                }
 
-               Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3,
-                                         cl.stats[STAT_AMMO] <= 10);
+               Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
        }
 
-       if (vid.width > 320) {
-               if (cl.gametype == GAME_DEATHMATCH)
-                       Sbar_MiniDeathmatchOverlay ();
-       }
+       if (vid.conwidth > 320 && cl.gametype == GAME_DEATHMATCH)
+               Sbar_MiniDeathmatchOverlay ();
 }
 
 //=============================================================================
@@ -970,7 +915,7 @@ void Sbar_DeathmatchOverlay (void)
 // draw the text
        l = scoreboardlines;
 
-       x = ((vid.width - 320)>>1) - 140;
+       x = ((vid.conwidth - 320)>>1) - 140;
        y = 40;
        for (i = 0;i < l;i++)
        {
@@ -1016,7 +961,7 @@ void Sbar_MiniDeathmatchOverlay (void)
        char                    num[128];
        scoreboard_t    *s;
 
-       if (vid.width < 512 || !sb_lines)
+       if (vid.conwidth < 512 || !sb_lines)
                return;
 
 // scores
@@ -1024,7 +969,7 @@ void Sbar_MiniDeathmatchOverlay (void)
 
 // draw the text
        l = scoreboardlines;
-       y = vid.height - sb_lines;
+       y = vid.conheight - sb_lines;
        numlines = sb_lines/8;
        if (numlines < 3)
                return;
@@ -1045,7 +990,7 @@ void Sbar_MiniDeathmatchOverlay (void)
             i = 0;
 
        x = 324;
-       for (;i < scoreboardlines && y < vid.height - 8;i++)
+       for (;i < scoreboardlines && y < vid.conheight - 8;i++)
        {
                k = fragsort[i];
                s = &cl.scores[k];
@@ -1125,5 +1070,5 @@ void Sbar_FinaleOverlay (void)
        qpic_t  *pic;
 
        pic = Draw_CachePic ("gfx/finale.lmp");
-       Draw_Pic ( (vid.width-pic->width)/2, 16, pic);
+       Draw_Pic ( (vid.conwidth-pic->width)/2, 16, pic);
 }
index d280f47d1ee11dd3b301042ed6955c1a72791d87..9aa91f8dfd64b9ab5aa44d143e96785738c48c6e 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 
 cvar_t sv_pvscheckentities = {0, "sv_pvscheckentities", "1"};
-cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "1"};
+cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "0"}; // extremely accurate visibility checking, but too slow
 cvar_t sv_reportvischeckentities = {0, "sv_reportvischeckentities", "0"};
 int sv_vischeckentitycullcount = 0;
 
@@ -233,7 +233,7 @@ void SV_SendServerinfo (client_t *client)
        char                    message[2048];
 
        MSG_WriteByte (&client->message, svc_print);
-       sprintf (message, "%c\nDARKPLACES VERSION %4.2f BUILD %i SERVER (%i CRC)", 2, VERSION, buildnumber, pr_crc);
+       sprintf (message, "\002\nServer: %s build %i (progs %i crc)", gamename, buildnumber, pr_crc);
        MSG_WriteString (&client->message,message);
 
        MSG_WriteByte (&client->message, svc_serverinfo);
@@ -262,7 +262,7 @@ void SV_SendServerinfo (client_t *client)
        MSG_WriteByte (&client->message, sv.edicts->v.sounds);
        MSG_WriteByte (&client->message, sv.edicts->v.sounds);
 
-// set view    
+// set view
        MSG_WriteByte (&client->message, svc_setview);
        MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
 
@@ -419,7 +419,7 @@ void SV_AddToFatPVS (vec3_t org, mnode_t *node)
                        }
                        return;
                }
-       
+
                plane = node->plane;
                d = DotProduct (org, plane->normal) - plane->dist;
                if (d > 8)
@@ -500,9 +500,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
        vec3_t  org, origin, angles, entmins, entmaxs;
        float   movelerp, moveilerp, nextfullupdate;
        edict_t *ent;
-       eval_t  *val;
-       entity_state_t *baseline; // LordHavoc: delta or startup baseline
+       eval_t  *val;
+       entity_state_t  *baseline; // LordHavoc: delta or startup baseline
        trace_t trace;
+       model_t *model;
 
 // find the client's PVS
        VectorAdd (clent->v.origin, clent->v.view_ofs, org);
@@ -516,7 +517,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
        */
 
        clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
-// send over all entities (except the client) that touch the pvs
+       // send all entities that touch the pvs
        ent = NEXT_EDICT(sv.edicts);
        for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
        {
@@ -559,10 +560,15 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                if (val->_float != 0)
                        bits |= U_GLOWTRAIL;
 
-               if (ent->v.modelindex == 0 || pr_strings[ent->v.model] == 0) // no model
+               if (ent->v.modelindex >= 0 && ent->v.modelindex < MAX_MODELS && pr_strings[ent->v.model])
+                       model = sv.models[(int)ent->v.modelindex];
+               else
+               {
+                       model = NULL;
                        if (ent != clent) // LordHavoc: always send player
                                if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
                                        continue;
+               }
 
                if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement
                {
@@ -603,6 +609,16 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                }
                else // copy as they are
                {
+                       if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
+                       {
+                               // update lerp positions
+                               ent->steplerptime = sv.time;
+                               VectorCopy(ent->v.origin, ent->stepoldorigin);
+                               VectorCopy(ent->v.angles, ent->stepoldangles);
+                               VectorCopy(ent->v.origin, ent->steporigin);
+                               VectorCopy(ent->v.angles, ent->stepangles);
+                       }
+
                        VectorCopy(ent->v.angles, angles);
                        if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f)
                        {
@@ -615,27 +631,37 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                        {
                                VectorCopy(ent->v.origin, origin);
                        }
-                       if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
-                       {
-                               // update lerp positions
-                               ent->steplerptime = sv.time;
-                               VectorCopy(ent->v.origin, ent->stepoldorigin);
-                               VectorCopy(ent->v.angles, ent->stepoldangles);
-                               VectorCopy(ent->v.origin, ent->steporigin);
-                               VectorCopy(ent->v.angles, ent->stepangles);
-                       }
                }
 
                // ent has survived every check so far, check if it is visible
                if (ent != clent && ((bits & U_VIEWMODEL) == 0))
                {
                        // use the predicted origin
-                       entmins[0] = ent->v.mins[0] + origin[0] - 1.0f;
-                       entmins[1] = ent->v.mins[1] + origin[1] - 1.0f;
-                       entmins[2] = ent->v.mins[2] + origin[2] - 1.0f;
-                       entmaxs[0] = ent->v.maxs[0] + origin[0] + 1.0f;
-                       entmaxs[1] = ent->v.maxs[1] + origin[1] + 1.0f;
-                       entmaxs[2] = ent->v.maxs[2] + origin[2] + 1.0f;
+                       entmins[0] = origin[0] - 1.0f;
+                       entmins[1] = origin[1] - 1.0f;
+                       entmins[2] = origin[2] - 1.0f;
+                       entmaxs[0] = origin[0] + 1.0f;
+                       entmaxs[1] = origin[1] + 1.0f;
+                       entmaxs[2] = origin[2] + 1.0f;
+                       // using the model's bounding box to ensure things are visible regardless of their physics box
+                       if (model)
+                       {
+                               if (ent->v.angles[0] || ent->v.angles[2]) // pitch and roll
+                               {
+                                       VectorAdd(entmins, model->rotatedmins, entmins);
+                                       VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
+                               }
+                               else if (ent->v.angles[1])
+                               {
+                                       VectorAdd(entmins, model->yawmins, entmins);
+                                       VectorAdd(entmaxs, model->yawmaxs, entmaxs);
+                               }
+                               else
+                               {
+                                       VectorAdd(entmins, model->normalmins, entmins);
+                                       VectorAdd(entmaxs, model->normalmaxs, entmaxs);
+                               }
+                       }
 
                        // if not touching a visible leaf
                        if (sv_pvscheckentities.value && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes))
@@ -689,10 +715,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                {
                        if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
                        {
-                               if (ent->v.modelindex && pr_strings[ent->v.model]) // model
+                               if (model) // model
                                {
                                        // don't send if flagged for NODRAW and there are no effects
-                                       if (sv.models[(int)ent->v.modelindex]->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
+                                       if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
                                                continue;
                                }
                                else // no model and no effects
@@ -992,11 +1018,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        MSG_WriteByte (msg, ent->v.ammo_rockets);
        MSG_WriteByte (msg, ent->v.ammo_cells);
 
-       if (standard_quake)
-       {
-               MSG_WriteByte (msg, ent->v.weapon);
-       }
-       else
+       if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
        {
                for(i=0;i<32;i++)
                {
@@ -1007,6 +1029,10 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
                        }
                }
        }
+       else
+       {
+               MSG_WriteByte (msg, ent->v.weapon);
+       }
 }
 
 /*
index 9fc909d34ca4bf002d905b3a82844c981a8f4bd4..3cf4fd1a11f7d24dd5ddded80dc0da1b9376f54b 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -356,6 +356,8 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                                return 7;
                        }
                        CrossProduct (planes[0], planes[1], dir);
+                       // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+                       VectorNormalize(dir);
                        d = DotProduct (dir, ent->v.velocity);
                        VectorScale (dir, d, ent->v.velocity);
                }
index fd3d2b6498228c2490f7ebd53fbd7cf7fb1355d1..27a6e108b5e8f7299ed347d213db24b46b96e41b 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -582,8 +582,8 @@ nextmsg:
                                 || Q_strncasecmp(s, "ping", 4) == 0
                                 || Q_strncasecmp(s, "ban", 3) == 0
                                 || Q_strncasecmp(s, "pmodel", 6) == 0
-                                || (nehahra && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0))
-                                || (!nehahra && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0)))
+                                || (gamemode == GAME_NEHAHRA && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0))
+                                || (gamemode != GAME_NEHAHRA && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0)))
                                {
                                        ret = 1;
                                        Cmd_ExecuteString (s, src_client);
diff --git a/sys.h b/sys.h
index dd31ce09f19dcd252836606642908c0046ce3b16..4b5372ea931c47a803dade47f74953f5ed497dd4 100644 (file)
--- a/sys.h
+++ b/sys.h
@@ -60,3 +60,7 @@ void Sys_Sleep (void);
 void Sys_SendKeyEvents (void);
 // Perform Key_Event () callbacks until the input que is empty
 
+// called after Com_InitArgv
+void Sys_Shared_EarlyInit (void);
+// called after Host_init
+void Sys_Shared_LateInit (void);
index d36b558854061086956e702110b8faa488372900..405dc31496c80fa66349e8b7d81c36d4cf2dedf6 100644 (file)
@@ -274,9 +274,11 @@ int main (int c, char **v)
 
        fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
 
+       Sys_Shared_EarlyInit();
+
        Host_Init();
 
-       Sys_Shared_Init();
+       Sys_Shared_LateInit();
 
        oldtime = Sys_DoubleTime () - 0.1;
        while (1)
index 719bce792de45867ada0b19aee1bc1c788c5ed82..01fd0fbabee12a34fb4509fc4dcafcd9c171688b 100644 (file)
@@ -107,19 +107,24 @@ void Sys_Printf (char *fmt, ...)
 //#endif
 }
 
-void Sys_Shared_Init(void)
+char engineversion[40];
+
+void Sys_Shared_EarlyInit(void)
 {
-       if (COM_CheckParm("-nostdout"))
-               sys_nostdout = 1;
-       else
-       {
 #if defined(__linux__)
-               fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
-               printf ("DarkPlaces Linux   GL %.2f build %3i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "%s Linux GL build %3i", gamename, buildnumber);
 #elif defined(WIN32)
-               printf ("DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "%s Windows GL build %3i", gamename, buildnumber);
 #else
-               printf ("DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "%s Unknown GL build %3i", gamename, buildnumber);
 #endif
-       }
+
+       if (COM_CheckParm("-nostdout"))
+               sys_nostdout = 1;
+       else
+               printf("%s\n", engineversion);
+}
+
+void Sys_Shared_LateInit(void)
+{
 }
index 8ad72f032c3887f507cede8764538bc840e53612..82b5179be4510168be8ca50a0a9650105b4fc7c0 100644 (file)
--- a/sys_win.c
+++ b/sys_win.c
@@ -579,7 +579,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
                                *lpCmdLine = 0;
                                lpCmdLine++;
                        }
-                       
+
                }
        }
 
@@ -590,7 +590,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
        host_parms.argc = com_argc;
        host_parms.argv = com_argv;
 
-       Sys_Shared_Init();
+       Sys_Shared_EarlyInit();
 
 // take the greater of all the available memory or half the total memory,
 // but at least 8 Mb and no more than 16 Mb, unless they explicitly
@@ -631,13 +631,13 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
                        if (t < com_argc)
                                hFile = (HANDLE)atoi (com_argv[t+1]);
                }
-                       
+
                if ((t = COM_CheckParm ("-HPARENT")) > 0)
                {
                        if (t < com_argc)
                                heventParent = (HANDLE)atoi (com_argv[t+1]);
                }
-                       
+
                if ((t = COM_CheckParm ("-HCHILD")) > 0)
                {
                        if (t < com_argc)
@@ -659,9 +659,10 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
        timeBeginPeriod (1);
 #endif
 
-       Sys_Printf ("Host_Init\n");
        Host_Init ();
 
+       Sys_Shared_LateInit();
+
        oldtime = Sys_DoubleTime ();
 
     /* main window message loop */
index 9396bbe3eb6eb4e986883074c88884efe8edac9e..363d04c921bceb25d5daa08f70a09d6ffb647b3a 100644 (file)
@@ -148,17 +148,17 @@ void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale)
        softwaretransform_classify();
 }
 
-void softwaretransformforentity (entity_t *e)
+void softwaretransformforentity (entity_render_t *r)
 {
        vec3_t angles;
-       angles[0] = -e->render.angles[0];
-       angles[1] = e->render.angles[1];
-       angles[2] = e->render.angles[2];
-       softwaretransformset(e->render.origin, angles, e->render.scale);
+       angles[0] = -r->angles[0];
+       angles[1] = r->angles[1];
+       angles[2] = r->angles[2];
+       softwaretransformset(r->origin, angles, r->scale);
 }
 
 // brush entities are not backwards like models and sprites are
-void softwaretransformforbrushentity (entity_t *e)
+void softwaretransformforbrushentity (entity_render_t *r)
 {
-       softwaretransformset(e->render.origin, e->render.angles, e->render.scale);
+       softwaretransformset(r->origin, r->angles, r->scale);
 }
index 6b0494ecf21da6d0e15c47c65cf66fdf8dd2493a..e2d82e58e1f0618c19b8b870b72d0b223999f095 100644 (file)
@@ -10,8 +10,8 @@ extern vec3_t softwaretransform_y;
 extern vec3_t softwaretransform_z;
 extern int softwaretransform_type;
 
-extern void softwaretransformforentity (entity_t *e);
-extern void softwaretransformforbrushentity (entity_t *e);
+extern void softwaretransformforentity (entity_render_t *r);
+extern void softwaretransformforbrushentity (entity_render_t *r);
 extern void softwaretransformidentity (void);
 extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale);
 extern void (*softwaretransform) (vec3_t in, vec3_t out);
diff --git a/ui.c b/ui.c
index 1e10d337d6de4dee8bc02cf0cb664f35e1086b1c..88e1c2e51f61cc999466dcbab356bc73d996ca05 100644 (file)
--- a/ui.c
+++ b/ui.c
@@ -39,7 +39,7 @@ static byte pointerimage[256] =
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
@@ -49,8 +49,8 @@ void ui_start(void)
 {
 //     ui_mousepointer = Draw_CachePic("ui/mousepointer.lmp");
        ui_mousepointertexture = R_LoadTexture("mousepointer", 16, 16, pointerimage, TEXF_ALPHA | TEXF_PRECACHE);
-       ui_mouse_x = vid.width * 0.5;
-       ui_mouse_y = vid.height * 0.5;
+       ui_mouse_x = vid.conwidth * 0.5;
+       ui_mouse_y = vid.conheight * 0.5;
        ui_alive = true;
 }
 
@@ -75,8 +75,8 @@ void ui_mouseupdate(float x, float y)
 {
        if (ui_alive)
        {
-               ui_mouse_x = bound(0, x, vid.width);
-               ui_mouse_y = bound(0, y, vid.height);
+               ui_mouse_x = bound(0, x, vid.conwidth);
+               ui_mouse_y = bound(0, y, vid.conheight);
        }
 }
 
@@ -86,8 +86,8 @@ void ui_mouseupdaterelative(float x, float y)
        {
                ui_mouse_x += x;
                ui_mouse_y += y;
-               ui_mouse_x = bound(0, ui_mouse_x, vid.width);
-               ui_mouse_y = bound(0, ui_mouse_y, vid.height);
+               ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
+               ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
        }
 }
 
@@ -115,7 +115,7 @@ void ui_clear(ui_t *ui)
 void ui_item
 (
        ui_t *ui, char *basename, int number,
-       float x, float y, qpic_t *pic,
+       float x, float y, qpic_t *pic, char *string,
        float left, float top, float width, float height,
        void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
        void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
@@ -140,30 +140,37 @@ void ui_item
                }
                ui->item_count++;
        }
+       memset(it, 0, sizeof(ui_item_t));
        strncpy(it->name, itemname, 32);
        it->flags = 0;
+       if (pic || string)
+       {
+               it->flags |= ITEM_DRAWABLE;
+               it->draw_pic = pic;
+               it->draw_string = string;
+               it->draw_x = x;
+               it->draw_y = y;
+       }
        if (leftkey || rightkey || enterkey || mouseclick)
+       {
                it->flags |= ITEM_CLICKABLE;
-       if (pic)
-               it->flags |= ITEM_DRAWABLE;
-       it->draw_x = x;
-       it->draw_y = y;
-       it->click_x = x + left;
-       it->click_y = y + top;
-       it->click_x2 = it->click_x + width;
-       it->click_y2 = it->click_y + height;
-       it->leftkey = leftkey;
-       it->rightkey = rightkey;
-       it->enterkey = enterkey;
-       it->mouseclick = mouseclick;
-       if (it->mouseclick == NULL)
-               it->mouseclick = (void *)it->enterkey;
-       if (it->leftkey == NULL)
-               it->leftkey = it->enterkey;
-       if (it->rightkey == NULL)
-               it->rightkey = it->enterkey;
-       it->nativedata1 = nativedata1;
-       it->nativedata2 = nativedata2;
+               it->click_x = x + left;
+               it->click_y = y + top;
+               it->click_x2 = it->click_x + width;
+               it->click_y2 = it->click_y + height;
+               it->leftkey = leftkey;
+               it->rightkey = rightkey;
+               it->enterkey = enterkey;
+               it->mouseclick = mouseclick;
+               if (it->mouseclick == NULL)
+                       it->mouseclick = (void *)it->enterkey;
+               if (it->leftkey == NULL)
+                       it->leftkey = it->enterkey;
+               if (it->rightkey == NULL)
+                       it->rightkey = it->enterkey;
+               it->nativedata1 = nativedata1;
+               it->nativedata2 = nativedata2;
+       }
 }
 
 void ui_item_remove(ui_t *ui, char *basename, int number)
@@ -298,8 +305,8 @@ void ui_update(void)
        ui_item_t *startitem, *it;
        if (ui_alive)
        {
-               ui_mouse_x = bound(0, ui_mouse_x, vid.width);
-               ui_mouse_y = bound(0, ui_mouse_y, vid.height);
+               ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
+               ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
 
                if ((ui_active = ui_isactive()))
                {
@@ -397,17 +404,28 @@ void ui_draw(void)
                                if (ui->item_count)
                                        for (i = 0, it = ui->items;i < ui->item_count;i++, it++)
                                                if (it->flags & ITEM_DRAWABLE)
-                                                       Draw_Pic(it->draw_x, it->draw_y, it->draw_pic);
+                                               {
+                                                       if (it->draw_pic)
+                                                               Draw_Pic(it->draw_x, it->draw_y, it->draw_pic);
+                                                       if (it->draw_string)
+                                                               Draw_String(it->draw_x, it->draw_y, it->draw_string, 9999);
+                                               }
 
                if ((it = ui_hititem(ui_mouse_x, ui_mouse_y)))
                {
-                       Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+                       if (it->draw_pic)
+                               Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+                       if (it->draw_string)
+                               Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999);
                        if (ui_showname.value)
                                Draw_String(ui_mouse_x, ui_mouse_y + 16, it->name, 9999);
        }
 
                it = ui_keyrealitem;
-               Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+               if (it->draw_pic)
+                       Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+               if (it->draw_string)
+                       Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999);
 
 //             Draw_Pic(ui_mouse_x, ui_mouse_y, ui_mousepointer);
                Draw_GenericPic(ui_mousepointertexture, 1, 1, 1, 1, ui_mouse_x, ui_mouse_y, 16, 16);
diff --git a/ui.h b/ui.h
index 4fc2c1c653563a933cf02b85a036cc9833596136..a9b94688c9fd58a286f8ae7ab5bfade2f96daef0 100644 (file)
--- a/ui.h
+++ b/ui.h
@@ -12,6 +12,7 @@ typedef struct
        char name[32];
        int flags;
        qpic_t *draw_pic;
+       char *draw_string;
        int draw_x, draw_y;
        int click_x, click_y, click_x2, click_y2;
        void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2);
@@ -64,7 +65,7 @@ void ui_clear(ui_t *ui);
 void ui_item
 (
        ui_t *ui, char *basename, int number,
-       float x, float y, qpic_t *pic,
+       float x, float y, qpic_t *pic, char *string,
        float left, float top, float width, float height,
        void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
        void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
diff --git a/vid.h b/vid.h
index d8a4cfdf2a981fec493021c5e72b45be3158134f..60a659f15e99477cb5cd16196fe874deb38f9cc0 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -19,17 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 // vid.h -- video driver defs
 
-typedef struct vrect_s
-{
-       int                             x,y,width,height;
-       struct vrect_s  *pnext;
-} vrect_t;
-
 typedef struct
 {
-       int             width;          
-       int             height;
-       int             recalc_refdef;  // if true, recalc vid-based stuff
+       // these are set with GL_BeginRendering and can change from frame to frame
+       int             realx;
+       int             realy;
+       int             realwidth;
+       int             realheight;
+//     int             recalc_refdef;  // if true, recalc vid-based stuff
+
        int             conwidth;
        int             conheight;
 } viddef_t;
index 3f4e42661c506cee232bb6221ac5a60b8cc528dc..cc1f9cca5d9bfd436d9309531821153021f97903 100644 (file)
@@ -291,8 +291,6 @@ void VID_Init(void)
                vid.conheight = height;
        if (vid.conwidth > width)
                vid.conwidth = width;
-       vid.width = vid.conwidth;
-       vid.height = vid.conheight;
 
        InitSig(); // trap evil signals
 
@@ -302,7 +300,7 @@ void VID_Init(void)
 
        Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
 
-       vid.recalc_refdef = 1;                          // force a surface cache flush
+//     vid.recalc_refdef = 1;                          // force a surface cache flush
 }
 
 void VID_ExtraOptionDraw(unsigned int options_draw_cursor)
index 69c347059cb68eb9d8b64e250776e53cf94cc58d..994084da86f5c4ced9396e935591a42f93b58a55 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <X11/extensions/xf86dga.h>
 #include <X11/extensions/xf86vmode.h>
 
-static Display *dpy = NULL;
+static Display *vidx11_display = NULL;
 static int scrnum;
 static Window win;
 static GLXContext ctx = NULL;
@@ -73,6 +73,9 @@ static XF86VidModeModeInfo **vidmodes;
 static int num_vidmodes;
 static qboolean vidmode_active = false;
 
+static Visual *vidx11_visual;
+static Colormap vidx11_colormap;
+
 /*-----------------------------------------------------------------------*/
 
 float          gldepthmin, gldepthmax;
@@ -215,20 +218,20 @@ static void install_grabs(void)
        XWindowAttributes attribs_1;
        XSetWindowAttributes attribs_2;
 
-       XGetWindowAttributes(dpy, win, &attribs_1);
+       XGetWindowAttributes(vidx11_display, win, &attribs_1);
        attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
-       XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2);
+       XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2);
 
 // inviso cursor
-       XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
+       XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win));
 
-       XGrabPointer(dpy, win,  True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
+       XGrabPointer(vidx11_display, win,  True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
 
        if (vid_dga.value)
        {
                int MajorVersion, MinorVersion;
 
-               if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion))
+               if (!XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion))
                {
                        // unable to query, probalby not supported
                        Con_Printf( "Failed to detect XF86DGA Mouse\n" );
@@ -237,34 +240,34 @@ static void install_grabs(void)
                else
                {
                        vid_dga.value = 1;
-                       XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
-                       XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+                       XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse);
+                       XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0);
                }
        }
        else
-               XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
+               XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, scr_width / 2, scr_height / 2);
 
-       XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+       XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
 
        mouse_active = true;
        mouse_x = mouse_y = 0;
 
-//     XSync(dpy, True);
+//     XSync(vidx11_display, True);
 }
 
 static void uninstall_grabs(void)
 {
-       if (!dpy || !win)
+       if (!vidx11_display || !win)
                return;
 
        if (vid_dga.value == 1)
-               XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
+               XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0);
 
-       XUngrabPointer(dpy, CurrentTime);
-       XUngrabKeyboard(dpy, CurrentTime);
+       XUngrabPointer(vidx11_display, CurrentTime);
+       XUngrabKeyboard(vidx11_display, CurrentTime);
 
 // inviso cursor
-       XUndefineCursor(dpy, win);
+       XUndefineCursor(vidx11_display, win);
 
        mouse_active = false;
 }
@@ -275,12 +278,12 @@ static void HandleEvents(void)
 //     KeySym ks;
        qboolean dowarp = false;
 
-       if (!dpy)
+       if (!vidx11_display)
                return;
 
-       while (XPending(dpy))
+       while (XPending(vidx11_display))
        {
-               XNextEvent(dpy, &event);
+               XNextEvent(vidx11_display, &event);
 
                switch (event.type)
                {
@@ -312,7 +315,7 @@ static void HandleEvents(void)
                                                {
                                                        mouse_x += event.xmotion.x - p_mouse_x;
                                                        mouse_y += event.xmotion.y - p_mouse_y;
-                                                       if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4)
+                                                       if (abs(scr_width/2 - event.xmotion.x) > scr_width / 4 || abs(scr_height/2 - event.xmotion.y) > scr_height / 4)
                                                                dowarp = true;
                                                }
                                        }
@@ -394,16 +397,16 @@ static void HandleEvents(void)
        if (dowarp)
        {
                /* move the mouse to the window center again */
-               p_mouse_x = vid.width / 2;
-               p_mouse_y = vid.height / 2;
-               XWarpPointer(dpy, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y);
+               p_mouse_x = scr_width / 2;
+               p_mouse_y = scr_height / 2;
+               XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y);
        }
 
 }
 
 static void IN_DeactivateMouse( void )
 {
-       if (!mouse_avail || !dpy || !win)
+       if (!mouse_avail || !vidx11_display || !win)
                return;
 
        if (mouse_active)
@@ -415,7 +418,7 @@ static void IN_DeactivateMouse( void )
 
 static void IN_ActivateMouse( void )
 {
-       if (!mouse_avail || !dpy || !win)
+       if (!mouse_avail || !vidx11_display || !win)
                return;
 
        if (!mouse_active)
@@ -429,25 +432,25 @@ static void IN_ActivateMouse( void )
 
 void VID_Shutdown(void)
 {
-       if (!ctx || !dpy)
+       if (!ctx || !vidx11_display)
                return;
 
-       if (dpy)
+       if (vidx11_display)
        {
                uninstall_grabs();
 
                if (vidmode_active)
-                       XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
+                       XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[0]);
 /* Disabled, causes a segfault during shutdown.
                if (ctx)
-                       glXDestroyContext(dpy, ctx);
+                       glXDestroyContext(vidx11_display, ctx);
 */
                if (win)
-                       XDestroyWindow(dpy, win);
-               XCloseDisplay(dpy);
+                       XDestroyWindow(vidx11_display, win);
+               XCloseDisplay(vidx11_display);
        }
        vidmode_active = false;
-       dpy = NULL;
+       vidx11_display = NULL;
        win = 0;
        ctx = NULL;
 }
@@ -495,7 +498,7 @@ void GL_EndRendering (void)
        if (!r_render.value)
                return;
        glFlush();
-       glXSwapBuffers(dpy, win);
+       glXSwapBuffers(vidx11_display, win);
 
 // handle the mouse state when windowed if that's changed
        usemouse = false;
@@ -521,15 +524,100 @@ void GL_EndRendering (void)
        }
 }
 
+// LordHavoc: ported from SDL 1.2.2, this was far more difficult to port from
+// SDL than to simply use the XFree gamma ramp extension, but that affects the
+// whole screen even when the game window is inactive, this only affects the
+// screen while the window is active, very desirable behavior :)
 int VID_SetGamma(float prescale, float gamma, float scale, float base)
 {
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 1
        return FALSE;
+#else
+       int i, ncolors, c;
+       unsigned int Rmask, Gmask, Bmask, Rloss, Gloss, Bloss, Rshift, Gshift, Bshift, mask;
+       XColor xcmap[256];
+       unsigned short ramp[256];
+
+       if (COM_CheckParm("-nogamma"))
+               return FALSE;
+
+       if (vidx11_visual->class != DirectColor)
+       {
+               Con_Printf("X11 Visual class is %d, can only do gamma on %d\n", vidx11_visual->class, DirectColor);
+               return FALSE;
+       }
+
+       Rmask = vidx11_visual->red_mask;
+       Gmask = vidx11_visual->green_mask;
+       Bmask = vidx11_visual->blue_mask;
+
+       Rshift = 0;
+       Rloss = 8;
+       if ((mask = Rmask))
+       {
+               for (;!(mask & 1);mask >>= 1)
+                       ++Rshift;
+               for (;(mask & 1);mask >>= 1)
+                       --Rloss;
+       }
+       Gshift = 0;
+       Gloss = 8;
+       if ((mask = Gmask))
+       {
+               for (;!(mask & 1);mask >>= 1)
+                       ++Gshift;
+               for (;(mask & 1);mask >>= 1)
+                       --Gloss;
+       }
+       Bshift = 0;
+       Bloss = 8;
+       if ((mask = Bmask))
+       {
+               for (;!(mask & 1);mask >>= 1)
+                       ++Bshift;
+               for (;(mask & 1);mask >>= 1)
+                       --Bloss;
+       }
+
+       BuildGammaTable16(prescale, gamma, scale, base, ramp);
+
+       // convert gamma ramp to palette (yes this seems odd)
+       ncolors = vidx11_visual->map_entries;
+       for (i = 0;i < ncolors;i++)
+       {
+               c = (256 * i / ncolors);
+               xcmap[i].pixel = ((c >> Rloss) << Rshift) | ((c >> Gloss) << Gshift) | ((c >> Bloss) << Bshift);
+               xcmap[i].red   = ramp[c];
+               xcmap[i].green = ramp[c];
+               xcmap[i].blue  = ramp[c];
+               xcmap[i].flags = (DoRed|DoGreen|DoBlue);
+       }
+       XStoreColors(vidx11_display, vidx11_colormap, xcmap, ncolors);
+       XSync(vidx11_display, false);
+       // FIXME: should this check for BadAccess/BadColor/BadValue errors produced by XStoreColors before setting this true?
+       return TRUE;
+#endif
 }
 
 void VID_Init(void)
 {
        int i;
-       int attrib[] =
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 0
+       int gammaattrib[] =
+       {
+               GLX_RGBA,
+               GLX_RED_SIZE, 1,
+               GLX_GREEN_SIZE, 1,
+               GLX_BLUE_SIZE, 1,
+               GLX_DOUBLEBUFFER,
+               GLX_DEPTH_SIZE, 1,
+               GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR,
+               None
+       };
+#endif
+       int nogammaattrib[] =
        {
                GLX_RGBA,
                GLX_RED_SIZE, 1,
@@ -547,7 +635,6 @@ void VID_Init(void)
        XVisualInfo *visinfo;
        qboolean fullscreen = true;
        int MajorVersion, MinorVersion;
-       int actualWidth, actualHeight;
 
        Cvar_RegisterVariable (&vid_mouse);
        Cvar_RegisterVariable (&vid_dga);
@@ -584,18 +671,18 @@ void VID_Init(void)
        if (vid.conheight < 200)
                vid.conheight = 200;
 
-       if (!(dpy = XOpenDisplay(NULL)))
+       if (!(vidx11_display = XOpenDisplay(NULL)))
        {
                fprintf(stderr, "Error couldn't open the X display\n");
                exit(1);
        }
 
-       scrnum = DefaultScreen(dpy);
-       root = RootWindow(dpy, scrnum);
+       scrnum = DefaultScreen(vidx11_display);
+       root = RootWindow(vidx11_display, scrnum);
 
        // Get video mode list
        MajorVersion = MinorVersion = 0;
-       if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion))
+       if (!XF86VidModeQueryVersion(vidx11_display, &MajorVersion, &MinorVersion))
                vidmode_ext = false;
        else
        {
@@ -603,18 +690,27 @@ void VID_Init(void)
                vidmode_ext = true;
        }
 
-       visinfo = glXChooseVisual(dpy, scrnum, attrib);
+       visinfo = NULL;
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 0
+       if (!COM_CheckParm("-nogamma"))
+               visinfo = glXChooseVisual(vidx11_display, scrnum, gammaattrib);
+#endif
        if (!visinfo)
        {
-               fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
-               exit(1);
+               visinfo = glXChooseVisual(vidx11_display, scrnum, nogammaattrib);
+               if (!visinfo)
+               {
+                       fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
+                       exit(1);
+               }
        }
 
        if (vidmode_ext)
        {
                int best_fit, best_dist, dist, x, y;
 
-               XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
+               XF86VidModeGetAllModeLines(vidx11_display, scrnum, &num_vidmodes, &vidmodes);
 
                // Are we going fullscreen?  If so, let's change video mode
                if (fullscreen)
@@ -639,25 +735,32 @@ void VID_Init(void)
 
                        if (best_fit != -1)
                        {
-                               actualWidth = vidmodes[best_fit]->hdisplay;
-                               actualHeight = vidmodes[best_fit]->vdisplay;
+                               // LordHavoc: changed from ActualWidth/ActualHeight =,
+                               // to width/height =, so the window will take the full area of
+                               // the mode chosen
+                               width = vidmodes[best_fit]->hdisplay;
+                               height = vidmodes[best_fit]->vdisplay;
 
                                // change to the mode
-                               XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
+                               XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[best_fit]);
                                vidmode_active = true;
 
                                // Move the viewport to top left
-                               XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+                               XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0);
                        }
                        else
                                fullscreen = 0;
                }
        }
 
+       // LordHavoc: save the visual for use in gamma ramp settings later
+       vidx11_visual = visinfo->visual;
+
        /* window attributes */
        attr.background_pixel = 0;
        attr.border_pixel = 0;
-       attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+       // LordHavoc: save the colormap for later, too
+       vidx11_colormap = attr.colormap = XCreateColormap(vidx11_display, root, visinfo->visual, AllocNone);
        attr.event_mask = X_MASK;
        if (vidmode_active)
        {
@@ -669,25 +772,25 @@ void VID_Init(void)
        else
                mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
 
-       win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
-       XStoreName(dpy, win, "DarkPlaces-GLX");
-       XMapWindow(dpy, win);
+       win = XCreateWindow(vidx11_display, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
+       XStoreName(vidx11_display, win, gamename);
+       XMapWindow(vidx11_display, win);
 
        if (vidmode_active)
        {
-               XMoveWindow(dpy, win, 0, 0);
-               XRaiseWindow(dpy, win);
-               XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
-               XFlush(dpy);
+               XMoveWindow(vidx11_display, win, 0, 0);
+               XRaiseWindow(vidx11_display, win);
+               XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0);
+               XFlush(vidx11_display);
                // Move the viewport to top left
-               XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+               XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0);
        }
 
-       XFlush(dpy);
+       XFlush(vidx11_display);
 
-       ctx = glXCreateContext(dpy, visinfo, NULL, True);
+       ctx = glXCreateContext(vidx11_display, visinfo, NULL, True);
 
-       glXMakeCurrent(dpy, win, ctx);
+       glXMakeCurrent(vidx11_display, win, ctx);
 
        scr_width = width;
        scr_height = height;
@@ -696,8 +799,6 @@ void VID_Init(void)
                vid.conheight = height;
        if (vid.conwidth > width)
                vid.conwidth = width;
-       vid.width = vid.conwidth;
-       vid.height = vid.conheight;
 
        InitSig(); // trap evil signals
 
@@ -706,7 +807,7 @@ void VID_Init(void)
        Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
 
        // force a surface cache flush
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 }
 
 void Sys_SendKeyEvents(void)
@@ -764,7 +865,7 @@ void IN_MouseMove (usercmd_t *cmd)
        if (/*freelook && */!(in_strafe.state & 1))
        {
                cl.viewangles[PITCH] += m_pitch.value * mouse_y;
-               cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80);
+               cl.viewangles[PITCH] = bound (-90, cl.viewangles[PITCH], 90);
        }
        else
        {
index cb4621c2c651bc4da51d3c58ca860664785b9386..7f4cc5f6438194b515d3491cf3bc0e84fa586de2 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -163,7 +163,7 @@ qboolean VID_SetWindowedMode (int modenum)
        height = rect.bottom - rect.top;
 
        // Create the DIB window
-       mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
+       mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
 
        if (!mainwindow)
                Sys_Error ("Couldn't create DIB window");
@@ -180,8 +180,6 @@ qboolean VID_SetWindowedMode (int modenum)
                vid.conheight = modelist[modenum].height;
        if (vid.conwidth > modelist[modenum].width)
                vid.conwidth = modelist[modenum].width;
-       vid.width = vid.conwidth;
-       vid.height = vid.conheight;
 
        SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon);
        SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon);
@@ -229,7 +227,7 @@ qboolean VID_SetFullDIBMode (int modenum)
        height = rect.bottom - rect.top;
 
        // Create the DIB window
-       mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
+       mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
 
        if (!mainwindow)
                Sys_Error ("Couldn't create DIB window");
@@ -241,8 +239,6 @@ qboolean VID_SetFullDIBMode (int modenum)
                vid.conheight = modelist[modenum].height;
        if (vid.conwidth > modelist[modenum].width)
                vid.conwidth = modelist[modenum].width;
-       vid.width = vid.conwidth;
-       vid.height = vid.conheight;
 
 // needed because we're not getting WM_MOVE messages fullscreen on NT
        window_x = 0;
@@ -342,7 +338,7 @@ int VID_SetMode (int modenum)
        if (!msg_suppress_1)
                Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
 
-       vid.recalc_refdef = 1;
+//     vid.recalc_refdef = 1;
 
        return true;
 }
@@ -587,6 +583,7 @@ void ClearAllStates (void)
 }
 
 void VID_RestoreGameGamma(void);
+extern qboolean hostloopactive;
 
 void AppActivate(BOOL fActive, BOOL minimize)
 /****************************************************************************
@@ -640,7 +637,8 @@ void AppActivate(BOOL fActive, BOOL minimize)
 //                     IN_ActivateMouse ();
 //                     IN_HideMouse ();
 //             }
-               VID_RestoreGameGamma();
+               if (hostloopactive)
+                       VID_RestoreGameGamma();
        }
 
        if (!fActive)
@@ -988,7 +986,7 @@ void VID_InitDIB (HINSTANCE hInstance)
     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
        wc.hbrBackground = NULL;
     wc.lpszMenuName  = 0;
-    wc.lpszClassName = "DarkPlaces";
+    wc.lpszClassName = gamename;
 
     if (!RegisterClass (&wc) )
                Sys_Error ("Couldn't register window class");
diff --git a/view.c b/view.c
index ae3c45f2aba532d3b2db2566fde9b6587ce1a6e6..65ba402a6bf6b4bf75881df2bc20d7b6659f2e61 100644 (file)
--- a/view.c
+++ b/view.c
@@ -562,7 +562,7 @@ CalcGunAngle
 ==================
 */
 void CalcGunAngle (void)
-{      
+{
        /*
        float   yaw, pitch, move;
        static float oldyaw = 0;
@@ -718,6 +718,8 @@ void V_CalcIntermissionRefdef (void)
        v_idlescale.value = old;
 }
 
+extern void CL_LerpUpdate(entity_t *e, int frame, int modelindex);
+
 /*
 ==================
 V_CalcRefdef
@@ -786,13 +788,12 @@ void V_CalcRefdef (void)
                V_BoundOffsets ();
 
        // set up gun position
+               VectorCopy (ent->render.origin, view->render.origin);
+               view->render.origin[2] += cl.viewheight;
                VectorCopy (cl.viewangles, view->render.angles);
 
                CalcGunAngle ();
 
-               VectorCopy (ent->render.origin, view->render.origin);
-               view->render.origin[2] += cl.viewheight;
-
                for (i=0 ; i<3 ; i++)
                {
                        view->render.origin[i] += forward[i]*bob*0.4;
@@ -801,9 +802,16 @@ void V_CalcRefdef (void)
                }
                view->render.origin[2] += bob;
 
+               // FIXME: this setup code is somewhat evil (CL_LerpUpdate should be private)
+               CL_LerpUpdate(view, cl.stats[STAT_WEAPONFRAME], cl.stats[STAT_WEAPON]);
+
                view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]];
                view->render.frame = cl.stats[STAT_WEAPONFRAME];
                view->render.colormap = -1; // no special coloring
+               view->render.alpha = ent->render.alpha; // LordHavoc: if the player is transparent, so is the gun
+               view->render.effects = ent->render.effects;
+               view->render.scale = 1;
+               VectorCopy(ent->render.colormod, view->render.colormod);
 
        // set up the refresh position
 
diff --git a/view.h b/view.h
index f44353eb8037009eace793c56975225c51e10feb..ab069251e10faefc503a94fcd86b73cd141ecf82 100644 (file)
--- a/view.h
+++ b/view.h
@@ -28,4 +28,5 @@ void V_Init (void);
 void V_RenderView (void);
 float V_CalcRoll (vec3_t angles, vec3_t velocity);
 void V_UpdateBlends (void);
+void V_CalcBlend (void);
 
diff --git a/world.c b/world.c
index fc2f38a4e6c1429b5d7252f23da2c83b8ac26d0e..c0edd62e5acc5da7e56f04b8ded32e06a2de5c77 100644 (file)
--- a/world.c
+++ b/world.c
@@ -320,7 +320,7 @@ void SV_ClearWorld (void)
 
        memset (sv_areanodes, 0, sizeof(sv_areanodes));
        sv_numareanodes = 0;
-       SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
+       SV_CreateAreaNode (0, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
 }
 
 
@@ -566,157 +566,173 @@ LINE TESTING IN HULLS
 */
 
 // 1/32 epsilon to keep floating point happy
-#define        DIST_EPSILON    (0.03125)
+//#define      DIST_EPSILON    (0.03125)
+#define DIST_EPSILON (0.125)
 
-/*
-==================
-SV_RecursiveHullCheck
+#define HULLCHECKSTATE_EMPTY 0
+#define HULLCHECKSTATE_SOLID 1
+#define HULLCHECKSTATE_DONE 2
 
-==================
-*/
-/*
-qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
+// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass
+// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc...
+RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo;
+#define RHC RecursiveHullCheckInfo
+
+void SV_RecursiveHullCheck_Impact (mplane_t *plane, int side)
+{
+       // LordHavoc: using doubles for extra accuracy
+       double t1, t2, frac;
+
+       // LordHavoc: now that we have found the impact, recalculate the impact
+       // point from scratch for maximum accuracy, with an epsilon bias on the
+       // surface distance
+       frac = plane->dist;
+       if (side)
+       {
+               frac -= DIST_EPSILON;
+               VectorNegate (plane->normal, RHC.trace->plane.normal);
+               RHC.trace->plane.dist = -plane->dist;
+       }
+       else
+       {
+               frac += DIST_EPSILON;
+               VectorCopy (plane->normal, RHC.trace->plane.normal);
+               RHC.trace->plane.dist = plane->dist;
+       }
+
+       if (plane->type < 3)
+       {
+               t1 = RHC.start[plane->type] - frac;
+               t2 = RHC.start[plane->type] + RHC.dist[plane->type] - frac;
+       }
+       else
+       {
+               t1 = plane->normal[0] * RHC.start[0] + plane->normal[1] * RHC.start[1] + plane->normal[2] * RHC.start[2] - frac;
+               t2 = plane->normal[0] * (RHC.start[0] + RHC.dist[0]) + plane->normal[1] * (RHC.start[1] + RHC.dist[1]) + plane->normal[2] * (RHC.start[2] + RHC.dist[2]) - frac;
+       }
+
+       frac = t1 / (t1 - t2);
+       frac = bound(0.0f, frac, 1.0f);
+
+       RHC.trace->fraction = frac;
+       RHC.trace->endpos[0] = RHC.start[0] + frac * RHC.dist[0];
+       RHC.trace->endpos[1] = RHC.start[1] + frac * RHC.dist[1];
+       RHC.trace->endpos[2] = RHC.start[2] + frac * RHC.dist[2];
+}
+
+int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
 {
        dclipnode_t     *node;
-       mplane_t        *plane;
-       float           t1, t2;
-       float           frac;
-       int                     i;
        vec3_t          mid;
        int                     side;
        float           midf;
+       // LordHavoc: FIXME: this is not thread safe...  if threading matters here,
+       // remove the static prefixes
+       static int ret;
+       static mplane_t *plane;
+       static float t1, t2, frac;
 
+       // LordHavoc: a goto!  everyone flee in terror... :)
 loc0:
-// check for empty
+       // check for empty
        if (num < 0)
        {
-               if (num != CONTENTS_SOLID)
+               RHC.trace->endcontents = num;
+               if (RHC.trace->startcontents)
                {
-                       trace->allsolid = false;
-                       if (num == CONTENTS_EMPTY)
-                               trace->inopen = true;
+                       if (num == RHC.trace->startcontents)
+                               RHC.trace->allsolid = false;
                        else
-                               trace->inwater = true;
+                       {
+                               // if the first leaf is solid, set startsolid
+                               if (RHC.trace->allsolid)
+                                       RHC.trace->startsolid = true;
+                               return HULLCHECKSTATE_SOLID;
+                       }
+                       return HULLCHECKSTATE_EMPTY;
                }
                else
-                       trace->startsolid = true;
-               return true;            // empty
+               {
+                       if (num != CONTENTS_SOLID)
+                       {
+                               RHC.trace->allsolid = false;
+                               if (num == CONTENTS_EMPTY)
+                                       RHC.trace->inopen = true;
+                               else
+                                       RHC.trace->inwater = true;
+                       }
+                       else
+                       {
+                               // if the first leaf is solid, set startsolid
+                               if (RHC.trace->allsolid)
+                                       RHC.trace->startsolid = true;
+                               return HULLCHECKSTATE_SOLID;
+                       }
+                       return HULLCHECKSTATE_EMPTY;
+               }
        }
 
-       if (num < hull->firstclipnode || num > hull->lastclipnode)
-               Sys_Error ("SV_RecursiveHullCheck: bad node number");
-
-//
-// find the point distances
-//
-       node = hull->clipnodes + num;
-       plane = hull->planes + node->planenum;
+       // find the point distances
+       node = RHC.hull->clipnodes + num;
 
-       t1 = PlaneDiff(p1, plane);
-       t2 = PlaneDiff(p2, plane);
-       
-#if 1
-       if (t1 >= 0 && t2 >= 0)
-       // LordHavoc: optimized recursion
-//             return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
-       {
-               num = node->children[0];
-               goto loc0;
-       }
-       if (t1 < 0 && t2 < 0)
-//             return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+       plane = RHC.hull->planes + node->planenum;
+       if (plane->type < 3)
        {
-               num = node->children[1];
-               goto loc0;
+               t1 = p1[plane->type] - plane->dist;
+               t2 = p2[plane->type] - plane->dist;
        }
-#else
-       if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
-               return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
-       if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
-               return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
-#endif
-
-// put the crosspoint DIST_EPSILON pixels on the near side
-       if (t1 < 0)
-               frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1);
        else
-               frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1);
-               
-       midf = p1f + (p2f - p1f)*frac;
-       mid[0] = p1[0] + frac*(p2[0] - p1[0]);
-       mid[1] = p1[1] + frac*(p2[1] - p1[1]);
-       mid[2] = p1[2] + frac*(p2[2] - p1[2]);
-
-       side = (t1 < 0);
-
-// move up to the node
-       if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
-               return false;
-
-#ifdef PARANOID
-       if (SV_HullPointContents (hull, node->children[side], mid) == CONTENTS_SOLID)
-       {
-               Con_Printf ("mid PointInHullSolid\n");
-               return false;
-       }
-#endif
-
-       if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID)
-// go past the node
-               return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
-       // mid would need to be duplicated during recursion...
-*/
-       /*
        {
-               p1f = midf;
-               p1 = mid;
-               num = node->children[side^1];
-               goto loc0;
+               t1 = DotProduct (plane->normal, p1) - plane->dist;
+               t2 = DotProduct (plane->normal, p2) - plane->dist;
        }
-       */
-/*
 
-       if (trace->allsolid)
-               return false;           // never got out of the solid area
-       
-//==================
-// the other side of the node is solid, this is the impact point
-//==================
-       if (!side)
+       // LordHavoc: rearranged the side/frac code
+       if (t1 >= 0)
        {
-               VectorCopy (plane->normal, trace->plane.normal);
-               trace->plane.dist = plane->dist;
+               if (t2 >= 0)
+               {
+                       num = node->children[0];
+                       goto loc0;
+               }
+               // put the crosspoint DIST_EPSILON pixels on the near side
+               side = 0;
        }
        else
        {
-               VectorNegate (plane->normal, trace->plane.normal);
-               trace->plane.dist = -plane->dist;
-       }
-
-       while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID)
-       { // shouldn't really happen, but does occasionally
-               frac -= 0.1;
-               if (frac < 0)
+               if (t2 < 0)
                {
-                       trace->fraction = midf;
-                       VectorCopy (mid, trace->endpos);
-                       Con_DPrintf ("backup past 0\n");
-                       return false;
+                       num = node->children[1];
+                       goto loc0;
                }
-               midf = p1f + (p2f - p1f)*frac;
-               for (i=0 ; i<3 ; i++)
-                       mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+               // put the crosspoint DIST_EPSILON pixels on the near side
+               side = 1;
        }
 
-       trace->fraction = midf;
-       VectorCopy (mid, trace->endpos);
+       frac = t1 / (t1 - t2);
+       frac = bound(0.0f, frac, 1.0f);
 
-       return false;
+       midf = p1f + ((p2f - p1f) * frac);
+       mid[0] = RHC.start[0] + midf * RHC.dist[0];
+       mid[1] = RHC.start[1] + midf * RHC.dist[1];
+       mid[2] = RHC.start[2] + midf * RHC.dist[2];
+
+       // front side first
+       ret = SV_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
+       if (ret != HULLCHECKSTATE_EMPTY)
+               return ret; // solid or done
+       ret = SV_RecursiveHullCheck (node->children[!side], midf, p2f, mid, p2);
+       if (ret != HULLCHECKSTATE_SOLID)
+               return ret; // empty or done
+
+       // front is air and back is solid, this is the impact point...
+       SV_RecursiveHullCheck_Impact(RHC.hull->planes + node->planenum, side);
+
+       return HULLCHECKSTATE_DONE;
 }
-*/
 
-// LordHavoc: backported from my optimizations to PM_RecursiveHullCheck in QuakeForge newtree (QW)
-qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
+/*
+qboolean SV_RecursiveHullCheckContentBoundary (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
 {
        dclipnode_t     *node;
        mplane_t        *plane;
@@ -732,16 +748,10 @@ loc0:
 // check for empty
        if (num < 0)
        {
-               if (num != CONTENTS_SOLID)
-               {
-                       trace->allsolid = false;
-                       if (num == CONTENTS_EMPTY)
-                               trace->inopen = true;
-                       else
-                               trace->inwater = true;
-               }
-               else
+               if (num != trace->startcontents)
                        trace->startsolid = true;
+               else
+                       trace->allsolid = false;
                return true;            // empty
        }
 
@@ -760,49 +770,61 @@ loc0:
                t2 = DotProduct (plane->normal, p2) - plane->dist;
        }
 
+       // LordHavoc: rearranged the side/frac code
        // LordHavoc: recursion optimization
-       if (t1 >= 0 && t2 >= 0)
+       if (t1 >= 0)
        {
-               num = node->children[0];
-               goto loc0;
+               if (t2 >= 0)
+               {
+                       num = node->children[0];
+                       goto loc0;
+               }
+               // put the crosspoint DIST_EPSILON pixels on the near side
+               side = 0;
        }
-       if (t1 < 0 && t2 < 0)
+       else
        {
-               num = node->children[1];
-               goto loc0;
+               if (t2 < 0)
+               {
+                       num = node->children[1];
+                       goto loc0;
+               }
+               // put the crosspoint DIST_EPSILON pixels on the near side
+               side = 1;
        }
 
-// put the crosspoint DIST_EPSILON pixels on the near side
-       side = (t1 < 0);
-       if (side)
-               frac = bound(0, (t1 + DIST_EPSILON) / (t1 - t2), 1);
-       else
-               frac = bound(0, (t1 - DIST_EPSILON) / (t1 - t2), 1);
-               
-       midf = p1f + (p2f - p1f)*frac;
-       for (i=0 ; i<3 ; i++)
-               mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+       frac = t1 / (t1 - t2);
+       frac = bound(0.0f, frac, 1.0f);
+
+       midf = p1f + ((p2f - p1f) * frac);
+       mid[0] = p1[0] + ((p2[0] - p1[0]) * frac);
+       mid[1] = p1[1] + ((p2[1] - p1[1]) * frac);
+       mid[2] = p1[2] + ((p2[2] - p1[2]) * frac);
 
 // move up to the node
        if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
                return false;
 
+*/
+       /*
 #ifdef PARANOID
-       if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) == CONTENTS_SOLID)
+       if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) != trace->startcontents)
        {
                Con_Printf ("mid PointInHullSolid\n");
                return false;
        }
 #endif
+       */
+/*
 
        // LordHavoc: warning to the clumsy, this recursion can not be optimized because mid would need to be duplicated on a stack
-       if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID)
+       if (SV_HullPointContents (hull, node->children[side^1], mid) == trace->startcontents)
 // go past the node
                return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
-       
+
        if (trace->allsolid)
                return false;           // never got out of the solid area
-               
+
 //==================
 // the other side of the node is solid, this is the impact point
 //==================
@@ -817,8 +839,11 @@ loc0:
                trace->plane.dist = -plane->dist;
        }
 
-       while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID)
-       { // shouldn't really happen, but does occasionally
+*/
+       /*
+       while (SV_HullPointContents (hull, hull->firstclipnode, mid) != trace->startcontents)
+       {
+               // shouldn't really happen, but does occasionally
                frac -= 0.1;
                if (frac < 0)
                {
@@ -828,15 +853,30 @@ loc0:
                        return false;
                }
                midf = p1f + (p2f - p1f)*frac;
-               for (i=0 ; i<3 ; i++)
-                       mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+               mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+               mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+               mid[2] = p1[2] + frac*(p2[2] - p1[2]);
        }
+       */
+/*
+
+       frac = t1;
+       if (side)
+               frac += DIST_EPSILON;
+       else
+               frac -= DIST_EPSILON;
 
-       trace->fraction = midf;
-       VectorCopy (mid, trace->endpos);
+       frac /= (t1 - t2);
+       frac = bound(0.0f, frac, 1.0f);
+
+       trace->fraction = p1f + (p2f - p1f)*frac;
+       trace->endpos[0] = p1[0] + frac*(p2[0] - p1[0]);
+       trace->endpos[1] = p1[1] + frac*(p2[1] - p1[1]);
+       trace->endpos[2] = p1[2] + frac*(p2[2] - p1[2]);
 
        return false;
 }
+*/
 
 qboolean SV_TestLine (hull_t *hull, int num, vec3_t p1, vec3_t p2)
 {
@@ -858,44 +898,98 @@ loc0:
 // find the point distances
 //
        node = hull->clipnodes + num;
+       if (node->children[0] < 0)
+       {
+               if (node->children[0] == CONTENTS_SOLID)
+                       return false;
+               if (node->children[1] < 0)
+                       return node->children[1] != CONTENTS_SOLID;
+       }
+       else if (node->children[1] == CONTENTS_SOLID)
+               return false;
+
        plane = hull->planes + node->planenum;
 
-       t1 = PlaneDiff(p1, plane);
-       t2 = PlaneDiff(p2, plane);
-       
-       if (t1 >= 0 && t2 >= 0)
+       if (plane->type < 3)
        {
-               num = node->children[0];
-               goto loc0;
+               t1 = p1[plane->type] - plane->dist;
+               t2 = p2[plane->type] - plane->dist;
        }
-       if (t1 < 0 && t2 < 0)
+       else
        {
-               num = node->children[1];
-               goto loc0;
+               t1 = DotProduct (plane->normal, p1) - plane->dist;
+               t2 = DotProduct (plane->normal, p2) - plane->dist;
        }
 
-// put the crosspoint DIST_EPSILON pixels on the near side
-       side = (t1 < 0);
-
-       if (side)
-               frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1);
+       if (t1 >= 0)
+       {
+               if (t2 >= 0)
+               {
+                       num = node->children[0];
+                       goto loc0;
+               }
+               side = 0;
+       }
        else
-               frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1);
-               
-       mid[0] = p1[0] + frac*(p2[0] - p1[0]);
-       mid[1] = p1[1] + frac*(p2[1] - p1[1]);
-       mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+       {
+               if (t2 < 0)
+               {
+                       num = node->children[1];
+                       goto loc0;
+               }
+               side = 1;
+       }
 
        if (node->children[side] < 0)
        {
                if (node->children[side] == CONTENTS_SOLID)
                        return false;
-               return SV_TestLine(hull, node->children[!side], mid, p2);
+
+               if (node->children[!side] < 0)
+                       return node->children[!side] != CONTENTS_SOLID;
+               else
+               {
+                       frac = t1 / (t1 - t2);
+                       frac = bound(0, frac, 1);
+
+                       mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+                       mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+                       mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+                       return SV_TestLine(hull, node->children[!side], mid, p2);
+               }
        }
-       else if (SV_TestLine(hull, node->children[side], p1, mid))
-               return SV_TestLine(hull, node->children[!side], mid, p2);
        else
-               return false;
+       {
+               if (node->children[!side] < 0)
+               {
+                       if (node->children[!side] == CONTENTS_SOLID)
+                               return false;
+
+                       frac = t1 / (t1 - t2);
+                       frac = bound(0, frac, 1);
+
+                       mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+                       mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+                       mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+                       return SV_TestLine(hull, node->children[side], p1, mid);
+               }
+               else
+               {
+                       frac = t1 / (t1 - t2);
+                       frac = bound(0, frac, 1);
+
+                       mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+                       mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+                       mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+                       if (SV_TestLine(hull, node->children[side], p1, mid))
+                               return SV_TestLine(hull, node->children[!side], mid, p2);
+                       else
+                               return false;
+               }
+       }
 }
 
 
@@ -947,7 +1041,11 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
        }
 
 // trace a line through the apropriate clipping hull
-       SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
+       VectorCopy(start_l, RecursiveHullCheckInfo.start);
+       VectorSubtract(end_l, start_l, RecursiveHullCheckInfo.dist);
+       RecursiveHullCheckInfo.hull = hull;
+       RecursiveHullCheckInfo.trace = &trace;
+       SV_RecursiveHullCheck (hull->firstclipnode, 0, 1, start_l, end_l);
 
 // LordHavoc: enabling rotating bmodels
        // rotate endpos back to world frame of reference
@@ -1149,7 +1247,7 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e
                VectorCopy (mins, clip.mins2);
                VectorCopy (maxs, clip.maxs2);
        }
-       
+
 // create the bounding box of the entire move
        SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
 
diff --git a/world.h b/world.h
index c6cc8a8367e369c3771af3ec6da005fd6b19ee36..7de90a32ba973694ae44bebc811bcd41e0390cf2 100644 (file)
--- a/world.h
+++ b/world.h
@@ -8,7 +8,7 @@ of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 See the GNU General Public License for more details.
 
@@ -34,9 +34,9 @@ typedef struct
        vec3_t  endpos;                 // final position
        plane_t plane;                  // surface normal at impact
        edict_t *ent;                   // entity the surface is on
-       // LordHavoc: added texture and lighting to traceline
-       char    *texturename;
-       vec3_t  light;
+       int             startcontents;  // if not zero, treats this value as empty, and
+                                                       // all others as solid (impact on content change)
+       int             endcontents;    // set to the contents that was hit at the end point
 } trace_t;
 
 
@@ -82,4 +82,17 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e
 
 // passedict is explicitly excluded from clipping checks (normally NULL)
 
-extern qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
+int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2);
+
+typedef struct
+{
+       hull_t *hull;
+       trace_t *trace;
+       vec3_t start;
+       vec3_t dist;
+}
+RecursiveHullCheckTraceInfo_t;
+
+// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass
+// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc...
+extern RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo;