]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
optimized AngleVectors calls (pass NULL for vectors that should not be generated)
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 6 Apr 2001 03:10:06 +0000 (03:10 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 6 Apr 2001 03:10:06 +0000 (03:10 +0000)
added VectorVectors (takes a forward unit vector, makes right and up vectors)
corrected silly id spelling mistakes 'allready' and 'allways'
most host_frametime references changed to cl.frametime or sv.frametime
fixed movement interpolation in listen games (host client wasn't lerping the framerate capped server's frames)
added EF_FLAME effect, untested
changed svc_showlmp to use shorts, not bytes (except in nehahra compatibility mode)
broke svc_fog for now
removed svc_farclip
removed svc_playerposition
removed svc_skybox
increased maximum number of models and sounds to 1024 each (and added extra svc_ messages and update bits to handle the new limits)
made punchangle use preciseangles (on DP servers), added punchvector (view origin kick, useful for earthquakes?)
redesigned entire animation interpolation system (can lerp between independently playing framegroups)
redesigned animation scene lookup in model and sprite rendering to use a single system
added a simple clientside effect system (meant for playing sprite explosion animations entirely on the client, with very nice interpolation and framerate control)
added te_smallflash
added te_customflash
added te_flamejet (untested)
darkened lightning glow and made it adjustable (r_glowinglightning cvar is now a scaler, not just an option)
increased maximum number of clientside entities
COM_WriteFile will now create a path leading up to the file
removed cpu_*.* files
reorganized fractalnoise code, now behaves more correctly
stripped out qsg_version stuff, replaced by pr_checkextension and extensions have changed completely (extensions are documented in dpextensions.qc in DP mod and release zips)
made skin and sprite mipmapping optional (r_mipskins cvar, r_mipsprites cvar), saves about 32% of texture memory if disabled
rewrote texture management system (again), now uses flags to specify texture attributes (all textures without the PRECACHE flag are uploaded only when first used, conserves huge amounts of memory), and is cleaner code
r_precachetextures cvar controls how PRECACHE texture flag is used (0 = never precache, 1 = use PRECACHE flag, 2 = always precache)
changed way text filtering mode is decided
now requires vertex array support (standard in OpenGL 1.1 so this is not a problem)
takes advantage of GL_EXT_compiled_vertex_array extension (no speed gain for my Geforce2, may help other people)
reverted to GL transforms for models (no speed gain for my Geforce2, may help other people)
gl_transform cvar controls whether to use GL transforms (1) or software transforms (0), could not measure any speed difference in my testing
r_shadows removed due to GL transforms on models
model and sprite interpolation now handle 4 frame interpolation to accomodate new interpolation system
RSurf_Draw* functions greatly optimized
Host_Error will now Sys_Error rather than crash if Host_Frame has not yet been executed
cleaned up viewthing frame reporting code, now uses the new animation system
can now look directly up and down
ByteToNormal and NormalToByte added in mathlib.c, also moved anorms.h table to mathlib.c
added axial cases for BoxOnPlaneSide (BIG improvement)
trivert2 vertex format removed, now uses alias trivertx_t format as-is (33% less model memory usage and possibly quicker loading)
redesigned map texture loading again (particularly HL maps)
water is now lit on both sides
sprites are now cached like models
sprite loading redesigned to use new animation system
increased maximum packet size to accomodate the largest possible
PF_vectoyaw optimized a little
PF_vectoangles optimized a little
PF_findchain added
PF_findchainfloat added
PF_effect added
PF_te_blood added
PF_te_bloodshower added
PF_te_explosionrgb added
PF_te_particlecube added
PF_te_particlerain added
PF_te_particlesnow added
PF_te_spark added
PF_te_gunshotquad added
PF_te_spikequad added
PF_te_superspikequad added
PF_te_explosionquad added
PF_te_smallflash added
PF_te_customflash added
PF_te_gunshot added
PF_te_spike added
PF_te_superspike added
PF_te_explosion added
PF_te_tarexplosion added
PF_te_wizspike added
PF_te_knightspike added
PF_te_lavasplash added
PF_te_teleport added
PF_te_explosion2 added
PF_te_lightning1 added
PF_te_lightning2 added
PF_te_lightning3 added
PF_te_beam added
PF_vectorvectors added
increased maximum file path length
explosions are no longer round
removed LIGHTSCALE settings
removed r_donttransformmodels cvar
a lot of particle effect changes (bouncing sparks, blood sprays from gibs that stick on the walls)
fixed sound combining so it no longer plays past the end of the buffer
fixed sound resampling

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

81 files changed:
anorms.h [deleted file]
chase.c
cl_demo.c
cl_input.c
cl_main.c
cl_parse.c
cl_tent.c
client.h
cmd.c
cmd.h
common.c
common.h
cpu_noasm.c [deleted file]
cpu_x86.bat [deleted file]
cpu_x86.nasm [deleted file]
cpu_x86.obj [deleted file]
cvar.c
cvar.h
draw.h
fractalnoise.c
gl_draw.c
gl_models.c
gl_poly.c
gl_poly.h
gl_rmain.c
gl_rsurf.c
gl_screen.c
gl_textures.c
gl_warp.c
glquake.h
host.c
host_cmd.c
image.c
image.h
in_svgalib.c
in_win.c
makefile
mathlib.c
mathlib.h
menu.c
model_alias.c
model_alias.h
model_brush.c
model_brush.h
model_shared.c
model_shared.h
model_sprite.c
model_sprite.h
net.h
pr_cmds.c
pr_edict.c
progs.h
protocol.h
quakedef.h
r_crosshairs.c
r_explosion.c
r_lerpanim.c [new file with mode: 0644]
r_lerpanim.h [new file with mode: 0644]
r_light.c
r_light.h
r_part.c
r_sprites.c
r_textures.h [new file with mode: 0644]
render.h
server.h
snd_dma.c
snd_mem.c
snd_mix.c
snd_win.c
sv_main.c
sv_phys.c
sv_user.c
sys_win.c
vid.h
vid_3dfxsvga.c
vid_glx.c
vid_shared.c
vid_wgl.c
view.c
world.c
zone.c

diff --git a/anorms.h b/anorms.h
deleted file mode 100644 (file)
index 11a9007..0000000
--- a/anorms.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-*/
-{-0.525731, 0.000000, 0.850651}, 
-{-0.442863, 0.238856, 0.864188}, 
-{-0.295242, 0.000000, 0.955423}, 
-{-0.309017, 0.500000, 0.809017}, 
-{-0.162460, 0.262866, 0.951056}, 
-{0.000000, 0.000000, 1.000000}, 
-{0.000000, 0.850651, 0.525731}, 
-{-0.147621, 0.716567, 0.681718}, 
-{0.147621, 0.716567, 0.681718}, 
-{0.000000, 0.525731, 0.850651}, 
-{0.309017, 0.500000, 0.809017}, 
-{0.525731, 0.000000, 0.850651}, 
-{0.295242, 0.000000, 0.955423}, 
-{0.442863, 0.238856, 0.864188}, 
-{0.162460, 0.262866, 0.951056}, 
-{-0.681718, 0.147621, 0.716567}, 
-{-0.809017, 0.309017, 0.500000}, 
-{-0.587785, 0.425325, 0.688191}, 
-{-0.850651, 0.525731, 0.000000}, 
-{-0.864188, 0.442863, 0.238856}, 
-{-0.716567, 0.681718, 0.147621}, 
-{-0.688191, 0.587785, 0.425325}, 
-{-0.500000, 0.809017, 0.309017}, 
-{-0.238856, 0.864188, 0.442863}, 
-{-0.425325, 0.688191, 0.587785}, 
-{-0.716567, 0.681718, -0.147621}, 
-{-0.500000, 0.809017, -0.309017}, 
-{-0.525731, 0.850651, 0.000000}, 
-{0.000000, 0.850651, -0.525731}, 
-{-0.238856, 0.864188, -0.442863}, 
-{0.000000, 0.955423, -0.295242}, 
-{-0.262866, 0.951056, -0.162460}, 
-{0.000000, 1.000000, 0.000000}, 
-{0.000000, 0.955423, 0.295242}, 
-{-0.262866, 0.951056, 0.162460}, 
-{0.238856, 0.864188, 0.442863}, 
-{0.262866, 0.951056, 0.162460}, 
-{0.500000, 0.809017, 0.309017}, 
-{0.238856, 0.864188, -0.442863}, 
-{0.262866, 0.951056, -0.162460}, 
-{0.500000, 0.809017, -0.309017}, 
-{0.850651, 0.525731, 0.000000}, 
-{0.716567, 0.681718, 0.147621}, 
-{0.716567, 0.681718, -0.147621}, 
-{0.525731, 0.850651, 0.000000}, 
-{0.425325, 0.688191, 0.587785}, 
-{0.864188, 0.442863, 0.238856}, 
-{0.688191, 0.587785, 0.425325}, 
-{0.809017, 0.309017, 0.500000}, 
-{0.681718, 0.147621, 0.716567}, 
-{0.587785, 0.425325, 0.688191}, 
-{0.955423, 0.295242, 0.000000}, 
-{1.000000, 0.000000, 0.000000}, 
-{0.951056, 0.162460, 0.262866}, 
-{0.850651, -0.525731, 0.000000}, 
-{0.955423, -0.295242, 0.000000}, 
-{0.864188, -0.442863, 0.238856}, 
-{0.951056, -0.162460, 0.262866}, 
-{0.809017, -0.309017, 0.500000}, 
-{0.681718, -0.147621, 0.716567}, 
-{0.850651, 0.000000, 0.525731}, 
-{0.864188, 0.442863, -0.238856}, 
-{0.809017, 0.309017, -0.500000}, 
-{0.951056, 0.162460, -0.262866}, 
-{0.525731, 0.000000, -0.850651}, 
-{0.681718, 0.147621, -0.716567}, 
-{0.681718, -0.147621, -0.716567}, 
-{0.850651, 0.000000, -0.525731}, 
-{0.809017, -0.309017, -0.500000}, 
-{0.864188, -0.442863, -0.238856}, 
-{0.951056, -0.162460, -0.262866}, 
-{0.147621, 0.716567, -0.681718}, 
-{0.309017, 0.500000, -0.809017}, 
-{0.425325, 0.688191, -0.587785}, 
-{0.442863, 0.238856, -0.864188}, 
-{0.587785, 0.425325, -0.688191}, 
-{0.688191, 0.587785, -0.425325}, 
-{-0.147621, 0.716567, -0.681718}, 
-{-0.309017, 0.500000, -0.809017}, 
-{0.000000, 0.525731, -0.850651}, 
-{-0.525731, 0.000000, -0.850651}, 
-{-0.442863, 0.238856, -0.864188}, 
-{-0.295242, 0.000000, -0.955423}, 
-{-0.162460, 0.262866, -0.951056}, 
-{0.000000, 0.000000, -1.000000}, 
-{0.295242, 0.000000, -0.955423}, 
-{0.162460, 0.262866, -0.951056}, 
-{-0.442863, -0.238856, -0.864188}, 
-{-0.309017, -0.500000, -0.809017}, 
-{-0.162460, -0.262866, -0.951056}, 
-{0.000000, -0.850651, -0.525731}, 
-{-0.147621, -0.716567, -0.681718}, 
-{0.147621, -0.716567, -0.681718}, 
-{0.000000, -0.525731, -0.850651}, 
-{0.309017, -0.500000, -0.809017}, 
-{0.442863, -0.238856, -0.864188}, 
-{0.162460, -0.262866, -0.951056}, 
-{0.238856, -0.864188, -0.442863}, 
-{0.500000, -0.809017, -0.309017}, 
-{0.425325, -0.688191, -0.587785}, 
-{0.716567, -0.681718, -0.147621}, 
-{0.688191, -0.587785, -0.425325}, 
-{0.587785, -0.425325, -0.688191}, 
-{0.000000, -0.955423, -0.295242}, 
-{0.000000, -1.000000, 0.000000}, 
-{0.262866, -0.951056, -0.162460}, 
-{0.000000, -0.850651, 0.525731}, 
-{0.000000, -0.955423, 0.295242}, 
-{0.238856, -0.864188, 0.442863}, 
-{0.262866, -0.951056, 0.162460}, 
-{0.500000, -0.809017, 0.309017}, 
-{0.716567, -0.681718, 0.147621}, 
-{0.525731, -0.850651, 0.000000}, 
-{-0.238856, -0.864188, -0.442863}, 
-{-0.500000, -0.809017, -0.309017}, 
-{-0.262866, -0.951056, -0.162460}, 
-{-0.850651, -0.525731, 0.000000}, 
-{-0.716567, -0.681718, -0.147621}, 
-{-0.716567, -0.681718, 0.147621}, 
-{-0.525731, -0.850651, 0.000000}, 
-{-0.500000, -0.809017, 0.309017}, 
-{-0.238856, -0.864188, 0.442863}, 
-{-0.262866, -0.951056, 0.162460}, 
-{-0.864188, -0.442863, 0.238856}, 
-{-0.809017, -0.309017, 0.500000}, 
-{-0.688191, -0.587785, 0.425325}, 
-{-0.681718, -0.147621, 0.716567}, 
-{-0.442863, -0.238856, 0.864188}, 
-{-0.587785, -0.425325, 0.688191}, 
-{-0.309017, -0.500000, 0.809017}, 
-{-0.147621, -0.716567, 0.681718}, 
-{-0.425325, -0.688191, 0.587785}, 
-{-0.162460, -0.262866, 0.951056}, 
-{0.442863, -0.238856, 0.864188}, 
-{0.162460, -0.262866, 0.951056}, 
-{0.309017, -0.500000, 0.809017}, 
-{0.147621, -0.716567, 0.681718}, 
-{0.000000, -0.525731, 0.850651}, 
-{0.425325, -0.688191, 0.587785}, 
-{0.587785, -0.425325, 0.688191}, 
-{0.688191, -0.587785, 0.425325}, 
-{-0.955423, 0.295242, 0.000000}, 
-{-0.951056, 0.162460, 0.262866}, 
-{-1.000000, 0.000000, 0.000000}, 
-{-0.850651, 0.000000, 0.525731}, 
-{-0.955423, -0.295242, 0.000000}, 
-{-0.951056, -0.162460, 0.262866}, 
-{-0.864188, 0.442863, -0.238856}, 
-{-0.951056, 0.162460, -0.262866}, 
-{-0.809017, 0.309017, -0.500000}, 
-{-0.864188, -0.442863, -0.238856}, 
-{-0.951056, -0.162460, -0.262866}, 
-{-0.809017, -0.309017, -0.500000}, 
-{-0.681718, 0.147621, -0.716567}, 
-{-0.681718, -0.147621, -0.716567}, 
-{-0.850651, 0.000000, -0.525731}, 
-{-0.688191, 0.587785, -0.425325}, 
-{-0.587785, 0.425325, -0.688191}, 
-{-0.425325, 0.688191, -0.587785}, 
-{-0.425325, -0.688191, -0.587785}, 
-{-0.587785, -0.425325, -0.688191}, 
-{-0.688191, -0.587785, -0.425325}, 
diff --git a/chase.c b/chase.c
index 21893960b14923dcea732e5455352eddf9276200..9bab5473dc09a8be7f207cb73b6008f13add33f9 100644 (file)
--- a/chase.c
+++ b/chase.c
@@ -53,13 +53,13 @@ float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
 
 void Chase_Update (void)
 {
-       vec3_t  forward, up, right, stop, chase_dest, normal;
+       vec3_t  forward, stop, chase_dest, normal;
        float   dist;
 
        chase_back.value = bound(0, chase_back.value, 128);
        chase_up.value = bound(-64, chase_up.value, 64);
 
-       AngleVectors (cl.viewangles, forward, right, up);
+       AngleVectors (cl.viewangles, forward, NULL, NULL);
 
        dist = -chase_back.value - 8;
        chase_dest[0] = r_refdef.vieworg[0] + forward[0] * dist;
index 13fbed5b0ad43a0fcec26737b500c0da129bc92d..85873db36349a3cca5cb578361209ff137452869 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -101,12 +101,12 @@ int CL_GetMessage (void)
                        return 0;
 
        // decide if it is time to grab the next message                
-               if (cls.signon == SIGNONS)      // allways grab until fully connected
+               if (cls.signon == SIGNONS)      // always grab until fully connected
                {
                        if (cls.timedemo)
                        {
                                if (host_framecount == cls.td_lastframe)
-                                       return 0;               // allready read this frame's message
+                                       return 0;               // already read this frame's message
                                cls.td_lastframe = host_framecount;
                        // if this is the second frame, grab the real td_starttime
                        // so the bogus time on the first frame doesn't count
index f3432d2230a5022a153e6daf128d261a1c408ea6..21f084ff820047266da4dffe4f9ec72a314f2715 100644 (file)
@@ -253,9 +253,9 @@ void CL_AdjustAngles (void)
        float   up, down;
        
        if (in_speed.state & 1)
-               speed = host_frametime * cl_anglespeedkey.value;
+               speed = cl.frametime * cl_anglespeedkey.value;
        else
-               speed = host_frametime;
+               speed = cl.frametime;
 
        if (!(in_strafe.state & 1))
        {
@@ -430,8 +430,7 @@ void CL_SendMove (usercmd_t *cmd)
                return;
 
 //
-// allways dump the first two message, because it may contain leftover inputs
-// from the last level
+// always dump the first two messages, because they may contain leftover inputs from the last level
 //
        if (++cl.movemessages <= 2)
                return;
index 1abbfd2fe3a5498f233d3b5499a6d4f05413d803..7a6623a102212c0725c05a2058d0ec3aa341b52d 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -175,9 +175,6 @@ void CL_EstablishConnection (char *host)
        cls.signon = 0;                         // need all the signon messages before playing
 }
 
-extern int numgltextures;
-extern int texels;
-
 /*
 =====================
 CL_SignonReply
@@ -224,8 +221,6 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
                
        case 4:
                SCR_EndLoadingPlaque ();                // allow normal screen updates
-               // LordHavoc: debugging purposes
-               Con_DPrintf("Texture slots in use: %i : %i : %i texels\n", texture_extension_number, numgltextures, texels);
                break;
        }
 }
@@ -280,8 +275,7 @@ void CL_PrintEntities_f (void)
                        Con_Printf ("EMPTY\n");
                        continue;
                }
-               Con_Printf ("%s:%2i  (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n"
-               ,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]);
+               Con_Printf ("%s:%2i  (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", ent->model->name, ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]);
        }
 }
 
@@ -374,8 +368,9 @@ float       CL_LerpPoint (void)
        float   f, frac;
 
        f = cl.mtime[0] - cl.mtime[1];
-       
-       if (!f || cl_nolerp.value || cls.timedemo || sv.active)
+
+       // LordHavoc: lerp in listen games as the server is being capped below the client (usually)
+       if (!f || cl_nolerp.value || cls.timedemo || (sv.active && svs.maxclients == 1))
        {
                cl.time = cl.mtime[0];
                return 1;
@@ -460,8 +455,8 @@ void CL_RelinkEntities (void)
        {
                if (!ent->model)
                {       // empty slot
-                       if (ent->forcelink)
-                               R_RemoveEfrags (ent);   // just became empty
+//                     if (ent->forcelink)
+//                             R_RemoveEfrags (ent);   // just became empty
                        continue;
                }
 
@@ -470,30 +465,11 @@ void CL_RelinkEntities (void)
                {
                        ent->model = NULL;
                        // LordHavoc: free on the same frame, not the next
-                       if (ent->forcelink)
-                               R_RemoveEfrags (ent);   // just became empty
+//                     if (ent->forcelink)
+//                             R_RemoveEfrags (ent);   // just became empty
                        continue;
                }
 
-               // LordHavoc: animation interpolation, note: framegroups partially override this in the renderer
-               /*
-               if (ent->model != ent->lerp_model || ent->lerp_time > cl.time)
-               {
-                       ent->lerp_frame1 = ent->lerp_frame2 = ent->frame;
-                       ent->lerp_time = cl.time;
-                       ent->lerp = 0;
-               }
-               else if (ent->frame != ent->lerp_frame2)
-               {
-                       ent->lerp_frame1 = ent->lerpframe2;
-                       ent->lerp_frame2 = ent->frame;
-                       ent->lerp_time = cl.time;
-                       ent->lerp = 0;
-               }
-               else
-                       ent->lerp = bound(0, (cl.time - ent->lerp_time) * 10.0f, 1);
-               */
-
                VectorCopy (ent->origin, oldorg);
 
                if (ent->forcelink)
@@ -532,12 +508,12 @@ void CL_RelinkEntities (void)
                        R_EntityParticles (ent);
                if (ent->effects & EF_MUZZLEFLASH)
                {
-                       vec3_t          fv, rv, uv;
+                       vec3_t          fv;
 
                        dl = CL_AllocDlight (i);
                        VectorCopy (ent->origin,  dl->origin);
                        dl->origin[2] += 16;
-                       AngleVectors (ent->angles, fv, rv, uv);
+                       AngleVectors (ent->angles, fv, NULL, NULL);
                         
                        VectorMA (dl->origin, 18, fv, dl->origin);
                        dl->radius = 100 + (rand()&31);
@@ -589,6 +565,25 @@ void CL_RelinkEntities (void)
                        dl->die = cl.time + 0.001;
                        dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
                }
+               else if (ent->effects & EF_FLAME)
+               {
+                       if (ent->model)
+                       {
+                               vec3_t mins, maxs;
+                               int temp;
+                               VectorAdd(ent->origin, ent->model->mins, mins);
+                               VectorAdd(ent->origin, ent->model->maxs, maxs);
+                               // how many flames to make
+                               temp = (int) (cl.time * 30) - (int) (cl.oldtime * 30);
+                               R_FlameCube(mins, maxs, temp);
+                       }
+                       dl = CL_AllocDlight (i);
+                       VectorCopy (ent->origin, dl->origin);
+                       dl->radius = 200 + (rand()&31);
+                       dl->die = cl.time + 0.25;
+                       dl->decay = dl->radius * 4;
+                       dl->color[0] = 1.0;dl->color[1] = 0.7;dl->color[2] = 0.3;
+               }
 
                if (ent->model->flags) // LordHavoc: if the model has no flags, don't check each
                {
@@ -643,10 +638,7 @@ void CL_RelinkEntities (void)
                if (!ent->model || ent->effects & EF_NODRAW)
                        continue;
                if (cl_numvisedicts < MAX_VISEDICTS)
-               {
-                       cl_visedicts[cl_numvisedicts] = ent;
-                       cl_numvisedicts++;
-               }
+                       cl_visedicts[cl_numvisedicts++] = ent;
        }
 
 }
@@ -664,7 +656,7 @@ int CL_ReadFromServer (void)
        int             ret;
 
        cl.oldtime = cl.time;
-       cl.time += host_frametime;
+       cl.time += cl.frametime;
        
        do
        {
@@ -683,6 +675,7 @@ int CL_ReadFromServer (void)
 
        CL_RelinkEntities ();
        CL_UpdateTEnts ();
+       CL_DoEffects ();
 
 //
 // bring the links up to date
@@ -712,7 +705,6 @@ void CL_SendCmd (void)
        
        // send the unreliable message
                CL_SendMove (&cmd);
-       
        }
 
        if (cls.demoplayback)
index 0d776abff948e84593a95c23b6ee3daa19e4a44a..368bf3da43efdc6e8628c7b387ece1ca9e9957ba 100644 (file)
@@ -65,24 +65,25 @@ char *svc_strings[128] =
        "svc_cdtrack",                  // [byte] track [byte] looptrack
        "svc_sellscreen",
        "svc_cutscene",
-       "svc_showlmp",  // [string] iconlabel [string] lmpfile [byte] x [byte] y
+       "svc_showlmp",  // [string] iconlabel [string] lmpfile [short] x [short] y
        "svc_hidelmp",  // [string] iconlabel
-       "svc_skybox", // [string] skyname
-       "?", // 38
-       "?", // 39
-       "?", // 40
-       "?", // 41
-       "?", // 42
-       "?", // 43
-       "?", // 44
-       "?", // 45
-       "?", // 46
-       "?", // 47
-       "?", // 48
-       "?", // 49
-       "svc_farclip", // [coord] size
-       "svc_fog", // [byte] enable <optional past this point, only included if enable is true> [short] density*4096 [byte] red [byte] green [byte] blue
-       "svc_playerposition" // [float] x [float] y [float] z
+       "", // 37
+       "", // 38
+       "", // 39
+       "", // 40
+       "", // 41
+       "", // 42
+       "", // 43
+       "", // 44
+       "", // 45
+       "", // 46
+       "", // 47
+       "", // 48
+       "", // 49
+       "", // 50
+       "svc_fog", // 51
+       "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
+       "svc_effect2", // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
 };
 
 //=============================================================================
@@ -119,14 +120,14 @@ entity_t  *CL_EntityNum (int num)
 CL_ParseStartSoundPacket
 ==================
 */
-void CL_ParseStartSoundPacket(void)
+void CL_ParseStartSoundPacket(int largesoundindex)
 {
     vec3_t  pos;
     int        channel, ent;
     int        sound_num;
     int        volume;
     int        field_mask;
-    float      attenuation;  
+    float      attenuation;
        int             i;
                   
     field_mask = MSG_ReadByte(); 
@@ -142,7 +143,13 @@ void CL_ParseStartSoundPacket(void)
                attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
        
        channel = MSG_ReadShort ();
-       sound_num = MSG_ReadByte ();
+       if (largesoundindex)
+               sound_num = (unsigned short) MSG_ReadShort ();
+       else
+               sound_num = MSG_ReadByte ();
+
+       if (sound_num >= MAX_SOUNDS)
+               Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
 
        ent = channel >> 3;
        channel &= 7;
@@ -455,7 +462,7 @@ relinked.  Other attributes can change without relinking.
 */
 void CL_ParseUpdate (int bits)
 {
-       int                     i, modnum, num, alpha, scale, glowsize, glowcolor, colormod;
+       int                     i, modnum, num, alpha, scale, glowsize, glowcolor, colormod, frame;
        model_t         *model;
        qboolean        forcelink;
        entity_t        *ent;
@@ -511,21 +518,8 @@ void CL_ParseUpdate (int bits)
        modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex;
        if (modnum >= MAX_MODELS)
                Host_Error ("CL_ParseModel: bad modnum");
-       ent->deltabaseline.modelindex = modnum;
-               
-       model = cl.model_precache[modnum];
-       if (model != ent->model)
-       {
-               ent->model = model;
-       // automatic animation (torches, etc) can be either all together
-       // or randomized
-               if (model)
-                       ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
-               else
-                       forcelink = true;       // hack to make null model players work
-       }
 
-       ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
+       frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
 
        i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
        ent->deltabaseline.colormap = i;
@@ -564,14 +558,36 @@ void CL_ParseUpdate (int bits)
        glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize;
        glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor;
        colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod;
-       ent->frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
+       modnum |= ((bits & U_MODEL2) ? (MSG_ReadByte() << 8) : (baseline->modelindex & 0xFF00));
+       frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
+
+       if (modnum >= MAX_MODELS)
+               Host_Error("modnum (%i) >= MAX_MODELS (%i)\n", modnum, MAX_MODELS);
+
+       model = cl.model_precache[modnum];
+       if (model != ent->model)
+       {
+               ent->model = model;
+       // automatic animation (torches, etc) can be either all together
+       // or randomized
+               if (model)
+                       ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
+               else
+                       forcelink = true;       // hack to make null model players work
+       }
+
+       ent->frame = frame;
+       if (model && (unsigned) frame >= model->numframes)
+               Con_DPrintf("CL_ParseUpdate: no such frame %i in \"%s\"\n", frame, model->name);
+
        ent->deltabaseline.alpha = alpha;
        ent->deltabaseline.scale = scale;
        ent->deltabaseline.effects = ent->effects;
        ent->deltabaseline.glowsize = glowsize;
        ent->deltabaseline.glowcolor = glowcolor;
        ent->deltabaseline.colormod = colormod;
-       ent->deltabaseline.frame = ent->frame;
+       ent->deltabaseline.modelindex = modnum;
+       ent->deltabaseline.frame = frame;
        ent->alpha = (float) alpha * (1.0 / 255.0);
        ent->scale = (float) scale * (1.0 / 16.0);
        ent->glowsize = glowsize * 4.0;
@@ -579,7 +595,7 @@ void CL_ParseUpdate (int bits)
        ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0);
        ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0);
        ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0);
-       if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the early Nehahra movie segments
+       if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the Nehahra movie
        {
                i = MSG_ReadFloat();
                ent->alpha = MSG_ReadFloat();
@@ -608,11 +624,14 @@ void CL_ParseUpdate (int bits)
 CL_ParseBaseline
 ==================
 */
-void CL_ParseBaseline (entity_t *ent)
+void CL_ParseBaseline (entity_t *ent, int largemodelindex)
 {
        int                     i;
-       
-       ent->baseline.modelindex = MSG_ReadByte ();
+
+       if (largemodelindex)
+               ent->baseline.modelindex = (unsigned short) MSG_ReadShort ();
+       else
+               ent->baseline.modelindex = MSG_ReadByte ();
        ent->baseline.frame = MSG_ReadByte ();
        ent->baseline.colormap = MSG_ReadByte();
        ent->baseline.skin = MSG_ReadByte();
@@ -626,6 +645,9 @@ void CL_ParseBaseline (entity_t *ent)
        ent->baseline.glowsize = 0;
        ent->baseline.glowcolor = 254;
        ent->baseline.colormod = 255;
+       
+       if (ent->baseline.modelindex >= MAX_MODELS)
+               Host_Error("CL_ParseBaseline: modelindex (%i) >= MAX_MODELS (%i)\n", ent->baseline.modelindex, MAX_MODELS);
 }
 
 
@@ -639,7 +661,13 @@ Server information pertaining to this client only
 void CL_ParseClientdata (int bits)
 {
        int             i, j;
-       
+
+       bits &= 0xFFFF;
+       if (bits & SU_EXTEND1)
+               bits |= (MSG_ReadByte() << 16);
+       if (bits & SU_EXTEND2)
+               bits |= (MSG_ReadByte() << 24);
+
        if (bits & SU_VIEWHEIGHT)
                cl.viewheight = MSG_ReadChar ();
        else
@@ -654,9 +682,18 @@ void CL_ParseClientdata (int bits)
        for (i=0 ; i<3 ; i++)
        {
                if (bits & (SU_PUNCH1<<i) )
-                       cl.punchangle[i] = MSG_ReadChar();
+               {
+                       if (dpprotocol)
+                               cl.punchangle[i] = MSG_ReadPreciseAngle();
+                       else
+                               cl.punchangle[i] = MSG_ReadChar();
+               }
                else
                        cl.punchangle[i] = 0;
+               if (bits & (SU_PUNCHVEC1<<i))
+                       cl.punchvector[i] = MSG_ReadFloatCoord();
+               else
+                       cl.punchvector[i] = 0;
                if (bits & (SU_VELOCITY1<<i) )
                        cl.mvelocity[0][i] = MSG_ReadChar()*16;
                else
@@ -699,7 +736,7 @@ void CL_ParseClientdata (int bits)
 CL_ParseStatic
 =====================
 */
-void CL_ParseStatic (void)
+void CL_ParseStatic (int largemodelindex)
 {
        entity_t *ent;
        int             i;
@@ -709,11 +746,15 @@ void CL_ParseStatic (void)
                Host_Error ("Too many static entities");
        ent = &cl_static_entities[i];
        cl.num_statics++;
-       CL_ParseBaseline (ent);
+       CL_ParseBaseline (ent, largemodelindex);
 
 // copy it to the current state
        ent->model = cl.model_precache[ent->baseline.modelindex];
-       ent->frame = ent->baseline.frame;
+       ent->frame = ent->frame1 = ent->frame2 = ent->baseline.frame;
+       ent->framelerp = 0;
+       ent->lerp_starttime = -1;
+       // make torchs play out of sync
+       ent->frame1start = ent->frame2start = -(rand() & 32767);
        ent->colormap = -1; // no special coloring
        ent->skinnum = ent->baseline.skin;
        ent->effects = ent->baseline.effects;
@@ -738,10 +779,8 @@ void CL_ParseStaticSound (void)
 {
        vec3_t          org;
        int                     sound_num, vol, atten;
-       int                     i;
-       
-       for (i=0 ; i<3 ; i++)
-               org[i] = MSG_ReadCoord ();
+
+       MSG_ReadVector(org);
        sound_num = MSG_ReadByte ();
        vol = MSG_ReadByte ();
        atten = MSG_ReadByte ();
@@ -749,6 +788,34 @@ void CL_ParseStaticSound (void)
        S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
 }
 
+void CL_ParseEffect (void)
+{
+       vec3_t          org;
+       int                     modelindex, startframe, framecount, framerate;
+
+       MSG_ReadVector(org);
+       modelindex = MSG_ReadByte ();
+       startframe = MSG_ReadByte ();
+       framecount = MSG_ReadByte ();
+       framerate = MSG_ReadByte ();
+
+       CL_Effect(org, modelindex, startframe, framecount, framerate);
+}
+
+void CL_ParseEffect2 (void)
+{
+       vec3_t          org;
+       int                     modelindex, startframe, framecount, framerate;
+
+       MSG_ReadVector(org);
+       modelindex = MSG_ReadShort ();
+       startframe = MSG_ReadByte ();
+       framecount = MSG_ReadByte ();
+       framerate = MSG_ReadByte ();
+
+       CL_Effect(org, modelindex, startframe, framecount, framerate);
+}
+
 
 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
 
@@ -919,9 +986,13 @@ void CL_ParseServerMessage (void)
                        break;
                        
                case svc_sound:
-                       CL_ParseStartSoundPacket();
+                       CL_ParseStartSoundPacket(false);
                        break;
-                       
+
+               case svc_sound2:
+                       CL_ParseStartSoundPacket(true);
+                       break;
+
                case svc_stopsound:
                        i = MSG_ReadShort();
                        S_StopSound(i>>3, i&7);
@@ -952,14 +1023,30 @@ void CL_ParseServerMessage (void)
                        R_ParseParticleEffect ();
                        break;
 
+               case svc_effect:
+                       CL_ParseEffect ();
+                       break;
+
+               case svc_effect2:
+                       CL_ParseEffect2 ();
+                       break;
+
                case svc_spawnbaseline:
                        i = MSG_ReadShort ();
                        // must use CL_EntityNum() to force cl.num_entities up
-                       CL_ParseBaseline (CL_EntityNum(i));
+                       CL_ParseBaseline (CL_EntityNum(i), false);
+                       break;
+               case svc_spawnbaseline2:
+                       i = MSG_ReadShort ();
+                       // must use CL_EntityNum() to force cl.num_entities up
+                       CL_ParseBaseline (CL_EntityNum(i), false);
                        break;
                case svc_spawnstatic:
-                       CL_ParseStatic ();
-                       break;                  
+                       CL_ParseStatic (false);
+                       break;
+               case svc_spawnstatic2:
+                       CL_ParseStatic (true);
+                       break;
                case svc_temp_entity:
                        CL_ParseTEnt ();
                        break;
@@ -1037,24 +1124,6 @@ void CL_ParseServerMessage (void)
                case svc_showlmp:
                        SHOWLMP_decodeshow();
                        break;
-       // LordHavoc: extra worldspawn fields (fog, sky, farclip)
-               case svc_skybox:
-                       R_SetSkyBox(MSG_ReadString());
-                       break;
-               case svc_farclip:
-                       r_farclip.value = MSG_ReadCoord();
-                       break;
-               case svc_fog:
-                       if (MSG_ReadByte())
-                       {
-                               fog_density = MSG_ReadShort() * (1.0f / 4096.0f);
-                               fog_red = MSG_ReadByte() * (1.0 / 255.0);
-                               fog_green = MSG_ReadByte() * (1.0 / 255.0);
-                               fog_blue = MSG_ReadByte() * (1.0 / 255.0);
-                       }
-                       else
-                               fog_density = 0.0f;
-                       break;
                }
        }
 }
index 518b1ef417c1d58655a8375976e3bc9ad22a1dd3..1046cbc66337345d721392b9bfac6b4e2f2b7175 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#define MSG_ReadVector(v) {(v)[0] = MSG_ReadCoord();(v)[1] = MSG_ReadCoord();(v)[2] = MSG_ReadCoord();}
-
 cvar_t r_glowinglightning = {"r_glowinglightning", "1", true};
 
 int                    num_temp_entities;
@@ -242,11 +240,11 @@ void CL_ParseTEnt (void)
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte (); // amount of particles
-               R_BloodPuff(pos);
+               R_BloodPuff(pos, dir, count);
                break;
        case TE_BLOOD2: // blood puff
                MSG_ReadVector(pos);
-               R_BloodPuff(pos);
+               R_BloodPuff(pos, vec3_origin, 10);
                break;
        case TE_SPARK:  // spark shower
                MSG_ReadVector(pos);
@@ -398,6 +396,36 @@ void CL_ParseTEnt (void)
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
 
+       case TE_SMALLFLASH:
+               MSG_ReadVector(pos);
+               FindNonSolidLocation(pos);
+               dl = CL_AllocDlight (0);
+               VectorCopy (pos, dl->origin);
+               dl->radius = 200;
+               dl->die = cl.time + 0.2;
+               dl->decay = 1000;
+               dl->color[0] = dl->color[1] = dl->color[2] = 1;
+               break;
+
+       case TE_CUSTOMFLASH:
+               MSG_ReadVector(pos);
+               FindNonSolidLocation(pos);
+               dl = CL_AllocDlight (0);
+               VectorCopy (pos, dl->origin);
+               dl->radius = MSG_ReadByte() * 8;
+               velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
+               dl->die = cl.time + velspeed;
+               dl->decay = dl->radius / velspeed;
+               dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0);
+               break;
+
+       case TE_FLAMEJET:
+               MSG_ReadVector(pos);
+               MSG_ReadVector(dir);
+               count = MSG_ReadByte();
+               R_Flames(pos, dir, count);
+               break;
+
        case TE_LIGHTNING1:                             // lightning bolts
                CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
                break;
@@ -467,15 +495,13 @@ entity_t *CL_NewTempEntity (void)
 {
        entity_t        *ent;
 
-       if (cl_numvisedicts == MAX_VISEDICTS)
+       if (cl_numvisedicts >= MAX_VISEDICTS)
                return NULL;
-       if (num_temp_entities == MAX_TEMP_ENTITIES)
+       if (num_temp_entities >= MAX_TEMP_ENTITIES)
                return NULL;
-       ent = &cl_temp_entities[num_temp_entities];
+       ent = &cl_temp_entities[num_temp_entities++];
        memset (ent, 0, sizeof(*ent));
-       num_temp_entities++;
-       cl_visedicts[cl_numvisedicts] = ent;
-       cl_numvisedicts++;
+       cl_visedicts[cl_numvisedicts++] = ent;
 
        ent->colormap = -1; // no special coloring
        ent->scale = 1;
@@ -559,7 +585,7 @@ void CL_UpdateTEnts (void)
                                VectorCopy (ent->origin,  dl->origin);
                                dl->radius = 100 + (rand()&31);
                                dl->die = cl.time + 0.001;
-                               dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 1;
+                               dl->color[0] = dl->color[1] = dl->color[2] = r_glowinglightning.value * 0.25f;
                        }
 
                        VectorMA(org, 30, dist, org);
index 44fbedf9fb194d9970e4e8d9e29bcd76e34c5f75..9abe25e25db9fa00d82a4ac196c90a60fdb80dcc 100644 (file)
--- a/client.h
+++ b/client.h
@@ -161,6 +161,7 @@ typedef struct
        vec3_t          velocity;               // lerped between mvelocity[0] and [1]
 
        vec3_t          punchangle;             // temporary offset
+       vec3_t          punchvector;    // LordHavoc: origin view kick
        
 // pitch drifting vars
        float           idealpitch;
@@ -185,6 +186,8 @@ typedef struct
                                                                // a lerp point for other data
        double          oldtime;                // previous cl.time, time-oldtime is used
                                                                // to decay light values and smooth step ups
+
+       double          frametime;
        
 
        float           last_received_message;  // (realtime) for net trouble icon
@@ -249,8 +252,9 @@ extern      cvar_t  m_forward;
 extern cvar_t  m_side;
 
 
-#define        MAX_TEMP_ENTITIES       64                      // lightning bolts, etc
-#define        MAX_STATIC_ENTITIES     128                     // torches, etc
+// LordHavoc: raised these from 64 and 128 to 512 and 256
+#define        MAX_TEMP_ENTITIES       512                     // lightning bolts, effects, etc
+#define        MAX_STATIC_ENTITIES     256                     // torches, etc
 
 extern client_state_t  cl;
 
@@ -283,7 +287,8 @@ void CL_Disconnect (void);
 void CL_Disconnect_f (void);
 void CL_NextDemo (void);
 
-#define                        MAX_VISEDICTS   256
+// LordHavoc: raised this from 256 to the maximum possible number of entities visible
+#define                        MAX_VISEDICTS   (MAX_EDICTS + MAX_STATIC_ENTITIES + MAX_TEMP_ENTITIES)
 extern int                             cl_numvisedicts;
 extern entity_t                *cl_visedicts[MAX_VISEDICTS];
 
@@ -306,6 +311,11 @@ void CL_SendMove (usercmd_t *cmd);
 
 void CL_ParseTEnt (void);
 void CL_UpdateTEnts (void);
+void CL_DoEffects (void);
+
+entity_t *CL_NewTempEntity (void);
+
+void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate);
 
 void CL_ClearState (void);
 
diff --git a/cmd.c b/cmd.c
index 6bb726f458f9e8b711435dd717c18fa23906dcd6..85cd55c1f1e02faf34ae0e10a61fefa707363138 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -360,7 +360,7 @@ void Cmd_Alias_f (void)
                return;
        }
 
-       // if the alias allready exists, reuse it
+       // if the alias already exists, reuse it
        for (a = cmd_alias ; a ; a=a->next)
        {
                if (!strcmp(s, a->name))
diff --git a/cmd.h b/cmd.h
index f9eab24ec8d22b3c21be3327df396910711fff6c..da1daa65e7970697c6b3296b74b50107549d32e7 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -96,7 +96,7 @@ char  *Cmd_Argv (int arg);
 char   *Cmd_Args (void);
 // The functions that execute commands get their parameters with these
 // functions. Cmd_Argv () will return an empty string, not a NULL
-// if arg > argc, so string operations are allways safe.
+// if arg > argc, so string operations are always safe.
 
 int Cmd_CheckParm (char *parm);
 // Returns the position (1 to argc-1) in the command's argument list
index 1430e057d6c651cca4470e3630b7ff75bea9e2df..cc4bfd8b68205e8399f775745006106630696d60 100644 (file)
--- a/common.c
+++ b/common.c
@@ -1383,6 +1383,30 @@ void COM_Path_f (void)
        }
 }
 
+/*
+============
+COM_CreatePath
+
+LordHavoc: Previously only used for CopyFile, now also used for COM_WriteFile.
+============
+*/
+void    COM_CreatePath (char *path)
+{
+       char    *ofs, save;
+       
+       for (ofs = path+1 ; *ofs ; ofs++)
+       {
+               if (*ofs == '/' || *ofs == '\\' || *ofs == ':')
+               {       // create the directory
+                       save = *ofs;
+                       *ofs = 0;
+                       Sys_mkdir (path);
+                       *ofs = save;
+               }
+       }
+}
+
+
 /*
 ============
 COM_WriteFile
@@ -1397,6 +1421,9 @@ void COM_WriteFile (char *filename, void *data, int len)
        
        sprintf (name, "%s/%s", com_gamedir, filename);
 
+       // LordHavoc: added this
+       COM_CreatePath (name); // create directories up to the file
+
        handle = Sys_FileOpenWrite (name);
        if (handle == -1)
        {
@@ -1410,29 +1437,6 @@ void COM_WriteFile (char *filename, void *data, int len)
 }
 
 
-/*
-============
-COM_CreatePath
-
-Only used for CopyFile
-============
-*/
-void    COM_CreatePath (char *path)
-{
-       char    *ofs;
-       
-       for (ofs = path+1 ; *ofs ; ofs++)
-       {
-               if (*ofs == '/')
-               {       // create the directory
-                       *ofs = 0;
-                       Sys_mkdir (path);
-                       *ofs = '/';
-               }
-       }
-}
-
-
 /*
 ===========
 COM_CopyFile
@@ -1639,7 +1643,7 @@ void COM_CloseFile (int h)
 COM_LoadFile
 
 Filename are reletive to the quake directory.
-Allways appends a 0 byte.
+Always appends a 0 byte.
 ============
 */
 cache_user_t *loadcache;
index a9dad19e01e2262500fc7ad7d39c91b0d802f6ba..502f4cdb436416b7f82305466f0dbb79aecc8b00 100644 (file)
--- a/common.h
+++ b/common.h
@@ -146,6 +146,8 @@ float MSG_ReadCoord (void);
 #define MSG_ReadAngle() (MSG_ReadByte() * (360.0f / 256.0f))
 #define MSG_ReadPreciseAngle() (MSG_ReadShort() * (360.0f / 65536.0f))
 
+#define MSG_ReadVector(v) {(v)[0] = MSG_ReadCoord();(v)[1] = MSG_ReadCoord();(v)[2] = MSG_ReadCoord();}
+
 extern qboolean dpprotocol;
 
 //============================================================================
diff --git a/cpu_noasm.c b/cpu_noasm.c
deleted file mode 100644 (file)
index 7c5f8ef..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-
-#include "quakedef.h"
-
-/*
-===============
-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");
-
-       node = model->nodes;
-       if (node->contents < 0)
-               return (mleaf_t *)node;
-       while (1)
-       {
-               node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
-               if (node->contents < 0)
-                       return (mleaf_t *)node;
-       }
-       
-       return NULL;    // never reached
-}
-/*
-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");
-
-       node = model->nodes;
-       while (1)
-       {
-               if (node->contents < 0)
-                       return (mleaf_t *)node;
-               plane = node->plane;
-               d = DotProduct (p,plane->normal) - plane->dist;
-               if (d > 0)
-                       node = node->children[0];
-               else
-                       node = node->children[1];
-       }
-       
-       return NULL;    // never reached
-}
-*/
-
-/*
-==================
-SV_HullPointContents
-
-==================
-*/
-int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
-{
-       while (num >= 0)
-               num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist];
-       
-       return num;
-}
diff --git a/cpu_x86.bat b/cpu_x86.bat
deleted file mode 100644 (file)
index 26e5a5a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-nasmw -fwin32 cpu_x86.nasm
diff --git a/cpu_x86.nasm b/cpu_x86.nasm
deleted file mode 100644 (file)
index 4ab9875..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-          BITS 32
-          GLOBAL _Mod_PointInLeaf
-          GLOBAL _SV_HullPointContents
-          SECTION .text
-_Mod_PointInLeaf
-
-;{
-
-        mov     eax, dword [esp+12-4] ; model
-       sub     esp, 4
-       push    ebx
-       push    esi
-
-;       mnode_t         *node;
-;       node = model->nodes;
-
-        mov     esi, dword [eax+200] ; model->nodes
-
-;       if (node->contents < 0)
-
-        cmp     dword [esi], 0 ; node->contents
-        jge     .firstvalid
-
-;               return (mleaf_t *)node;
-
-       mov     eax, esi
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
-.firstvalid
-        mov     edx, dword [esp+8+8] ; p
-.loop
-
-;       while (1)
-
-        xor     ecx, ecx
-        mov     eax, dword [esi+76] ; node->plane
-        mov     cl, byte [eax+16] ; node->plane->type
-
-;       {
-;               node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
-
-       cmp     cl, 3
-        jb      .axisplane
-        fld     dword [eax+4] ; node->plane->normal[1]
-        fmul    dword [edx+4] ; p[1]
-        fld     dword [eax+8] ; node->plane->normal[2]
-        fmul    dword [edx+8] ; p[2]
-        fld     dword [eax]   ; node->plane->normal[0]
-        fmul    dword [edx]   ; p[0]
-        faddp   st1, st0
-        faddp   st1, st0
-        fld     dword [eax+12] ; node->plane->dist
-        fcompp
-       fnstsw  ax
-       test    ah, 65                                  ; 00000041H
-       sete    cl
-        mov     esi, dword [esi+ecx*4+80] ; node = node->children[condition]
-
-;               if (node->contents < 0)
-
-        cmp     dword [esi], 0
-        jge     .loop
-
-;                       return (mleaf_t *)node;
-
-       mov     eax, esi
-
-;       }
-;       return NULL;    // never reached
-;}
-
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
-.axisplane:
-        fld     dword [edx+ecx*4]
-        fld     dword [eax+12]
-        fcompp
-        fnstsw  ax
-       test    ah, 65                                  ; 00000041H
-       sete    cl
-        mov     esi, dword [esi+ecx*4+80] ; node = node->children[condition]
-
-;               if (node->contents < 0)
-
-        cmp     dword [esi], 0
-        jge     .loop
-
-;                       return (mleaf_t *)node;
-
-       mov     eax, esi
-
-;       }
-;       return NULL;    // never reached
-;}
-
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
-
-
-_SV_HullPointContents
-
-;{
-        mov     ecx, [esp+12-4] ; num
-       sub     esp, 4
-       test    ecx, ecx
-        nop                     ; padding
-       push    ebx
-       push    esi
-       push    edi
-       push    ebp
-
-;       while (num >= 0)
-
-        jge     .firstvalid
-;       return num;
-       mov     eax, ecx
-       pop     ebp
-;}
-       pop     edi
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
-.firstvalid
-        mov     eax, [esp+8+16] ; hull
-        mov     edx, [esp+16+16] ; p
-        mov     esi, [eax]
-        mov     edi, [eax+4]
-.loop
-        mov     eax, [esi+ecx*8]
-        lea     ebx, [eax+eax*2]
-        xor     eax, eax
-        mov     al, [edi+ebx*8+16]
-        lea     ebp, [edi+ebx*8]
-
-;               num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist];
-
-       cmp     al, 3
-        jb      .axisplane
-        fld     dword [edx+8]
-        fmul    dword [ebp+8]
-        fld     dword [edx+4]
-        fmul    dword [ebp+4]
-        fld     dword [edx]
-        fmul    dword [ebp]
-        faddp   st1, st0
-        faddp   st1, st0
-        fstp    dword [esp-4+20]
-
-        fld     dword [ebp+12]
-        fcomp   dword [esp-4+20]
-       xor     ebx, ebx
-       fnstsw  ax
-       test    ah, 65                                  ; 00000041H
-       sete    bl
-        lea     eax, [ebx+ecx*4]
-        movsx   ecx, word [esi+eax*2+4]
-       test    ecx, ecx
-        jge     .loop
-;       return num;
-       mov     eax, ecx
-       pop     ebp
-;}
-       pop     edi
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
-
-.axisplane
-        mov     eax, [edx+eax*4]
-        mov     [esp-4+20], eax
-
-        fld     dword [ebp+12]
-        fcomp   dword [esp-4+20]
-       xor     ebx, ebx
-       fnstsw  ax
-       test    ah, 65                                  ; 00000041H
-       sete    bl
-        lea     eax, [ebx+ecx*4]
-        movsx   ecx, word [esi+eax*2+4]
-       test    ecx, ecx
-        jge     .loop
-;       return num;
-       mov     eax, ecx
-       pop     ebp
-;}
-       pop     edi
-       pop     esi
-       pop     ebx
-       add     esp, 4
-       ret     0
diff --git a/cpu_x86.obj b/cpu_x86.obj
deleted file mode 100644 (file)
index 3c13863..0000000
Binary files a/cpu_x86.obj and /dev/null differ
diff --git a/cvar.c b/cvar.c
index db48c0c26b8618a3f3a5c207c6408cc335065fec..bb6801587555a357b9776657e1767fd40ba15cf1 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -153,7 +153,7 @@ void Cvar_RegisterVariable (cvar_t *variable)
 {
        char    *oldstr;
        
-// first check to see if it has allready been defined
+// first check to see if it has already been defined
        if (Cvar_FindVar (variable->name))
        {
                Con_Printf ("Can't register variable %s, already defined\n", variable->name);
diff --git a/cvar.h b/cvar.h
index 009b74783f270cbde8cec33e38095f5c845d321b..4a961b20b1e1df66f45d43afff0f38e843eaf4ac 100644 (file)
--- a/cvar.h
+++ b/cvar.h
@@ -64,7 +64,7 @@ typedef struct cvar_s
 } cvar_t;
 
 void   Cvar_RegisterVariable (cvar_t *variable);
-// registers a cvar that allready has the name, string, and optionally the
+// registers a cvar that already has the name, string, and optionally the
 // archive elements set.
 
 void   Cvar_Set (char *var_name, char *value);
diff --git a/draw.h b/draw.h
index 322c9b8f93885e133c3dad00759886afd98a3560..267b9e921f91b690018133286b3db62b6d1c84db 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -25,7 +25,7 @@ extern        qpic_t          *draw_disc;     // also used on sbar
 
 void Draw_Init (void);
 void Draw_Character (int x, int y, int num);
-void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, int x, int y, int width, int height);
+void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height);
 void Draw_Pic (int x, int y, qpic_t *pic);
 void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation);
 void Draw_ConsoleBackground (int lines);
index e9899a47f84771e4bc3e22c2514ad20d514d0575..93622b14e4530f6f8f8223223bd79dfeda4353b3 100644 (file)
@@ -1,48 +1,50 @@
 
 #include "quakedef.h"
 
-void fractalnoise(unsigned char *noise, int size, int startgrid)
+void fractalnoise(byte *noise, int size, int startgrid)
 {
-       int x, y, g, g2, amplitude, min, max, size1 = size - 1;
+       int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower;
        int *noisebuf;
 #define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
-       if (startgrid > size)
-               startgrid = size;
+
+       for (sizepower = 0;(1 << sizepower) < size;sizepower++);
+       if (size != (1 << sizepower))
+               Sys_Error("fractalnoise: size must be power of 2\n");
+
+       for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
+       if (startgrid != (1 << gridpower))
+               Sys_Error("fractalnoise: grid must be power of 2\n");
+
+       startgrid = bound(0, startgrid, size);
+
+       amplitude = 32767;
        noisebuf = qmalloc(size*size*sizeof(int));
        memset(noisebuf, 0, size*size*sizeof(int));
 
-       amplitude = 32767;
-       // quick 1x1 case which the rest of the code can't handle
-       if (startgrid < 2)
-       {
-               for (x = 0;x < size*size;x++)
-                       *noise++ = (rand()&255);
-               return;
-       }
-       g2 = startgrid;
-       // clear the starting grid (the rest does not need to be cleared, it will simply be overwritten)
-       for (y = 0;y < size;y += g2)
-               for (x = 0;x < size;x += g2)
-                       n(x,y) = 0;
-       for (;(g = g2 >> 1) >= 1;g2 >>= 1)
+       for (g2 = startgrid;g2;g2 >>= 1)
        {
-               // subdivide, diamond-square algorythm (really this has little to do with squares)
-               // diamond
-               for (y = 0;y < size;y += g2)
-                       for (x = 0;x < size;x += g2)
-                               n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
-               // square
+               // brownian motion (at every smaller level there is random behavior)
+               amplitude >>= 1;
                for (y = 0;y < size;y += g2)
                        for (x = 0;x < size;x += g2)
-                       {
-                               n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
-                               n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
-                       }
-               // brownian motion theory
-               amplitude >>= 1;
-               for (y = 0;y < size;y += g)
-                       for (x = 0;x < size;x += g)
                                n(x,y) += (rand()&amplitude);
+
+               g = g2 >> 1;
+               if (g)
+               {
+                       // subdivide, diamond-square algorythm (really this has little to do with squares)
+                       // diamond
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                                       n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
+                       // square
+                       for (y = 0;y < size;y += g2)
+                               for (x = 0;x < size;x += g2)
+                               {
+                                       n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
+                                       n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
+                               }
+               }
        }
        // find range of noise values
        min = max = 0;
@@ -59,4 +61,4 @@ void fractalnoise(unsigned char *noise, int size, int startgrid)
                        *noise++ = (n(x,y) - min) * 255 / max;
        qfree(noisebuf);
 #undef n
-}
\ No newline at end of file
+}
index 5a1e715afc6275157059c7aca7efb608c9b861c9..f2c94651bde91ce59c5841748f6d4f0a8b53d23b 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -25,20 +25,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 //#define GL_COLOR_INDEX8_EXT     0x80E5
 
-cvar_t         qsg_version = {"qsg_version", "1"};
 cvar_t         scr_conalpha = {"scr_conalpha", "1"};
 
 byte           *draw_chars;                            // 8*8 graphic characters
 qpic_t         *draw_disc;
 
-int                    char_texture;
+rtexture_t     *char_texture;
 
 typedef struct
 {
-       int             texnum;
+       rtexture_t      *tex;
 } glpic_t;
 
-int                    conbacktexnum;
+rtexture_t     *conbacktex;
 
 //=============================================================================
 /* Support Routines */
@@ -67,7 +66,7 @@ qpic_t *Draw_PicFromWad (char *name)
        p = W_GetLumpName (name);
        gl = (glpic_t *)p->data;
 
-       gl->texnum = GL_LoadTexture (name, p->width, p->height, p->data, false, true, 1);
+       gl->tex = R_LoadTexture (name, p->width, p->height, p->data, TEXF_ALPHA | TEXF_PRECACHE);
        return p;
 }
 
@@ -111,9 +110,9 @@ qpic_t      *Draw_CachePic (char *path)
        pic->pic.height = dat->height;
 
        gl = (glpic_t *)pic->pic.data;
-       gl->texnum = loadtextureimage(path, 0, 0, false, false);
-       if (!gl->texnum)
-               gl->texnum = GL_LoadTexture (path, dat->width, dat->height, dat->data, false, true, 1);
+       gl->tex = loadtextureimage(path, 0, 0, false, false, true);
+       if (!gl->tex)
+               gl->tex = R_LoadTexture (path, dat->width, dat->height, dat->data, TEXF_ALPHA | TEXF_PRECACHE);
 
        qfree(dat);
 
@@ -133,7 +132,7 @@ void gl_draw_start()
 {
        int             i;
 
-       char_texture = loadtextureimage ("conchars", 0, 0, false, false);
+       char_texture = loadtextureimage ("conchars", 0, 0, false, false, true);
        if (!char_texture)
        {
                draw_chars = W_GetLumpName ("conchars");
@@ -142,10 +141,10 @@ void gl_draw_start()
                                draw_chars[i] = 255;    // proper transparent color
 
                // now turn them into textures
-               char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
+               char_texture = R_LoadTexture ("charset", 128, 128, draw_chars, TEXF_ALPHA | TEXF_PRECACHE);
        }
 
-       conbacktexnum = loadtextureimage("gfx/conback", 0, 0, false, false);
+       conbacktex = loadtextureimage("gfx/conback", 0, 0, false, false, true);
 
        // get the other pics we need
        draw_disc = Draw_PicFromWad ("disc");
@@ -158,11 +157,10 @@ void gl_draw_shutdown()
 char engineversion[40];
 int engineversionx, engineversiony;
 
-extern void GL_Textures_Init();
+extern void R_Textures_Init();
 void GL_Draw_Init (void)
 {
        int i;
-       Cvar_RegisterVariable (&qsg_version);
        Cvar_RegisterVariable (&scr_conalpha);
 
        Cmd_AddCommand ("loadsky", &LoadSky_f);
@@ -179,7 +177,7 @@ void GL_Draw_Init (void)
        engineversionx = vid.width - strlen(engineversion) * 8 - 8;
        engineversiony = vid.height - 8;
 
-       GL_Textures_Init();
+       R_Textures_Init();
        R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown);
 }
 
@@ -214,13 +212,18 @@ void Draw_Character (int x, int y, int num)
 
        if (!r_render.value)
                return;
-       glBindTexture(GL_TEXTURE_2D, char_texture);
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
        // LordHavoc: NEAREST mode on text if not scaling up
-       if (glwidth < (int) vid.width)
+       if (glwidth <= (int) vid.width)
        {
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        }
+       else
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       }
 
        glColor3f(1,1,1);
        glBegin (GL_QUADS);
@@ -235,11 +238,11 @@ void Draw_Character (int x, int y, int num)
        glEnd ();
 
        // LordHavoc: revert to LINEAR mode
-       if (glwidth < (int) vid.width)
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       }
+//     if (glwidth < (int) vid.width)
+//     {
+//             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+//             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+//     }
 }
 
 /*
@@ -260,14 +263,19 @@ void Draw_String (int x, int y, char *str, int maxlen)
                maxlen = strlen(str);
        else if (maxlen > (int) strlen(str))
                maxlen = strlen(str);
-       glBindTexture(GL_TEXTURE_2D, char_texture);
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
 
        // LordHavoc: NEAREST mode on text if not scaling up
-       if (glwidth < (int) vid.width)
+       if (glwidth <= (int) vid.width)
        {
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        }
+       else
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       }
 
        glColor3f(1,1,1);
        glBegin (GL_QUADS);
@@ -287,19 +295,19 @@ void Draw_String (int x, int y, char *str, int maxlen)
        glEnd ();
 
        // LordHavoc: revert to LINEAR mode
-       if (glwidth < (int) vid.width)
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       }
+//     if (glwidth < (int) vid.width)
+//     {
+//             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+//             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+//     }
 }
 
-void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, int x, int y, int width, int height)
+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)
                return;
        glColor4f(red,green,blue,alpha);
-       glBindTexture(GL_TEXTURE_2D, texnum);
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(tex));
        glBegin (GL_QUADS);
        glTexCoord2f (0, 0);glVertex2f (x, y);
        glTexCoord2f (1, 0);glVertex2f (x+width, y);
@@ -315,7 +323,7 @@ Draw_AlphaPic
 */
 void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
 {
-       Draw_GenericPic(((glpic_t *)pic->data)->texnum, 1,1,1,alpha, x,y,pic->width, pic->height);
+       Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,alpha, x,y,pic->width, pic->height);
 }
 
 
@@ -326,7 +334,7 @@ Draw_Pic
 */
 void Draw_Pic (int x, int y, qpic_t *pic)
 {
-       Draw_GenericPic(((glpic_t *)pic->data)->texnum, 1,1,1,1, x,y,pic->width, pic->height);
+       Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,1, x,y,pic->width, pic->height);
 }
 
 
@@ -341,6 +349,7 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation)
 {
        int                             i, c;
        byte                    *trans, *src, *dest;
+       rtexture_t              *rt;
 
        c = pic->width * pic->height;
        src = menuplyr_pixels;
@@ -348,12 +357,12 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation)
        for (i = 0;i < c;i++)
                *dest++ = translation[*src++];
 
-       c = GL_LoadTexture ("translatedplayerpic", pic->width, pic->height, trans, false, true, 1);
+       rt = R_LoadTexture ("translatedplayerpic", pic->width, pic->height, trans, TEXF_ALPHA | TEXF_PRECACHE);
        qfree(trans);
 
        if (!r_render.value)
                return;
-       Draw_GenericPic (c, 1,1,1,1, x, y, pic->width, pic->height);
+       Draw_GenericPic (rt, 1,1,1,1, x, y, pic->width, pic->height);
 }
 
 
@@ -365,7 +374,7 @@ Draw_ConsoleBackground
 */
 void Draw_ConsoleBackground (int lines)
 {
-       Draw_GenericPic (conbacktexnum, 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.height, 0, lines - vid.height, vid.width, vid.height);
        // LordHavoc: draw version
        Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
 }
@@ -465,8 +474,16 @@ void SHOWLMP_decodeshow()
        float x, y;
        strcpy(lmplabel,MSG_ReadString());
        strcpy(picname, MSG_ReadString());
-       x = MSG_ReadByte();
-       y = MSG_ReadByte();
+       if (nehahra) // LordHavoc: nasty old legacy junk
+       {
+               x = MSG_ReadByte();
+               y = MSG_ReadByte();
+       }
+       else
+       {
+               x = MSG_ReadShort();
+               y = MSG_ReadShort();
+       }
        k = -1;
        for (i = 0;i < SHOWLMP_MAXLABELS;i++)
                if (showlmp[i].isactive)
index 42b68fcd949efd37821e151189e4648cc4661b52..99e71140dc247f300bd1ccae99cbb4c916ffc5d5 100644 (file)
@@ -1,6 +1,9 @@
 
 #include "quakedef.h"
 
+cvar_t gl_transform = {"gl_transform", "1"};
+cvar_t gl_lockarrays = {"gl_lockarrays", "1"};
+
 typedef struct
 {
        float m[3][4];
@@ -8,14 +11,46 @@ typedef struct
 
 // LordHavoc: vertex array
 float *aliasvert;
-float *modelaliasvert;
 float *aliasvertnorm;
 byte *aliasvertcolor;
 byte *aliasvertcolor2;
 zymbonematrix *zymbonepose;
 int *aliasvertusage;
 
-int chrometexture;
+rtexture_t *chrometexture;
+
+int arraylocked = false;
+void GL_LockArray(int first, int count)
+{
+       if (gl_supportslockarrays && gl_lockarrays.value)
+       {
+               qglLockArraysEXT(first, count);
+               arraylocked = true;
+       }
+}
+
+void GL_UnlockArray()
+{
+       if (arraylocked)
+       {
+               qglUnlockArraysEXT();
+               arraylocked = false;
+       }
+}
+
+void GL_SetupModelTransform (vec3_t origin, vec3_t angles, vec_t scale)
+{
+    glTranslatef (origin[0], origin[1], origin[2]);
+
+       if (scale != 1)
+               glScalef (scale, scale, scale);
+       if (angles[1])
+           glRotatef (angles[1],  0, 0, 1);
+       if (angles[0])
+           glRotatef (-angles[0],  0, 1, 0);
+       if (angles[2])
+           glRotatef (angles[2],  1, 0, 0);
+}
 
 void makechrometexture()
 {
@@ -23,7 +58,7 @@ void makechrometexture()
        byte noise[64*64];
        byte data[64*64][4];
 
-       fractalnoise(noise, 64, 16);
+       fractalnoise(noise, 64, 8);
 
        // convert to RGBA data
        for (i = 0;i < 64*64;i++)
@@ -32,14 +67,13 @@ void makechrometexture()
                data[i][3] = 255;
        }
 
-       chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4);
+       chrometexture = R_LoadTexture ("chrometexture", 64, 64, &data[0][0], TEXF_MIPMAP | TEXF_RGBA | TEXF_PRECACHE);
 }
 
 void gl_models_start()
 {
        // allocate vertex processing arrays
        aliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
-       modelaliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
        aliasvertnorm = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
        aliasvertcolor = qmalloc(sizeof(byte[MD2MAX_VERTS][4]));
        aliasvertcolor2 = qmalloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
@@ -60,6 +94,9 @@ void gl_models_shutdown()
 
 void GL_Models_Init()
 {
+       Cvar_RegisterVariable(&gl_transform);
+       Cvar_RegisterVariable(&gl_lockarrays);
+
        R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
 }
 
@@ -68,74 +105,121 @@ extern vec3_t softwaretransform_y;
 extern vec3_t softwaretransform_z;
 extern vec_t softwaretransform_scale;
 extern vec3_t softwaretransform_offset;
-extern cvar_t r_modelsdonttransformnormals;
-void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
+void R_AliasTransformVerts(int vertcount)
 {
        int i;
        vec3_t point, matrix_x, matrix_y, matrix_z;
        float *av, *avn;
        av = aliasvert;
        avn = aliasvertnorm;
-       VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
-       VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
-       VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
-       if (lerp < 0) lerp = 0;
-       if (lerp > 1) lerp = 1;
-       if (lerp != 0)
+       matrix_x[0] = softwaretransform_x[0] * softwaretransform_scale;
+       matrix_x[1] = softwaretransform_y[0] * softwaretransform_scale;
+       matrix_x[2] = softwaretransform_z[0] * softwaretransform_scale;
+       matrix_y[0] = softwaretransform_x[1] * softwaretransform_scale;
+       matrix_y[1] = softwaretransform_y[1] * softwaretransform_scale;
+       matrix_y[2] = softwaretransform_z[1] * softwaretransform_scale;
+       matrix_z[0] = softwaretransform_x[2] * softwaretransform_scale;
+       matrix_z[1] = softwaretransform_y[2] * softwaretransform_scale;
+       matrix_z[2] = softwaretransform_z[2] * softwaretransform_scale;
+       for (i = 0;i < vertcount;i++)
+       {
+               // rotate, scale, and translate the vertex locations
+               VectorCopy(av, point);
+               av[0] = DotProduct(point, matrix_x) + softwaretransform_offset[0];
+               av[1] = DotProduct(point, matrix_y) + softwaretransform_offset[1];
+               av[2] = DotProduct(point, matrix_z) + softwaretransform_offset[2];
+               // rotate the normals
+               VectorCopy(avn, point);
+               avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+               avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+               avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+               av += 3;
+               avn += 3;
+       }
+}
+
+void R_AliasLerpVerts(int vertcount,
+                                         float lerp1, trivertx_t *verts1, vec3_t fscale1, vec3_t translate1,
+                                         float lerp2, trivertx_t *verts2, vec3_t fscale2, vec3_t translate2,
+                                         float lerp3, trivertx_t *verts3, vec3_t fscale3, vec3_t translate3,
+                                         float lerp4, trivertx_t *verts4, vec3_t fscale4, vec3_t translate4)
+{
+       int i;
+       vec3_t scale1, scale2, scale3, scale4, translate;
+       float *n1, *n2, *n3, *n4;
+       float *av, *avn;
+       av = aliasvert;
+       avn = aliasvertnorm;
+       VectorScaleQuick(fscale1, lerp1, scale1);
+       if (lerp2)
        {
-               float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
-               ilerp = 1 - lerp;
-               ilerp127 = ilerp * (1.0 / 127.0);
-               lerp127 = lerp * (1.0 / 127.0);
-               // calculate combined interpolation variables
-               scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] *  lerp;translatex = translate1[0] * ilerp + translate2[0] *  lerp;
-               scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] *  lerp;translatey = translate1[1] * ilerp + translate2[1] *  lerp;
-               scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] *  lerp;translatez = translate1[2] * ilerp + translate2[2] *  lerp;
-               // generate vertices
-               if (r_modelsdonttransformnormals.value)
+               VectorScaleQuick(fscale2, lerp2, scale2);
+               if (lerp3)
                {
-                       float *modelav = modelaliasvert;
-                       for (i = 0;i < vertcount;i++)
+                       VectorScaleQuick(fscale3, lerp3, scale3);
+                       if (lerp4)
                        {
-                               // rotate, scale, and translate the vertex locations
-                               point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
-                               point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
-                               point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
-                               // save mostly un-transformed copy for lighting
-                               modelav[0] = point[0] * softwaretransform_scale;
-                               modelav[1] = point[1] * softwaretransform_scale;
-                               modelav[2] = point[2] * softwaretransform_scale;
-                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
-                               // decompress but do not transform the normals
-                               avn[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
-                               avn[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
-                               avn[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
-                               modelav += 3;
-                               av += 3;
-                               avn += 3;
-                               verts1++;verts2++;
+                               VectorScaleQuick(fscale4, lerp4, scale4);
+                               translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3 + translate4[0] * lerp4;
+                               translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3 + translate4[1] * lerp4;
+                               translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3 + translate4[2] * lerp4;
+                               // generate vertices
+                               for (i = 0;i < vertcount;i++)
+                               {
+                                       av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + verts4->v[0] * scale4[0] + translate[0];
+                                       av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + verts4->v[1] * scale4[1] + translate[1];
+                                       av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + verts4->v[2] * scale4[2] + translate[2];
+                                       n1 = m_bytenormals[verts1->lightnormalindex];
+                                       n2 = m_bytenormals[verts2->lightnormalindex];
+                                       n3 = m_bytenormals[verts3->lightnormalindex];
+                                       n4 = m_bytenormals[verts4->lightnormalindex];
+                                       avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3 + n4[0] * lerp4;
+                                       avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4;
+                                       avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4;
+                                       av += 3;
+                                       avn += 3;
+                                       verts1++;verts2++;verts3++;verts4++;
+                               }
+                       }
+                       else
+                       {
+                               translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3;
+                               translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3;
+                               translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3;
+                               // generate vertices
+                               for (i = 0;i < vertcount;i++)
+                               {
+                                       av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + translate[0];
+                                       av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + translate[1];
+                                       av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + translate[2];
+                                       n1 = m_bytenormals[verts1->lightnormalindex];
+                                       n2 = m_bytenormals[verts2->lightnormalindex];
+                                       n3 = m_bytenormals[verts3->lightnormalindex];
+                                       avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3;
+                                       avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3;
+                                       avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3;
+                                       av += 3;
+                                       avn += 3;
+                                       verts1++;verts2++;verts3++;
+                               }
                        }
                }
                else
                {
+                       translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2;
+                       translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2;
+                       translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2;
+                       // generate vertices
                        for (i = 0;i < vertcount;i++)
                        {
-                               // rotate, scale, and translate the vertex locations
-                               point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
-                               point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
-                               point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
-                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
-                               // rotate the normals
-                               point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
-                               point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
-                               point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
-                               avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
-                               avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
-                               avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                               av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + translate[0];
+                               av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + translate[1];
+                               av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + translate[2];
+                               n1 = m_bytenormals[verts1->lightnormalindex];
+                               n2 = m_bytenormals[verts2->lightnormalindex];
+                               avn[0] = n1[0] * lerp1 + n2[0] * lerp2;
+                               avn[1] = n1[1] * lerp1 + n2[1] * lerp2;
+                               avn[2] = n1[2] * lerp1 + n2[2] * lerp2;
                                av += 3;
                                avn += 3;
                                verts1++;verts2++;
@@ -144,28 +228,22 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1
        }
        else
        {
+               translate[0] = translate1[0] * lerp1;
+               translate[1] = translate1[1] * lerp1;
+               translate[2] = translate1[2] * lerp1;
                // generate vertices
-               if (r_modelsdonttransformnormals.value)
+               if (lerp1 != 1)
                {
-                       float *modelav = modelaliasvert;
+                       // general but almost never used case
                        for (i = 0;i < vertcount;i++)
                        {
-                               // rotate, scale, and translate the vertex locations
-                               point[0] = verts1->v[0] * scale1[0] + translate1[0];
-                               point[1] = verts1->v[1] * scale1[1] + translate1[1];
-                               point[2] = verts1->v[2] * scale1[2] + translate1[2];
-                               // save mostly un-transformed copy for lighting
-                               modelav[0] = point[0] * softwaretransform_scale;
-                               modelav[1] = point[1] * softwaretransform_scale;
-                               modelav[2] = point[2] * softwaretransform_scale;
-                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
-                               // decompress normal but do not rotate it
-                               avn[0] = verts1->n[0] * (1.0f / 127.0f);
-                               avn[1] = verts1->n[1] * (1.0f / 127.0f);
-                               avn[2] = verts1->n[2] * (1.0f / 127.0f);
-                               modelav += 3;
+                               av[0] = verts1->v[0] * scale1[0] + translate[0];
+                               av[1] = verts1->v[1] * scale1[1] + translate[1];
+                               av[2] = verts1->v[2] * scale1[2] + translate[2];
+                               n1 = m_bytenormals[verts1->lightnormalindex];
+                               avn[0] = n1[0] * lerp1;
+                               avn[1] = n1[1] * lerp1;
+                               avn[2] = n1[2] * lerp1;
                                av += 3;
                                avn += 3;
                                verts1++;
@@ -173,22 +251,13 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1
                }
                else
                {
+                       // fast normal case
                        for (i = 0;i < vertcount;i++)
                        {
-                               // rotate, scale, and translate the vertex locations
-                               point[0] = verts1->v[0] * scale1[0] + translate1[0];
-                               point[1] = verts1->v[1] * scale1[1] + translate1[1];
-                               point[2] = verts1->v[2] * scale1[2] + translate1[2];
-                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
-                               // rotate the normals
-                               point[0] = verts1->n[0] * (1.0f / 127.0f);
-                               point[1] = verts1->n[1] * (1.0f / 127.0f);
-                               point[2] = verts1->n[2] * (1.0f / 127.0f);
-                               avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
-                               avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
-                               avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                               av[0] = verts1->v[0] * scale1[0] + translate[0];
+                               av[1] = verts1->v[1] * scale1[1] + translate[1];
+                               av[2] = verts1->v[2] * scale1[2] + translate[2];
+                               VectorCopy(m_bytenormals[verts1->lightnormalindex], avn);
                                av += 3;
                                avn += 3;
                                verts1++;
@@ -197,35 +266,11 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1
        }
 }
 
-float R_CalcAnimLerp(entity_t *ent, int pose, float lerpscale)
-{
-       if (ent->draw_lastmodel == ent->model && ent->draw_lerpstart <= cl.time)
-       {
-               if (pose != ent->draw_pose)
-               {
-                       ent->draw_lastpose = ent->draw_pose;
-                       ent->draw_pose = pose;
-                       ent->draw_lerpstart = cl.time;
-                       return 0;
-               }
-               else
-                       return ((cl.time - ent->draw_lerpstart) * lerpscale);
-       }
-       else // uninitialized
-       {
-               ent->draw_lastmodel = ent->model;
-               ent->draw_lastpose = ent->draw_pose = pose;
-               ent->draw_lerpstart = cl.time;
-               return 0;
-       }
-}
-
-void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
+void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr)
 {
-       int i;
        if (!r_render.value)
                return;
-       glBindTexture(GL_TEXTURE_2D, skin);
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin));
        if (!colors)
        {
                if (lighthalf)
@@ -233,41 +278,16 @@ void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
                else
                        glColor3f(1.0f, 1.0f, 1.0f);
        }
-       if (gl_vertexarrays.value)
+       if (colors)
        {
-               if (colors)
-               {
-                       qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
-                       glEnableClientState(GL_COLOR_ARRAY);
-               }
-
-               qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr));
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-               qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+               glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
+               glEnableClientState(GL_COLOR_ARRAY);
+       }
 
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
 
-               if (colors)
-                       glDisableClientState(GL_COLOR_ARRAY);
-       }
-       else
-       {
-               unsigned short *in, index;
-               float *tex;
-               in = (void *)((int) maliashdr + maliashdr->tridata);
-               glBegin(GL_TRIANGLES);
-               tex = (void *)((int) maliashdr + maliashdr->texdata);
-               for (i = 0;i < maliashdr->numtris * 3;i++)
-               {
-                       index = *in++;
-                       glTexCoord2f(tex[index*2], tex[index*2+1]);
-                       if (colors)
-                               glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f));
-                       glVertex3fv(&aliasvert[index*3]);
-               }
-               glEnd();
-       }
+       if (colors)
+               glDisableClientState(GL_COLOR_ARRAY);
        // leave it in a state for additional passes
        glDepthMask(0);
        glEnable(GL_BLEND);
@@ -299,43 +319,35 @@ R_DrawAliasFrame
 */
 extern vec3_t lightspot;
 void R_LightModel(int numverts, vec3_t center, vec3_t basecolor);
-void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int *skin, int colormap, int effects, int flags)
+void R_DrawAliasFrame (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)
 {
-       int             i, pose;
-       float   lerpscale, lerp;
-       maliasframe_t *frameinfo;
-
-       softwaretransformforentity(ent);
-
-       if ((frame >= maliashdr->numframes) || (frame < 0))
-       {
-               Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
-               frame = 0;
-       }
-
-       frameinfo = ((maliasframe_t *)((int) maliashdr + maliashdr->framedata)) + frame;
-       pose = frameinfo->start;
-
-       if (frameinfo->length > 1)
+       if (gl_transform.value)
        {
-               lerpscale = frameinfo->rate;
-               pose += (int)(cl.time * frameinfo->rate) % frameinfo->length;
+               if (r_render.value)
+               {
+                       glPushMatrix();
+                       GL_SetupModelTransform(org, angles, scale);
+               }
        }
-       else
-               lerpscale = 10.0f;
-
-       lerp = R_CalcAnimLerp(ent, pose, lerpscale);
+       // always needed, for model lighting
+       softwaretransformforentity(ent);
 
-       R_AliasLerpVerts(maliashdr->numverts, lerp, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_lastpose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_pose * maliashdr->numverts, maliashdr->scale, maliashdr->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);
 
        // prep the vertex array as early as possible
        if (r_render.value)
        {
-               if (gl_vertexarrays.value)
-               {
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-               }
+               glVertexPointer(3, GL_FLOAT, 0, aliasvert);
+               glEnableClientState(GL_VERTEX_ARRAY);
+               glTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr));
+               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+               GL_LockArray(0, maliashdr->numverts);
        }
 
        R_LightModel(maliashdr->numverts, org, color);
@@ -408,64 +420,20 @@ void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity
                VectorSubtract(org, r_refdef.vieworg, diff);
                glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
 
-               if (gl_vertexarrays.value)
-               {
-                       qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
-               }
-               else
-               {
-                       unsigned short *in;
-                       in = (void *)((int) maliashdr + maliashdr->tridata);
-                       glBegin(GL_TRIANGLES);
-                       for (i = 0;i < maliashdr->numtris * 3;i++)
-                               glVertex3fv(&aliasvert[*in++ * 3]);
-                       glEnd();
-               }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-       if (gl_vertexarrays.value)
-               glDisableClientState(GL_VERTEX_ARRAY);
-
-       if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
-       {
-               // flatten it to make a shadow
-               float *av = aliasvert + 2, l = lightspot[2] + 0.125;
-               av = aliasvert + 2;
-               for (i = 0;i < maliashdr->numverts;i++, av+=3)
-                       if (*av > l)
-                               *av = l;
-               glDisable (GL_TEXTURE_2D);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable (GL_BLEND);
-               glDepthMask(0); // disable zbuffer updates
-               glColor4f (0,0,0,0.5 * alpha);
-
-               if (gl_vertexarrays.value)
-               {
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                       qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
-                       glDisableClientState(GL_VERTEX_ARRAY);
-               }
-               else
-               {
-                       unsigned short *in;
-                       in = (void *)((int) maliashdr + maliashdr->tridata);
-                       glBegin(GL_TRIANGLES);
-                       for (i = 0;i < maliashdr->numtris * 3;i++)
-                               glVertex3fv(&aliasvert[*in++ * 3]);
-                       glEnd();
-               }
+               glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
 
                glEnable (GL_TEXTURE_2D);
                glColor3f (1,1,1);
        }
+       GL_UnlockArray();
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDisableClientState(GL_VERTEX_ARRAY);
 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable (GL_BLEND);
        glDepthMask(1);
+
+       glPopMatrix();
 }
 
 /*
@@ -474,42 +442,90 @@ R_DrawQ2AliasFrame
 
 =================
 */
-void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skin, int effects, int flags)
+void R_DrawQ2AliasFrame (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)
 {
        int *order, count;
-       float lerp;
-       md2memframe_t *frame1, *frame2;
+       md2frame_t *frame1, *frame2, *frame3, *frame4;
 
        if (r_render.value)
-               glBindTexture(GL_TEXTURE_2D, skin);
-
-       softwaretransformforentity(ent);
+               glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin));
 
-       if ((frame >= pheader->num_frames) || (frame < 0))
+       if (gl_transform.value)
        {
-               Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
-               frame = 0;
+               if (r_render.value)
+               {
+                       glPushMatrix();
+                       GL_SetupModelTransform(org, angles, scale);
+               }
        }
+       // always needed, for model lighting
+       softwaretransformforentity(ent);
 
-       lerp = R_CalcAnimLerp(ent, frame, 10);
-
-       frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_lastpose));
-       frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_pose));
-       R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
+       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);
+       if (!gl_transform.value)
+               R_AliasTransformVerts(pheader->num_xyz);
 
        R_LightModel(pheader->num_xyz, org, color);
 
        if (!r_render.value)
                return;
-       if (gl_vertexarrays.value)
+       // LordHavoc: big mess...
+       // using vertex arrays only slightly, although it is enough to prevent duplicates
+       // (saving half the transforms)
+       glVertexPointer(3, GL_FLOAT, 0, aliasvert);
+       glColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_COLOR_ARRAY);
+
+       order = (int *)((int)pheader + pheader->ofs_glcmds);
+       while(1)
+       {
+               if (!(count = *order++))
+                       break;
+               if (count > 0)
+                       glBegin(GL_TRIANGLE_STRIP);
+               else
+               {
+                       glBegin(GL_TRIANGLE_FAN);
+                       count = -count;
+               }
+               do
+               {
+                       glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
+                       glArrayElement(order[2]);
+                       order += 3;
+               }
+               while (count--);
+       }
+
+       glDisableClientState(GL_COLOR_ARRAY);
+       glDisableClientState(GL_VERTEX_ARRAY);
+
+       if (fogenabled)
        {
+               glDisable (GL_TEXTURE_2D);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable (GL_BLEND);
+               glDepthMask(0); // disable zbuffer updates
+               {
+                       vec3_t diff;
+                       VectorSubtract(org, r_refdef.vieworg, diff);
+                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+               }
+
                // LordHavoc: big mess...
-               // using arrays only slightly, although it is enough to prevent duplicates
+               // using vertex arrays only slightly, although it is enough to prevent duplicates
                // (saving half the transforms)
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
+               glVertexPointer(3, GL_FLOAT, 0, aliasvert);
                glEnableClientState(GL_VERTEX_ARRAY);
-               glEnableClientState(GL_COLOR_ARRAY);
 
                order = (int *)((int)pheader + pheader->ofs_glcmds);
                while(1)
@@ -525,230 +541,184 @@ void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t
                        }
                        do
                        {
-                               glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
-                               qglArrayElement(order[2]);
+                               glArrayElement(order[2]);
                                order += 3;
                        }
                        while (count--);
                }
 
-               glDisableClientState(GL_COLOR_ARRAY);
                glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
-       {
-               order = (int *)((int)pheader + pheader->ofs_glcmds);
-               while(1)
-               {
-                       if (!(count = *order++))
-                               break;
-                       if (count > 0)
-                               glBegin(GL_TRIANGLE_STRIP);
-                       else
-                       {
-                               glBegin(GL_TRIANGLE_FAN);
-                               count = -count;
-                       }
-                       do
-                       {
-                               glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
-                               glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f));
-                               glVertex3fv(&aliasvert[order[2] * 3]);
-                               order += 3;
-                       }
-                       while (count--);
-               }
+
+               glEnable (GL_TEXTURE_2D);
+               glColor3f (1,1,1);
        }
 
-       if (fogenabled)
-       {
-               glDisable (GL_TEXTURE_2D);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable (GL_BLEND);
-               glDepthMask(0); // disable zbuffer updates
-               {
-                       vec3_t diff;
-                       VectorSubtract(org, r_refdef.vieworg, diff);
-                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
-               }
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(1);
+
+       if (gl_transform.value)
+               glPopMatrix();
+}
 
-               if (gl_vertexarrays.value)
+void ZymoticLerpBones(int count, zymbonematrix *bonebase, frameblend_t *blend, zymbone_t *bone, float rootorigin[3], float rootangles[3], float rootscale)
+{
+       float lerp1, lerp2, lerp3, lerp4;
+       zymbonematrix *out, rootmatrix, m, *bone1, *bone2, *bone3, *bone4;
+       lerp1 = 1 - lerp2;
+       out = zymbonepose;
+       AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]);
+       VectorScale(rootmatrix.m[0], rootscale, rootmatrix.m[0]);
+       VectorScale(rootmatrix.m[1], rootscale, rootmatrix.m[1]);
+       VectorScale(rootmatrix.m[2], rootscale, rootmatrix.m[2]);
+       rootmatrix.m[0][3] = rootorigin[0];
+       rootmatrix.m[1][3] = rootorigin[1];
+       rootmatrix.m[2][3] = rootorigin[2];
+       bone1 = bonebase + blend[0].frame * count;
+       lerp1 = blend[0].lerp;
+       if (blend[1].lerp)
+       {
+               bone2 = bonebase + blend[1].frame * count;
+               lerp2 = blend[1].lerp;
+               if (blend[2].lerp)
                {
-                       // LordHavoc: big mess...
-                       // using arrays only slightly, although it is enough to prevent duplicates
-                       // (saving half the transforms)
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-
-                       order = (int *)((int)pheader + pheader->ofs_glcmds);
-                       while(1)
+                       bone3 = bonebase + blend[2].frame * count;
+                       lerp3 = blend[2].lerp;
+                       if (blend[3].lerp)
                        {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
-                               else
+                               // 4 poses
+                               bone4 = bonebase + blend[3].frame * count;
+                               lerp4 = blend[3].lerp;
+                               while(count--)
                                {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
+                                       // interpolate matrices
+                                       m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
+                                       m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
+                                       m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
+                                       m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
+                                       m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
+                                       m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
+                                       m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
+                                       m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
+                                       m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
+                                       m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
+                                       m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
+                                       m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
+                                       if (bone->parent >= 0)
+                                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
+                                       else
+                                               R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
+                                       bone1++;
+                                       bone2++;
+                                       bone3++;
+                                       bone4++;
+                                       bone++;
+                                       out++;
                                }
-                               do
+                       }
+                       else
+                       {
+                               // 3 poses
+                               while(count--)
                                {
-                                       qglArrayElement(order[2]);
-                                       order += 3;
+                                       // interpolate matrices
+                                       m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
+                                       m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
+                                       m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
+                                       m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
+                                       m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
+                                       m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
+                                       m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
+                                       m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
+                                       m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
+                                       m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
+                                       m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
+                                       m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
+                                       if (bone->parent >= 0)
+                                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
+                                       else
+                                               R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
+                                       bone1++;
+                                       bone2++;
+                                       bone3++;
+                                       bone++;
+                                       out++;
                                }
-                               while (count--);
                        }
-
-                       glDisableClientState(GL_VERTEX_ARRAY);
                }
                else
                {
-                       order = (int *)((int)pheader + pheader->ofs_glcmds);
-                       while(1)
+                       // 2 poses
+                       while(count--)
                        {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
+                               // interpolate matrices
+                               m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
+                               m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
+                               m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
+                               m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
+                               m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
+                               m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
+                               m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
+                               m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
+                               m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
+                               m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
+                               m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
+                               m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
+                               if (bone->parent >= 0)
+                                       R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
                                else
-                               {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
-                               }
-                               do
-                               {
-                                       glVertex3fv(&aliasvert[order[2] * 3]);
-                                       order += 3;
-                               }
-                               while (count--);
+                                       R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
+                               bone1++;
+                               bone2++;
+                               bone++;
+                               out++;
                        }
                }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
        }
-
-       if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
+       else
        {
-               int i;
-               float *av = aliasvert + 2, l = lightspot[2] + 0.125;
-               av = aliasvert + 2;
-               for (i = 0;i < pheader->num_xyz;i++, av+=3)
-                       if (*av > l)
-                               *av = l;
-               glDisable (GL_TEXTURE_2D);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable (GL_BLEND);
-               glDepthMask(0); // disable zbuffer updates
-               glColor4f (0,0,0,0.5 * alpha);
-
-               if (gl_vertexarrays.value)
+               // 1 pose
+               if (lerp1 != 1)
                {
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                                               
-                       while(1)
+                       // lerp != 1.0
+                       while(count--)
                        {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
+                               // interpolate matrices
+                               m.m[0][0] = bone1->m[0][0] * lerp1;
+                               m.m[0][1] = bone1->m[0][1] * lerp1;
+                               m.m[0][2] = bone1->m[0][2] * lerp1;
+                               m.m[0][3] = bone1->m[0][3] * lerp1;
+                               m.m[1][0] = bone1->m[1][0] * lerp1;
+                               m.m[1][1] = bone1->m[1][1] * lerp1;
+                               m.m[1][2] = bone1->m[1][2] * lerp1;
+                               m.m[1][3] = bone1->m[1][3] * lerp1;
+                               m.m[2][0] = bone1->m[2][0] * lerp1;
+                               m.m[2][1] = bone1->m[2][1] * lerp1;
+                               m.m[2][2] = bone1->m[2][2] * lerp1;
+                               m.m[2][3] = bone1->m[2][3] * lerp1;
+                               if (bone->parent >= 0)
+                                       R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
                                else
-                               {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
-                               }
-                               do
-                               {
-                                       qglArrayElement(order[2]);
-                                       order += 3;
-                               }
-                               while (count--);
+                                       R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
+                               bone1++;
+                               bone++;
+                               out++;
                        }
-
-                       glDisableClientState(GL_VERTEX_ARRAY);
                }
                else
                {
-                       while(1)
+                       // lerp == 1.0
+                       while(count--)
                        {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
+                               if (bone->parent >= 0)
+                                       R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]);
                                else
-                               {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
-                               }
-                               do
-                               {
-                                       glVertex3fv(&aliasvert[order[2] * 3]);
-                                       order += 3;
-                               }
-                               while (count--);
+                                       R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]);
+                               bone1++;
+                               bone++;
+                               out++;
                        }
                }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glEnable (GL_BLEND);
-       glDepthMask(1);
-}
-
-void ZymoticLerpBones(int count, float lerp2, zymbonematrix *bone1, zymbonematrix *bone2, zymbone_t *bone, float rootorigin[3], float rootangles[3])
-{
-       float lerp1;
-       zymbonematrix *out, rootmatrix, m;
-       lerp1 = 1 - lerp2;
-       out = zymbonepose;
-       AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]);
-       rootmatrix.m[0][3] = rootorigin[0];
-       rootmatrix.m[1][3] = rootorigin[1];
-       rootmatrix.m[2][3] = rootorigin[2];
-       if (lerp1 != 1) // interpolation
-       {
-               while(count--)
-               {
-                       // interpolate matrices
-                       m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
-                       m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
-                       m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
-                       m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
-                       m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
-                       m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
-                       m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
-                       m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
-                       m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
-                       m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
-                       m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
-                       m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
-                       if (bone->parent >= 0)
-                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
-                       else
-                               R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
-                       bone1++;
-                       bone2++;
-                       bone++;
-                       out++;
-               }
-       }
-       else // no interpolation
-       {
-               while(count--)
-               {
-                       if (bone->parent >= 0)
-                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]);
-                       else
-                               R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]);
-                       bone1++;
-                       bone++;
-                       out++;
-               }
        }
 }
 
@@ -852,65 +822,35 @@ void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist)
 
 void GL_DrawZymoticModelMesh(byte *colors, zymtype1header_t *m)
 {
-       int i, c, *renderlist, *texturenum;
+       int i, c, *renderlist;
+       rtexture_t **texture;
        if (!r_render.value)
                return;
        renderlist = (int *)(m->lump_render.start + (int) m);
-       texturenum = (int *)(m->lump_shaders.start + (int) m);
-       if (gl_vertexarrays.value)
-       {
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               glEnableClientState(GL_VERTEX_ARRAY);
-
-               qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
-               glEnableClientState(GL_COLOR_ARRAY);
+       texture = (rtexture_t **)(m->lump_shaders.start + (int) m);
+       glVertexPointer(3, GL_FLOAT, 0, aliasvert);
+       glEnableClientState(GL_VERTEX_ARRAY);
 
-               qglTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m));
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+       glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
+       glEnableClientState(GL_COLOR_ARRAY);
 
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = (*renderlist++) * 3;
-                       glBindTexture(GL_TEXTURE_2D, *texturenum++);
-                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
-                       renderlist += c;
-               }
+       glTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m));
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       for (i = 0;i < m->numshaders;i++)
+       {
+               c = (*renderlist++) * 3;
+               glBindTexture(GL_TEXTURE_2D, R_GetTexture(*texture));
+               texture++;
+               glDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
+               renderlist += c;
+       }
 
-               glDisableClientState(GL_COLOR_ARRAY);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 
-               glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
-       {
-               int index;
-               float *tex;
-               tex = (float *)(m->lump_texcoords.start + (int) m);
+       glDisableClientState(GL_COLOR_ARRAY);
 
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = *renderlist++;
-                       glBindTexture(GL_TEXTURE_2D, *texturenum++);
-                       glBegin(GL_TRIANGLES);
-                       while (c--)
-                       {
-                               index = *renderlist++;
-                               glTexCoord2fv(tex + index*2);
-                               glColor4ubv(colors + index*4);
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glTexCoord2fv(tex + index*2);
-                               glColor4ubv(colors + index*4);
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glTexCoord2fv(tex + index*2);
-                               glColor4ubv(colors + index*4);
-                               glVertex3fv(aliasvert + index*3);
-                       }
-                       glEnd();
-               }
-       }
+       glDisableClientState(GL_VERTEX_ARRAY);
 }
 
 void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
@@ -927,103 +867,19 @@ void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
 
        VectorSubtract(org, r_refdef.vieworg, diff);
        glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
-       if (gl_vertexarrays.value)
-       {
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               glEnableClientState(GL_VERTEX_ARRAY);
 
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = (*renderlist++) * 3;
-                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
-                       renderlist += c;
-               }
+       glVertexPointer(3, GL_FLOAT, 0, aliasvert);
+       glEnableClientState(GL_VERTEX_ARRAY);
 
-               glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
+       for (i = 0;i < m->numshaders;i++)
        {
-               int index;
-               float *tex;
-               tex = (float *)(m->lump_texcoords.start + (int) m);
-
-               glBegin(GL_TRIANGLES);
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = *renderlist++;
-                       while (c--)
-                       {
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                       }
-               }
-               glEnd();
+               c = (*renderlist++) * 3;
+               glDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
+               renderlist += c;
        }
-       glEnable(GL_TEXTURE_2D);
-       glColor3f (1,1,1);
-}
-
-void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m)
-{
-       int i, c, *renderlist;
-       float *av, l;
-       if (!r_render.value)
-               return;
-
-       // flatten it to make a shadow
-       av = aliasvert + 2;
-       l = lightspot[2] + 0.125;
-       for (i = 0;i < m->numverts;i++, av+=3)
-               if (*av > l)
-                       *av = l;
-
-       renderlist = (int *)(m->lump_render.start + (int) m);
-       glDisable(GL_TEXTURE_2D);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glEnable (GL_BLEND);
-       glDepthMask(0); // disable zbuffer updates
-
-       glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
-       if (gl_vertexarrays.value)
-       {
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               glEnableClientState(GL_VERTEX_ARRAY);
 
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = (*renderlist++) * 3;
-                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
-                       renderlist += c;
-               }
-
-               glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
-       {
-               int index;
-               float *tex;
-               tex = (float *)(m->lump_texcoords.start + (int) m);
+       glDisableClientState(GL_VERTEX_ARRAY);
 
-               glBegin(GL_TRIANGLES);
-               for (i = 0;i < m->numshaders;i++)
-               {
-                       c = *renderlist++;
-                       while (c--)
-                       {
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                               index = *renderlist++;
-                               glVertex3fv(aliasvert + index*3);
-                       }
-               }
-               glEnd();
-       }
        glEnable(GL_TEXTURE_2D);
        glColor3f (1,1,1);
 }
@@ -1033,47 +889,9 @@ void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m)
 R_DrawZymoticFrame
 =================
 */
-void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skinblah, int effects, int flags)
+void R_DrawZymoticFrame (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)
 {
-       zymscene_t *scene;
-       float scenetime, scenefrac;
-       int sceneframe1, sceneframe2;
-       zymbonematrix *basebonepose;
-       if ((frame >= m->numscenes) || (frame < 0))
-       {
-               Con_DPrintf ("R_ZymoticSetupFrame: no such frame %d\n", frame);
-               frame = 0;
-       }
-
-       scene = (zymscene_t *)(m->lump_scenes.start + (int) m) + frame;
-       if (ent->draw_lastmodel != ent->model || ent->draw_pose != frame || ent->draw_lerpstart >= cl.time)
-       {
-               ent->draw_lastmodel = ent->model;
-               ent->draw_lastpose = -1;
-               ent->draw_pose = frame;
-               ent->draw_lerpstart = cl.time;
-       }
-       scenetime = (cl.time - ent->draw_lerpstart) * scene->framerate;
-       sceneframe1 = (int) scenetime;
-       sceneframe2 = sceneframe1 + 1;
-       scenefrac = scenetime - sceneframe1;
-       if (scene->flags & ZYMSCENEFLAG_NOLOOP)
-       {
-               if (sceneframe1 > (scene->length - 1))
-                       sceneframe1 = (scene->length - 1);
-               if (sceneframe2 > (scene->length - 1))
-                       sceneframe2 = (scene->length - 1);
-       }
-       else
-       {
-               sceneframe1 %= scene->length;
-               sceneframe2 %= scene->length;
-       }
-       if (sceneframe2 == sceneframe1)
-               scenefrac = 0;
-
-       basebonepose = (zymbonematrix *)(m->lump_poses.start + (int) m);
-       ZymoticLerpBones(m->numbones, scenefrac, basebonepose + sceneframe1 * m->numbones, basebonepose + sceneframe2 * m->numbones, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles);
+       ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), blend, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles, 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));
 
@@ -1106,15 +924,11 @@ void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_
        if (fogenabled)
                GL_DrawZymoticModelMeshFog(org, m);
 
-       if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
-               GL_DrawZymoticModelMeshShadow(m);
-
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable (GL_BLEND);
        glDepthMask(1);
 }
 
-int modeldlightbits[8];
 extern int r_dlightframecount;
 
 /*
@@ -1123,13 +937,12 @@ R_DrawAliasModel
 
 =================
 */
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap)
+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)
 {
        int                     i;
        vec3_t          mins, maxs, color;
-       mleaf_t         *leaf;
        void            *modelheader;
-       int                     *skinset;
+       rtexture_t      **skinset;
 
        if (alpha < (1.0 / 64.0))
                return; // basically completely transparent
@@ -1142,30 +955,6 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i
 
        c_models++;
 
-       leaf = Mod_PointInLeaf (org, cl.worldmodel);
-       if (leaf->dlightframe == r_dlightframecount)
-               for (i = 0;i < 8;i++)
-                       modeldlightbits[i] = leaf->dlightbits[i];
-       else
-               for (i = 0;i < 8;i++)
-                       modeldlightbits[i] = 0;
-
-       // get lighting information
-
-       if ((flags & EF_FULLBRIGHT) || (effects & EF_FULLBRIGHT))
-               color[0] = color[1] = color[2] = 256;
-       else
-               R_LightPoint (color, org);
-
-       if (r_render.value)
-               glDisable(GL_ALPHA_TEST);
-
-       if (frame < 0 || frame >= clmodel->numframes)
-       {
-               frame = 0;
-               Con_DPrintf("invalid skin number %d for model %s\n", frame, clmodel->name);
-       }
-
        if (skin < 0 || skin >= clmodel->numskins)
        {
                skin = 0;
@@ -1178,7 +967,7 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i
 //             int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
 //             int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
                int *skinanimrange = clmodel->skinanimrange + skin * 2;
-               int *skinanim = clmodel->skinanim;
+               rtexture_t **skinanim = clmodel->skinanim;
                i = skinanimrange[0];
                if (skinanimrange[1] > 1) // animated
                        i += ((int) (cl.time * 10) % skinanimrange[1]);
@@ -1190,9 +979,9 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i
 
        c_alias_polys += clmodel->numtris;
        if (clmodel->aliastype == ALIASTYPE_ZYM)
-               R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, 0, effects, flags);
+               R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, 0                   , effects, flags);
        else if (clmodel->aliastype == ALIASTYPE_MD2)
-               R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset[0], effects, flags);
+               R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset[0]          , effects, flags);
        else
-               R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset, colormap, effects, flags);
+               R_DrawAliasFrame   (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset   , colormap, effects, flags);
 }
index 2f53d5cd260f765c29639ecca94bc1472c86fa15..4eb8bafebd634f45516b7953cd7e6a401914dc4e 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -4,19 +4,19 @@ transvert_t *transvert;
 transpoly_t *transpoly;
 unsigned short *transpolyindex;
 wallvert_t *wallvert;
+wallvertcolor_t *wallvertcolor;
 wallpoly_t *wallpoly;
 skyvert_t *skyvert;
 skypoly_t *skypoly;
 
-unsigned short currenttranspoly;
-unsigned short currenttransvert;
-unsigned short currentwallpoly;
-unsigned short currentwallvert;
-unsigned short currentskypoly;
-unsigned short currentskyvert;
+int currenttranspoly;
+int currenttransvert;
+int currentwallpoly;
+int currentwallvert;
+int currentskypoly;
+int currentskyvert;
 
 cvar_t gl_multitexture = {"gl_multitexture", "1"};
-cvar_t gl_vertexarrays = {"gl_vertexarrays", "1"};
 
 typedef struct translistitem_s
 {
@@ -41,6 +41,7 @@ void gl_poly_start()
        transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
        transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(unsigned short));
        wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t));
+       wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t));
        wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t));
        skyvert = qmalloc(MAX_SKYVERTS * sizeof(skyvert_t));
        skypoly = qmalloc(MAX_SKYPOLYS * sizeof(skypoly_t));
@@ -54,6 +55,7 @@ void gl_poly_shutdown()
        qfree(transpoly);
        qfree(transpolyindex);
        qfree(wallvert);
+       qfree(wallvertcolor);
        qfree(wallpoly);
        qfree(skyvert);
        qfree(skypoly);
@@ -62,7 +64,6 @@ void gl_poly_shutdown()
 void GL_Poly_Init()
 {
        Cvar_RegisterVariable (&gl_multitexture);
-       Cvar_RegisterVariable (&gl_vertexarrays);
        R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown);
 }
 
@@ -382,10 +383,7 @@ void transpolyrender()
        glEnable(GL_BLEND);
        glShadeModel(GL_SMOOTH);
        glDepthMask(0); // disable zbuffer updates
-       if (isG200) // Matrox G200 cards can't handle per pixel alpha
-               glEnable(GL_ALPHA_TEST);
-       else
-               glDisable(GL_ALPHA_TEST);
+       glDisable(GL_ALPHA_TEST);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        tpolytype = TPOLYTYPE_ALPHA;
        texnum = -1;
@@ -393,7 +391,7 @@ void transpolyrender()
        if (gl_vertexarrays.value)
        {
                // set up the vertex array
-               qglInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert);
+               glInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert);
                for (i = 0;i < transpolyindices;i++)
                {
                        p = &transpoly[transpolyindex[i]];
@@ -413,14 +411,14 @@ void transpolyrender()
                                                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                }
                        }
-                       qglDrawArrays(GL_POLYGON, p->firstvert, p->verts);
+                       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);
-                               qglDrawArrays(GL_POLYGON, p->firstvert, p->verts);
+                               glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                        }
                }
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -445,7 +443,8 @@ void transpolyrender()
                                        glEnd();
                                        if (isG200)
                                        {
-                                               if (p->fogtexnum) // alpha
+                                               // LordHavoc: Matrox G200 cards can't handle per pixel alpha
+                                               if (p->fogtexnum)
                                                        glEnable(GL_ALPHA_TEST);
                                                else
                                                        glDisable(GL_ALPHA_TEST);
@@ -568,6 +567,7 @@ void wallpolyrender()
        int i, j, texnum, lighttexnum;
        wallpoly_t *p;
        wallvert_t *vert;
+       wallvertcolor_t *vertcolor;
        if (!r_render.value)
                return;
        if (currentwallpoly < 1)
@@ -582,7 +582,7 @@ void wallpolyrender()
        glShadeModel(GL_FLAT);
        // make sure zbuffer is enabled
        glEnable(GL_DEPTH_TEST);
-       glDisable(GL_ALPHA_TEST);
+//     glDisable(GL_ALPHA_TEST);
        glDepthMask(1);
        glColor3f(1,1,1);
        if (r_fullbright.value) // LordHavoc: easy to do fullbright...
@@ -600,7 +600,7 @@ void wallpolyrender()
                        glBegin(GL_POLYGON);
                        for (j=0 ; j<p->numverts ; j++, vert++)
                        {
-                               glTexCoord2f (vert->s, vert->t);
+                               glTexCoord2f (vert->vert[3], vert->vert[4]);
                                glVertex3fv (vert->vert);
                        }
                        glEnd ();
@@ -631,8 +631,8 @@ void wallpolyrender()
                        glBegin(GL_POLYGON);
                        for (j=0 ; j<p->numverts ; j++, vert++)
                        {
-                               qglMTexCoord2f(gl_mtex_enum, vert->s, vert->t); // texture
-                               qglMTexCoord2f((gl_mtex_enum+1), vert->u, vert->v); // lightmap
+                               qglMTexCoord2f(gl_mtex_enum, vert->vert[3], vert->vert[4]); // texture
+                               qglMTexCoord2f((gl_mtex_enum+1), vert->vert[5], vert->vert[6]); // lightmap
                                glVertex3fv (vert->vert);
                        }
                        glEnd ();
@@ -660,7 +660,7 @@ void wallpolyrender()
                        glBegin(GL_POLYGON);
                        for (j=0 ; j<p->numverts ; j++, vert++)
                        {
-                               glTexCoord2f (vert->s, vert->t);
+                               glTexCoord2f (vert->vert[3], vert->vert[4]);
                                glVertex3fv (vert->vert);
                        }
                        glEnd ();
@@ -681,7 +681,7 @@ void wallpolyrender()
                        glBegin(GL_POLYGON);
                        for (j=0 ; j<p->numverts ; j++, vert++)
                        {
-                               glTexCoord2f (vert->u, vert->v);
+                               glTexCoord2f (vert->vert[5], vert->vert[6]);
                                glVertex3fv (vert->vert);
                        }
                        glEnd ();
@@ -692,7 +692,7 @@ void wallpolyrender()
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        glEnable(GL_BLEND);
-       glDisable(GL_ALPHA_TEST);
+//     glDisable(GL_ALPHA_TEST);
        glShadeModel(GL_SMOOTH);
        // render vertex lit overlays ontop
        texnum = -1;
@@ -700,8 +700,8 @@ void wallpolyrender()
        {
                if (!p->lit)
                        continue;
-               for (j = 0,vert = &wallvert[p->firstvert];j < p->numverts;j++, vert++)
-                       if (vert->r || vert->g || vert->b)
+               for (j = 0,vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vertcolor++)
+                       if (vertcolor->r || vertcolor->g || vertcolor->b)
                                goto lit;
                continue;
 lit:
@@ -712,12 +712,12 @@ lit:
                        glBindTexture(GL_TEXTURE_2D, texnum);
                }
                glBegin(GL_POLYGON);
-               for (j = 0,vert = &wallvert[p->firstvert];j < p->numverts;j++, vert++)
+               for (j = 0,vert = &wallvert[p->firstvert], vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vert++, vertcolor++)
                {
                        // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
-                       glTexCoord2f(vert->s, vert->t);
+                       glTexCoord2f(vert->vert[3], vert->vert[4]);
                        // again, vector version isn't supported I think
-                       glColor3ub(vert->r, vert->g, vert->b);
+                       glColor3ub(vertcolor->r, vertcolor->g, vertcolor->b);
                        glVertex3fv(vert->vert);
                }
                glEnd();
@@ -743,7 +743,7 @@ lit:
                glBegin(GL_POLYGON);
                for (j=0 ; j<p->numverts ; j++, vert++)
                {
-                       glTexCoord2f (vert->s, vert->t);
+                       glTexCoord2f (vert->vert[3], vert->vert[4]);
                        glVertex3fv (vert->vert);
                }
                glEnd();
@@ -771,7 +771,7 @@ lit:
        }
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glDisable(GL_ALPHA_TEST);
+//     glDisable(GL_ALPHA_TEST);
        glShadeModel(GL_SMOOTH);
        glDisable(GL_BLEND);
        glDepthMask(1);
@@ -783,10 +783,10 @@ void skypolyclear()
 }
 
 extern char skyname[];
-extern int solidskytexture, alphaskytexture;
+extern rtexture_t *solidskytexture, *alphaskytexture;
 void skypolyrender()
 {
-       int i, j;
+       int i, j, numskyverts;
        skypoly_t *p;
        skyvert_t *vert;
        float length, speedscale;
@@ -797,13 +797,18 @@ void skypolyrender()
                return;
        // testing
 //     Con_DPrintf("skypolyrender: %i polys %i vertices\n", currentskypoly, currentskyvert);
-       glDisable(GL_ALPHA_TEST);
+//     glDisable(GL_ALPHA_TEST);
        glDisable(GL_BLEND);
        // make sure zbuffer is enabled
        glEnable(GL_DEPTH_TEST);
        glDepthMask(1);
        if (!fogenabled && !skyname[0]) // normal quake sky
        {
+               glInterleavedArrays(GL_T2F_V3F, 0, skyvert);
+//             glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 2, &skyvert[0].tex[0]);
+//             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+//             glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]);
+//             glEnableClientState(GL_VERTEX_ARRAY);
                if(lighthalf)
                        glColor3f(0.5f, 0.5f, 0.5f);
                else
@@ -812,14 +817,14 @@ void skypolyrender()
                glEnable(GL_TEXTURE_2D);
                glDisable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glBindTexture(GL_TEXTURE_2D, solidskytexture); // upper clouds
+               glBindTexture(GL_TEXTURE_2D, R_GetTexture(solidskytexture)); // upper clouds
                speedscale = cl.time*8;
                speedscale -= (int)speedscale & ~127 ;
-               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+               numskyverts = 0;
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                {
-                       vert = &skyvert[p->firstvert];
-                       glBegin(GL_POLYGON);
-                       for (j=0 ; j<p->verts ; j++, vert++)
+                       vert = skyvert + p->firstvert;
+                       for (j = 0;j < p->verts;j++, vert++)
                        {
                                VectorSubtract (vert->v, r_origin, dir);
                                dir[2] *= 3;    // flatten the sphere
@@ -828,21 +833,24 @@ void skypolyrender()
                                length = sqrt (length);
                                length = 6*63/length;
 
-                               glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128));
-                               glVertex3fv (vert->v);
+                               vert->tex[0] = (speedscale + dir[0] * length) * (1.0/128);
+                               vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128);
                        }
-                       glEnd ();
+                       numskyverts += p->verts;
                }
+               GL_LockArray(0, numskyverts);
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
+                       glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
+               GL_UnlockArray();
                glEnable(GL_BLEND);
                glDepthMask(0);
-               glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds
+               glBindTexture(GL_TEXTURE_2D, R_GetTexture(alphaskytexture)); // lower clouds
                speedscale = cl.time*16;
                speedscale -= (int)speedscale & ~127 ;
-               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
                {
-                       vert = &skyvert[p->firstvert];
-                       glBegin(GL_POLYGON);
-                       for (j=0 ; j<p->verts ; j++, vert++)
+                       vert = skyvert + p->firstvert;
+                       for (j = 0;j < p->verts;j++, vert++)
                        {
                                VectorSubtract (vert->v, r_origin, dir);
                                dir[2] *= 3;    // flatten the sphere
@@ -851,29 +859,36 @@ void skypolyrender()
                                length = sqrt (length);
                                length = 6*63/length;
 
-                               glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128));
-                               glVertex3fv (vert->v);
+                               vert->tex[0] = (speedscale + dir[0] * length) * (1.0/128);
+                               vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128);
                        }
-                       glEnd ();
                }
+               GL_LockArray(0, numskyverts);
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
+                       glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
+               GL_UnlockArray();
                glDisable(GL_BLEND);
                glColor3f(1,1,1);
                glDepthMask(1);
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+               glDisableClientState(GL_VERTEX_ARRAY);
        }
        else
        {
+               glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]);
+               glEnableClientState(GL_VERTEX_ARRAY);
                glDisable(GL_TEXTURE_2D);
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                glColor3fv(fogcolor); // note: gets rendered over by skybox if fog is not enabled
-               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
-               {
-                       vert = &skyvert[p->firstvert];
-                       glBegin(GL_POLYGON);
-                       for (j=0 ; j<p->verts ; j++, vert++)
-                               glVertex3fv (vert->v);
-                       glEnd ();
-               }
+               numskyverts = 0;
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
+                       numskyverts += p->verts;
+               GL_LockArray(0, numskyverts);
+               for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
+                       glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
+               GL_UnlockArray();
                glColor3f(1,1,1);
                glEnable(GL_TEXTURE_2D);
+               glDisableClientState(GL_VERTEX_ARRAY);
        }
 }
index 429b97b3af11678e5d6690c2e74aa18fefef357c..24ece5f538c18ffbc004ce717fe7f4cb8546f770 100644 (file)
--- a/gl_poly.h
+++ b/gl_poly.h
@@ -30,7 +30,8 @@ typedef struct
        vec_t s, t;
        byte r,g,b,a;
        vec3_t v;
-} transvert_t;
+}
+transvert_t;
 
 typedef struct
 {
@@ -44,14 +45,21 @@ typedef struct
        unsigned short firstvert;
        unsigned short verts;
        unsigned short transpolytype;
-} transpoly_t;
+}
+transpoly_t;
+
+// note: must match format of glpoly_t vertices due to a memcpy used in RSurf_DrawWall
+typedef struct
+{
+       vec_t vert[VERTEXSIZE]; // xyz st uv
+}
+wallvert_t;
 
 typedef struct
 {
-       vec3_t vert;
-       vec_t s, t, u, v;
        byte r,g,b,a;
-} wallvert_t;
+}
+wallvertcolor_t;
 
 typedef struct
 {
@@ -59,33 +67,39 @@ typedef struct
        unsigned short firstvert;
        unsigned short numverts;
        unsigned short lit; // doesn't need to be an unsigned short, but to keep the structure consistent...
-} wallpoly_t;
+}
+wallpoly_t;
 
 typedef struct
 {
+       // the order and type of these is crucial to the vertex array based rendering 
+       vec2_t tex;
        vec3_t v;
-} skyvert_t;
+}
+skyvert_t;
 
 typedef struct
 {
        unsigned short firstvert;
        unsigned short verts;
-} skypoly_t;
+}
+skypoly_t;
 
 extern transvert_t *transvert;
 extern transpoly_t *transpoly;
 extern unsigned short *transpolyindex;
 extern wallvert_t *wallvert;
+extern wallvertcolor_t *wallvertcolor;
 extern wallpoly_t *wallpoly;
 extern skyvert_t *skyvert;
 extern skypoly_t *skypoly;
 
-extern unsigned short currenttranspoly;
-extern unsigned short currenttransvert;
-extern unsigned short currentwallpoly;
-extern unsigned short currentwallvert;
-extern unsigned short currentskypoly;
-extern unsigned short currentskyvert;
+extern int currenttranspoly;
+extern int currenttransvert;
+extern int currentwallpoly;
+extern int currentwallvert;
+extern int currentskypoly;
+extern int currentskyvert;
 
 #define transpolybegin(ttexnum, tglowtexnum, tfogtexnum, ttranspolytype)\
 {\
@@ -126,3 +140,30 @@ extern unsigned short currentskyvert;
                transpoly[currenttranspoly].verts++;\
        }\
 }
+
+#define transpolyvertub(vx,vy,vz,vs,vt,vr,vg,vb,va) \
+{\
+       if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert < MAX_TRANSVERTS)\
+       {\
+               transvert[currenttransvert].s = (vs);\
+               transvert[currenttransvert].t = (vt);\
+               if (lighthalf)\
+               {\
+                       transvert[currenttransvert].r = (vr) >> 1;\
+                       transvert[currenttransvert].g = (vg) >> 1;\
+                       transvert[currenttransvert].b = (vb) >> 1;\
+               }\
+               else\
+               {\
+                       transvert[currenttransvert].r = (vr);\
+                       transvert[currenttransvert].g = (vg);\
+                       transvert[currenttransvert].b = (vb);\
+               }\
+               transvert[currenttransvert].a = (va);\
+               transvert[currenttransvert].v[0] = (vx);\
+               transvert[currenttransvert].v[1] = (vy);\
+               transvert[currenttransvert].v[2] = (vz);\
+               currenttransvert++;\
+               transpoly[currenttranspoly].verts++;\
+       }\
+}
index 11a1c481cc255973d7946c656d628386afbb506d..c4a257d239f4016a08b00ae0b56c65e1730a3361 100644 (file)
@@ -73,7 +73,6 @@ cvar_t        r_speeds = {"r_speeds","0"};
 cvar_t r_speeds2 = {"r_speeds2","0"};
 cvar_t r_fullbright = {"r_fullbright","0"};
 //cvar_t       r_lightmap = {"r_lightmap","0"};
-cvar_t r_shadows = {"r_shadows","0"};
 cvar_t r_wateralpha = {"r_wateralpha","1"};
 cvar_t r_dynamic = {"r_dynamic","1"};
 cvar_t r_novis = {"r_novis","0"};
@@ -225,7 +224,6 @@ void GL_Main_Init()
        FOG_registercvars();
        Cvar_RegisterVariable (&r_drawentities);
        Cvar_RegisterVariable (&r_drawviewmodel);
-       Cvar_RegisterVariable (&r_shadows);
        Cvar_RegisterVariable (&r_speeds);
        Cvar_RegisterVariable (&r_speeds2);
        Cvar_RegisterVariable (&contrast);
@@ -257,6 +255,7 @@ extern void R_Crosshairs_Init();
 extern void R_Light_Init();
 extern void R_Particles_Init();
 extern void R_Explosion_Init();
+extern void CL_Effects_Init();
 
 void Render_Init()
 {
@@ -272,6 +271,7 @@ void Render_Init()
        R_Light_Init();
        R_Particles_Init();
        R_Explosion_Init();
+       CL_Effects_Init();
        R_StartModules();
 }
 
@@ -280,7 +280,7 @@ void Render_Init()
 GL_Init
 ===============
 */
-extern char *QSG_EXTENSIONS;
+extern char *ENGINE_EXTENSIONS;
 void GL_Init (void)
 {
        gl_vendor = glGetString (GL_VENDOR);
@@ -296,10 +296,10 @@ void GL_Init (void)
 //     Con_Printf ("%s %s\n", gl_renderer, gl_version);
 
        VID_CheckMultitexture();
-       VID_CheckVertexArrays();
+       VID_CheckCVA();
 
        // LordHavoc: report supported extensions
-       Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
+       Con_Printf ("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
 
        glCullFace(GL_FRONT);
        glEnable(GL_TEXTURE_2D);
@@ -325,13 +325,6 @@ void R_RotateForEntity (entity_t *e)
 }
 */
 
-// LordHavoc: if not for the fact BRIGHTFIELD particles require this, it would be removed...
-#define NUMVERTEXNORMALS       162
-
-float  r_avertexnormals[NUMVERTEXNORMALS][3] = {
-#include "anorms.h"
-};
-
 // LordHavoc: shading stuff
 vec3_t shadevector;
 vec3_t shadecolor;
@@ -341,7 +334,49 @@ float      modelalpha;
 //==================================================================================
 
 void R_DrawBrushModel (entity_t *e);
-void R_DrawSpriteModel (entity_t *e);
+void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
+
+void R_LerpUpdate(entity_t *ent)
+{
+       int frame;
+       frame = ent->frame;
+       if (ent->model && ent->frame >= ent->model->numframes)
+       {
+               Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->frame, ent->model->name);
+               frame = 0;
+       }
+
+       if (ent->lerp_model != ent->model)
+       {
+               // reset all interpolation information
+               ent->lerp_model = ent->model;
+               ent->frame1 = ent->frame2 = frame;
+               ent->frame1start = ent->frame2start = cl.time;
+               ent->framelerp = 1;
+               ent->lerp_starttime = 0;
+       }
+       else if (ent->frame2 != frame)
+       {
+               // transition to new frame
+               ent->frame1 = ent->frame2;
+               ent->frame1start = ent->frame2start;
+               ent->frame2 = frame;
+               ent->frame2start = cl.time;
+               ent->framelerp = 0;
+               ent->lerp_starttime = cl.time;
+       }
+       else
+       {
+               // lerp_starttime < 0 is used to prevent changing of framelerp
+               if (ent->lerp_starttime >= 0)
+               {
+                       // update transition
+                       ent->framelerp = (cl.time - ent->lerp_starttime) * 10;
+                       ent->framelerp = bound(0, ent->framelerp, 1);
+               }
+       }
+}
+
 
 /*
 =============
@@ -370,6 +405,7 @@ void R_DrawEntitiesOnList1 (void)
 void R_DrawEntitiesOnList2 (void)
 {
        int             i;
+       frameblend_t blend[4];
 
        if (!r_drawentities.value)
                return;
@@ -382,11 +418,18 @@ void R_DrawEntitiesOnList2 (void)
                switch (currententity->model->type)
                {
                case mod_alias:
-                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap);
+                       if (!strcmp(currententity->model->name, "progs/flame2.mdl"))
+                               blend[0].frame = 0;
+
+                       R_LerpUpdate(currententity);
+                       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
+                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap);
                        break;
 
                case mod_sprite:
-                       R_DrawSpriteModel (currententity);
+                       R_LerpUpdate(currententity);
+                       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
+                       R_DrawSpriteModel (currententity, blend);
                        break;
 
                default:
@@ -402,6 +445,8 @@ 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.model)
                return;
 
@@ -411,9 +456,12 @@ void R_DrawViewModel (void)
        currententity->scale = 1;
        VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod);
 
+       R_LerpUpdate(currententity);
+       R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend);
+
        // 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->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap);
+       R_DrawAliasModel (currententity, false, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap);
        glDepthRange (gldepthmin, gldepthmax);
 }
 
@@ -746,9 +794,6 @@ void R_RenderView (void)
        else
                starttime = currtime = 0;
        R_Clear();
-       skypolyclear();
-       wallpolyclear();
-       transpolyclear();
        skyisvisible = false;
        TIMEREPORT(time_clear)
 
@@ -757,6 +802,11 @@ void R_RenderView (void)
        R_SetupFrame ();
        R_SetFrustum ();
        R_SetupGL ();
+
+       skypolyclear();
+       wallpolyclear();
+       transpolyclear();
+
        TIMEREPORT(time_setup)
 
        R_MarkLeaves ();        // done here so we know if we're in water
@@ -777,8 +827,8 @@ void R_RenderView (void)
        wallpolyrender();
        TIMEREPORT(time_wall)
 
-//     if (!intimerefresh)
-//             S_ExtraUpdate ();       // don't let sound get messed up if going slow
+       if (!intimerefresh && !r_speeds2.value)
+               S_ExtraUpdate ();       // don't let sound get messed up if going slow
 
        R_DrawEntitiesOnList2 (); // other models
 //     R_RenderDlights ();
index 7276632e7a43564f1ce9e26fec8dc85b827c8a69..bde929ec7f3e4876f2dd1d1f60253a1f51caac73 100644 (file)
@@ -54,8 +54,6 @@ cvar_t r_dlightmap = {"r_dlightmap", "1"};
 qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible;
 int lightmapbytes;
 
-extern qboolean gl_arrays;
-
 extern int r_dlightframecount;
 
 void gl_surf_start()
@@ -81,14 +79,6 @@ void GL_Surf_Init()
        Cvar_RegisterVariable(&r_newworldnode);
        Cvar_RegisterVariable(&r_oldclip);
        Cvar_RegisterVariable(&r_dlightmap);
-       // check if it's the glquake minigl driver
-       if (strncasecmp(gl_vendor,"3Dfx",4)==0)
-       if (!gl_arrays)
-       {
-//             Cvar_SetValue("gl_nosubimagefragments", 1);
-//             Cvar_SetValue("gl_nosubimage", 1);
-               Cvar_SetValue("gl_lightmode", 0);
-       }
 
        R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown);
 }
@@ -100,20 +90,17 @@ int         dlightdivtable[32768];
 */
 int R_AddDynamicLights (msurface_t *surf)
 {
-       int         sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, j, s, t, smax, tmax, red, green, blue, lit, dist2, impacts, impactt;
+       int         sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, red, green, blue, lit, dist2, impacts, impactt;
        unsigned int *bl;
        float       dist;
        vec3_t      impact, local;
 
        // LordHavoc: use 64bit integer...  shame it's not very standardized...
-//#if _MSC_VER || __BORLANDC__
-//     __int64     k;
-//#else
-//     long long   k;
-//#endif
-
-       // LordHavoc: later note: MSVC and hopefully all other C compilers use a 64bit result for 32bit*32bit multiply, so that was not necessary
-       int                     k;
+#if _MSC_VER || __BORLANDC__
+       __int64     k;
+#else
+       long long   k;
+#endif
 
        lit = false;
 
@@ -136,7 +123,7 @@ int R_AddDynamicLights (msurface_t *surf)
                dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
 
                // for comparisons to minimum acceptable light
-               maxdist = (int) ((cl_dlights[lnum].radius * cl_dlights[lnum].radius) * LIGHTSCALE);
+               maxdist = (int) ((cl_dlights[lnum].radius * cl_dlights[lnum].radius));
 
                // clamp radius to avoid exceeding 32768 entry division table
                if (maxdist > 4194304)
@@ -161,7 +148,7 @@ int R_AddDynamicLights (msurface_t *surf)
 
                // reduce calculations
                for (s = 0, i = impacts; s < smax; s++, i -= 16)
-                       sdtable[s] = i * i + dist2;
+                       sdtable[s] = i * i + dist2 + LIGHTOFFSET;
 
                maxdist3 = maxdist - (int) (dist * dist);
 
@@ -184,9 +171,9 @@ int R_AddDynamicLights (msurface_t *surf)
                                        if (sdtable[s] < maxdist2)
                                        {
                                                k = dlightdivtable[(sdtable[s] + td) >> 7];
-                                               j = (red   * k) >> 9;bl[0] += j;
-                                               j = (green * k) >> 9;bl[1] += j;
-                                               j = (blue  * k) >> 9;bl[2] += j;
+                                               bl[0] += (red   * k) >> 9;
+                                               bl[1] += (green * k) >> 9;
+                                               bl[2] += (blue  * k) >> 9;
                                                lit = true;
                                        }
                                        bl += 3;
@@ -200,6 +187,70 @@ int R_AddDynamicLights (msurface_t *surf)
 }
 
 
+void R_ConvertLightmap (int *in, byte *out, int width, int height, int stride)
+{
+       int i, j;
+       stride -= (width*lightmapbytes);
+       if (lighthalf)
+       {
+               // LordHavoc: I shift down by 8 unlike GLQuake's 7,
+               // the image is brightened as a processing pass
+               if (lightmaprgba)
+               {
+                       for (i = 0;i < height;i++, out += stride)
+                       {
+                               for (j = 0;j < width;j++, in += 3, out += 4)
+                               {
+                                       out[0] = min(in[0] >> 8, 255);
+                                       out[1] = min(in[1] >> 8, 255);
+                                       out[2] = min(in[2] >> 8, 255);
+                                       out[3] = 255;
+                               }
+                       }
+               }
+               else
+               {
+                       for (i = 0;i < height;i++, out += stride)
+                       {
+                               for (j = 0;j < width;j++, in += 3, out += 3)
+                               {
+                                       out[0] = min(in[0] >> 8, 255);
+                                       out[1] = min(in[1] >> 8, 255);
+                                       out[2] = min(in[2] >> 8, 255);
+                               }
+                       }
+               }
+       }
+       else
+       {
+               if (lightmaprgba)
+               {
+                       for (i = 0;i < height;i++, out += stride)
+                       {
+                               for (j = 0;j < width;j++, in += 3, out += 4)
+                               {
+                                       out[0] = min(in[0] >> 7, 255);
+                                       out[1] = min(in[1] >> 7, 255);
+                                       out[2] = min(in[2] >> 7, 255);
+                                       out[3] = 255;
+                               }
+                       }
+               }
+               else
+               {
+                       for (i = 0;i < height;i++, out += stride)
+                       {
+                               for (j = 0;j < width;j++, in += 3, out += 3)
+                               {
+                                       out[0] = min(in[0] >> 7, 255);
+                                       out[1] = min(in[1] >> 7, 255);
+                                       out[2] = min(in[2] >> 7, 255);
+                               }
+                       }
+               }
+       }
+}
+
 /*
 ===============
 R_BuildLightMap
@@ -227,7 +278,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
        lightmap = surf->samples;
 
 // set to full bright if no light data
-       if (currententity->effects & EF_FULLBRIGHT || !cl.worldmodel->lightdata)
+       if (currententity && currententity->effects & EF_FULLBRIGHT || !cl.worldmodel->lightdata)
        {
                bl = blocklights;
                for (i=0 ; i<size ; i++)
@@ -266,66 +317,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
                        if ((surf->cached_dlight = R_AddDynamicLights(surf)))
                                c_light_polys++;
        }
-       stride -= (smax*lightmapbytes);
-       bl = blocklights;
-       if (lighthalf)
-       {
-               // LordHavoc: I shift down by 8 unlike GLQuake's 7,
-               // the image is brightened as a processing pass
-               if (lightmaprgba)
-               {
-                       for (i = 0;i < tmax;i++, dest += stride)
-                       {
-                               for (j = 0;j < smax;j++, bl += 3, dest += 4)
-                               {
-                                       dest[0] = min(bl[0] >> 8, 255);
-                                       dest[1] = min(bl[1] >> 8, 255);
-                                       dest[2] = min(bl[2] >> 8, 255);
-                                       dest[3] = 255;
-                               }
-                       }
-               }
-               else
-               {
-                       for (i = 0;i < tmax;i++, dest += stride)
-                       {
-                               for (j = 0;j < smax;j++, bl += 3, dest += 3)
-                               {
-                                       dest[0] = min(bl[0] >> 8, 255);
-                                       dest[1] = min(bl[1] >> 8, 255);
-                                       dest[2] = min(bl[2] >> 8, 255);
-                               }
-                       }
-               }
-       }
-       else
-       {
-               if (lightmaprgba)
-               {
-                       for (i = 0;i < tmax;i++, dest += stride)
-                       {
-                               for (j = 0;j < smax;j++, bl += 3, dest += 4)
-                               {
-                                       dest[0] = min(bl[0] >> 7, 255);
-                                       dest[1] = min(bl[1] >> 7, 255);
-                                       dest[2] = min(bl[2] >> 7, 255);
-                                       dest[3] = 255;
-                               }
-                       }
-               }
-               else
-               {
-                       for (i = 0;i < tmax;i++, dest += stride)
-                       {
-                               for (j = 0;j < smax;j++, bl += 3, dest += 3)
-                               {
-                                       dest[0] = min(bl[0] >> 7, 255);
-                                       dest[1] = min(bl[1] >> 7, 255);
-                                       dest[2] = min(bl[2] >> 7, 255);
-                               }
-                       }
-               }
-       }
+       R_ConvertLightmap(blocklights, dest, smax, tmax, stride);
 }
 
 byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4];
@@ -428,7 +420,6 @@ extern      float   speedscale;             // for top sky and bottom sky
 
 extern char skyname[];
 
-void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
 float  turbsin[256] =
 {
        #include "gl_warp_sin.h"
@@ -495,9 +486,8 @@ void RSurf_DrawSky(msurface_t *s, int transform)
                        {
                                for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
                                {
-                                       skyvert[currentskyvert].v[0] = v[0];
-                                       skyvert[currentskyvert].v[1] = v[1];
-                                       skyvert[currentskyvert++].v[2] = v[2];
+                                       VectorCopy(v, skyvert[currentskyvert].v);
+                                       currentskyvert++;
                                }
                        }
                }
@@ -526,8 +516,8 @@ int RSurf_Light(int *dlightbits, glpoly_t *polys)
                                        cr = light->color[0];
                                        cg = light->color[1];
                                        cb = light->color[2];
-                                       radius = light->radius*light->radius*LIGHTSCALE;
-                                       radius2 = radius * (256.0f / LIGHTSCALE2);
+                                       radius = light->radius*light->radius;
+                                       radius2 = radius * 256.0f;
                                        wv = wvert;
                                        for (p = polys;p;p = p->next)
                                        {
@@ -557,115 +547,228 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha)
        int             i;
        float   os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(cl.time * TURBSCALE + 96.0) & 255];
        glpoly_t *p;
-       float   *wv, *v;
-       wv = wvert;
-       for (p = s->polys;p;p = p->next)
+       float   *v;
+       // FIXME: make fog texture if water texture is transparent?
+
+       if (s->dlightframe != r_dlightframecount)
        {
-               for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+               vec3_t temp;
+               // LordHavoc: fast path for no vertex lighting cases
+               if (transform)
                {
-                       if (transform)
-                               softwaretransform(v, wv);
+                       if (r_waterripple.value)
+                       {
+                               for (p=s->polys ; p ; p=p->next)
+                               {
+                                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA);
+                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                                       {
+                                               softwaretransform(v, temp);
+                                               transpolyvert(temp[0], temp[1], temp[2] + r_waterripple.value * turbsin[(int)((temp[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((temp[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha);
+                                       }
+                                       transpolyend();
+                               }
+                       }
                        else
-                               VectorCopy(v, wv);
+                       {
+                               for (p=s->polys ; p ; p=p->next)
+                               {
+                                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA);
+                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                                       {
+                                               softwaretransform(v, temp);
+                                               transpolyvert(temp[0], temp[1], temp[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha);
+                                       }
+                                       transpolyend();
+                               }
+                       }
+               }
+               else
+               {
                        if (r_waterripple.value)
-                               wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
-                       wv[3] = wv[4] = wv[5] = 128.0f;
-                       wv += 6;
+                       {
+                               for (p=s->polys ; p ; p=p->next)
+                               {
+                                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA);
+                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                                               transpolyvert(v[0], v[1], v[2] + r_waterripple.value * turbsin[(int)((v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha);
+                                       transpolyend();
+                               }
+                       }
+                       else
+                       {
+                               for (p=s->polys ; p ; p=p->next)
+                               {
+                                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA);
+                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                                               transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha);
+                                       transpolyend();
+                               }
+                       }
                }
        }
-       if (s->dlightframe == r_dlightframecount)
-               RSurf_Light(s->dlightbits, s->polys);
-       wv = wvert;
-       // FIXME: make fog texture if water texture is transparent?
-       for (p=s->polys ; p ; p=p->next)
+       else
        {
-               transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, 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] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), wv[3], wv[4], wv[5], alpha);
-               transpolyend();
+               float *wv;
+               wv = wvert;
+               for (p = s->polys;p;p = p->next)
+               {
+                       for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                       {
+                               if (transform)
+                                       softwaretransform(v, wv);
+                               else
+                                       VectorCopy(v, wv);
+                               if (r_waterripple.value)
+                                       wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
+                               wv[3] = wv[4] = wv[5] = 128.0f;
+                               wv += 6;
+                       }
+               }
+               if (s->dlightframe == r_dlightframecount)
+                       RSurf_Light(s->dlightbits, s->polys);
+               wv = wvert;
+               for (p=s->polys ; p ; p=p->next)
+               {
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA);
+                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
+                               transpolyvert(wv[0], wv[1], wv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), wv[3], wv[4], wv[5], alpha);
+                       transpolyend();
+               }
        }
 }
 
 void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
 {
        int             i, lit = false, polys = 0, verts = 0;
-       float   *v, *wv;
+       float   *v;
        glpoly_t *p;
        wallpoly_t *wp;
        wallvert_t *out;
+       wallvertcolor_t *outcolor;
        // check for lightmap modification
-       if (r_dynamic.value)
+       if (s->cached_dlight
+        || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_dlightframecount)
+        || r_ambient.value != s->cached_ambient
+        || lighthalf != s->cached_lighthalf
+        || (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);
+       if (r_dlightmap.value || s->dlightframe != r_dlightframecount)
        {
-               if (s->cached_dlight
-                || (r_dlightmap.value && s->dlightframe == r_dlightframecount)
-                || r_ambient.value != s->cached_ambient
-                || lighthalf != s->cached_lighthalf
-                || (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);
-       }
-       wv = wvert;
-       for (p = s->polys;p;p = p->next)
-       {
-               for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+               // 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->texnum = (unsigned short) R_GetTexture(t->texture);
+                       wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum);
+                       wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture);
+                       wp->firstvert = currentwallvert;
+                       wp->numverts = p->numverts;
+                       wp->lit = lit;
+                       wp++;
+                       currentwallpoly++;
+                       currentwallvert += p->numverts;
+                       v = p->verts[0];
                        if (transform)
-                               softwaretransform(v, wv);
+                       {
+                               for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, out++)
+                               {
+                                       softwaretransform(v, out->vert);
+                                       out->vert[3] = v[3];
+                                       out->vert[4] = v[4];
+                                       out->vert[5] = v[5];
+                                       out->vert[6] = v[6];
+                               }
+                       }
                        else
-                               VectorCopy(v, wv);
-                       wv[3] = wv[4] = wv[5] = 0.0f;
-                       wv += 6;
+                       {
+                               /*
+                               for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, out++)
+                               {
+                                       VectorCopy(v, out->vert);
+                                       out->vert[3] = v[3];
+                                       out->vert[4] = v[4];
+                                       out->vert[5] = v[5];
+                                       out->vert[6] = v[6];
+                               }
+                               */
+                               memcpy(out, v, sizeof(vec_t) * VERTEXSIZE * p->numverts);
+                               out += p->numverts;
+                       }
                }
-               verts += p->numverts;
-               polys++;
        }
-       if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS))
-               return;
-       if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount)
-               lit = RSurf_Light(s->dlightbits, s->polys);
-       wv = wvert;
-       wp = &wallpoly[currentwallpoly];
-       out = &wallvert[currentwallvert];
-       currentwallpoly += polys;
-       for (p = s->polys;p;p = p->next)
+       else
        {
-               v = p->verts[0];
-               wp->texnum = (unsigned short) t->gl_texturenum;
-               wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum);
-               wp->glowtexnum = (unsigned short) t->gl_glowtexturenum;
-               wp->firstvert = currentwallvert;
-               wp->numverts = p->numverts;
-               wp->lit = lit;
-               wp++;
-               currentwallvert += p->numverts;
-               for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++)
+               float *wv;
+               wv = wvert;
+               for (p = s->polys;p;p = p->next)
                {
-                       if (lit)
+                       for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
                        {
-                               if (lighthalf)
-                               {
-                                       out->r = (byte) (bound(0, (int) wv[3] >> 1, 255));
-                                       out->g = (byte) (bound(0, (int) wv[4] >> 1, 255));
-                                       out->b = (byte) (bound(0, (int) wv[5] >> 1, 255));
-                                       out->a = 255;
-                               }
+                               if (transform)
+                                       softwaretransform(v, wv);
                                else
+                                       VectorCopy(v, wv);
+                               wv[3] = wv[4] = wv[5] = 0.0f;
+                               wv += 6;
+                       }
+                       verts += p->numverts;
+                       polys++;
+               }
+               if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS))
+                       return;
+               if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount)
+                       lit = RSurf_Light(s->dlightbits, s->polys);
+               wv = wvert;
+               wp = &wallpoly[currentwallpoly];
+               out = &wallvert[currentwallvert];
+               outcolor = &wallvertcolor[currentwallvert];
+               currentwallpoly += polys;
+               for (p = s->polys;p;p = p->next)
+               {
+                       v = p->verts[0];
+                       wp->texnum = (unsigned short) R_GetTexture(t->texture);
+                       wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum);
+                       wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture);
+                       wp->firstvert = currentwallvert;
+                       wp->numverts = p->numverts;
+                       wp->lit = lit;
+                       wp++;
+                       currentwallvert += p->numverts;
+                       for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++, outcolor++)
+                       {
+                               if (lit)
                                {
-                                       out->r = (byte) (bound(0, (int) wv[3], 255));
-                                       out->g = (byte) (bound(0, (int) wv[4], 255));
-                                       out->b = (byte) (bound(0, (int) wv[5], 255));
-                                       out->a = 255;
+                                       if (lighthalf)
+                                       {
+                                               outcolor->r = (byte) (bound(0, (int) wv[3] >> 1, 255));
+                                               outcolor->g = (byte) (bound(0, (int) wv[4] >> 1, 255));
+                                               outcolor->b = (byte) (bound(0, (int) wv[5] >> 1, 255));
+                                               outcolor->a = 255;
+                                       }
+                                       else
+                                       {
+                                               outcolor->r = (byte) (bound(0, (int) wv[3], 255));
+                                               outcolor->g = (byte) (bound(0, (int) wv[4], 255));
+                                               outcolor->b = (byte) (bound(0, (int) wv[5], 255));
+                                               outcolor->a = 255;
+                                       }
                                }
+                               out->vert[0] = wv[0];
+                               out->vert[1] = wv[1];
+                               out->vert[2] = wv[2];
+                               out->vert[3] = v[3];
+                               out->vert[4] = v[4];
+                               out->vert[5] = v[5];
+                               out->vert[6] = v[6];
                        }
-                       out->vert[0] = wv[0];
-                       out->vert[1] = wv[1];
-                       out->vert[2] = wv[2];
-                       out->s = v[3];
-                       out->t = v[4];
-                       out->u = v[5];
-                       out->v = v[6];
                }
        }
 }
@@ -720,7 +823,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(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->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->colormod[0], wv[4] * currententity->colormod[1], wv[5] * currententity->colormod[2], alpha);
                        transpolyend();
@@ -731,7 +834,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(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+                       transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->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();
@@ -1559,10 +1662,7 @@ void GL_BuildLightmaps (void)
        }
 
        if (!lightmap_textures)
-       {
-               lightmap_textures = texture_extension_number;
-               texture_extension_number += MAX_LIGHTMAPS;
-       }
+               lightmap_textures = R_GetTextureSlots(MAX_LIGHTMAPS);
 
        for (j=1 ; j<MAX_MODELS ; j++)
        {
index 23b7047c659673243c03a35be398730a19a09586..026861df783f77b0a203c3f973ec1252f84108fb 100644 (file)
@@ -58,7 +58,7 @@ Con_Printf ();
 net 
 turn off messages option
 
-the refresh is allways rendered, unless the console is full screen
+the refresh is always rendered, unless the console is full screen
 
 
 console is:
@@ -442,7 +442,7 @@ void SCR_DrawTurtle (void)
        if (!scr_showturtle.value)
                return;
 
-       if (host_frametime < 0.1)
+       if (cl.frametime < 0.1)
        {
                count = 0;
                return;
@@ -827,8 +827,6 @@ text to the screen.
 LordHavoc: due to my rewrite of R_WorldNode, it no longer takes 256k of stack space :)
 ==================
 */
-extern cvar_t gl_vertexarrays;
-extern qboolean gl_arrays;
 void GL_Finish();
 void SCR_UpdateScreen (void)
 {
@@ -837,9 +835,6 @@ void SCR_UpdateScreen (void)
        if (r_speeds.value)
                time1 = Sys_FloatTime ();
 
-       if (!gl_arrays)
-               gl_vertexarrays.value = 0;
-
        scr_copytop = 0;
        scr_copyeverything = 0;
 
index e7c19f38bf4fe2d9b78300382f5697622f330969..a5644a3d5c5645e85e5982aa56d50e453687376b 100644 (file)
@@ -1,9 +1,10 @@
 #include "quakedef.h"
 
-cvar_t         gl_max_size = {"gl_max_size", "2048"};
-cvar_t         gl_picmip = {"gl_picmip", "0"};
-cvar_t         gl_lerpimages = {"gl_lerpimages", "1"};
+cvar_t         r_max_size = {"r_max_size", "2048"};
+cvar_t         r_picmip = {"r_picmip", "0"};
+cvar_t         r_lerpimages = {"r_lerpimages", "1"};
 cvar_t         r_upload = {"r_upload", "1"};
+cvar_t         r_precachetextures = {"r_precachetextures", "1", true};
 
 int            gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
 int            gl_filter_max = GL_LINEAR;
@@ -14,27 +15,43 @@ int         texels;
 // 65536x65536
 #define MAXMIPS 16
 
+#define GLTEXF_LERPED 1
+#define GLTEXF_UPLOADED 2
+
 typedef struct
 {
        char    identifier[64];
-       int             texnum;
-       int             texeldatasize;
-       byte    *texels[MAXMIPS];
-       unsigned short texelsize[MAXMIPS][2];
+       int             texnum; // GL texture slot number
+       int             texeldatasize; // computed memory usage of this texture (including mipmaps, expansion to 32bit, etc)
+       byte    *inputtexels; // copy of the original texture supplied to the upload function, for re-uploading or deferred uploads (non-precached)
+       int             inputtexeldatasize; // size of the original texture
        unsigned short width, height;
 // LordHavoc: CRC to identify cache mismatchs
        unsigned short crc;
-       char    mipmap;
-       char    alpha;
-       char    bytesperpixel;
-       char    lerped; // whether this texture was uploaded with or without interpolation
-       char    inuse; // cleared during texture purge when loading new level
-       char    pad; // unused
+       int flags; // the requested flags when the texture was supplied to the upload function
+       int internalflags; // internal notes (lerped, etc)
 } gltexture_t;
 
 #define        MAX_GLTEXTURES  4096
 gltexture_t    *gltextures;
-int                    numgltextures;
+unsigned int numgltextures = 0, gl_texture_number = 1;
+
+void GL_UploadTexture(gltexture_t *t);
+
+int R_GetTexture(rtexture_t *rt)
+{
+       gltexture_t *glt;
+       if (!rt)
+               return 0;
+       glt = (gltexture_t *)rt;
+       if (!(glt->internalflags & GLTEXF_UPLOADED))
+       {
+               GL_UploadTexture(glt);
+               if (!(glt->internalflags & GLTEXF_UPLOADED))
+                       Host_Error("R_GetTexture: unable to upload texture\n");
+       }
+       return glt->texnum;
+}
 
 typedef struct
 {
@@ -42,7 +59,8 @@ typedef struct
        int     minimize, maximize;
 } glmode_t;
 
-glmode_t modes[] = {
+glmode_t modes[] =
+{
        {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
        {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
        {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
@@ -92,7 +110,7 @@ void Draw_TextureMode_f (void)
        // change all the existing mipmap texture objects
        for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
        {
-               if (glt->mipmap)
+               if (glt->flags & TEXF_MIPMAP)
                {
                        glBindTexture(GL_TEXTURE_2D, glt->texnum);
                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
@@ -101,59 +119,45 @@ void Draw_TextureMode_f (void)
        }
 }
 
-void GL_TextureStats_Print(char *name, int total, int crc, int mip, int alpha)
+void GL_TextureStats_Print(char *name, int total, int total2, int loaded, int crc, int mip, int alpha, int total2valid)
 {
-       char n[64];
-       int c = 0;
        if (!name[0])
                name = "<unnamed>";
-       while (name[c] && c < 28)
-               n[c++] = name[c];
-       // no need to pad since the name was moved to last
-//     while (c < 28)
-//             n[c++] = ' ';
-       n[c] = 0;
-       Con_Printf("%5i %04X %s %s %s\n", total, crc, mip ? "yes" : "no ", alpha ? "yes  " : "no   ", n);
+       Con_Printf("%5iK %c%5iK%c %04X %s %s %s %s\n", total, total2valid ? ' ' : '(', total2, total2valid ? ' ' : ')', crc, loaded ? "loaded" : "      ", mip ? "mip" : "   ", alpha ? "alpha" : "     ", name);
 }
 
-void GL_TextureStats_f(void)
+void GL_TextureStats_PrintTotal(void)
 {
-       int i, s = 0, sc = 0, t = 0;
+       int i, t = 0, p = 0, loaded = 0, loadedt = 0, loadedp = 0;
        gltexture_t *glt;
-       Con_Printf("kbytes crc  mip alpha name\n");
        for (i = 0, glt = gltextures;i < numgltextures;i++, glt++)
        {
-               GL_TextureStats_Print(glt->identifier, (glt->texeldatasize + 512) >> 10, glt->crc, glt->mipmap, glt->alpha);
                t += glt->texeldatasize;
-               if (glt->identifier[0] == '&')
+               p += glt->inputtexeldatasize;
+               if (glt->internalflags & GLTEXF_UPLOADED)
                {
-                       sc++;
-                       s += glt->texeldatasize;
+                       loaded++;
+                       loadedt += glt->texeldatasize;
+                       loadedp += glt->inputtexeldatasize;
                }
        }
-       Con_Printf("%i textures, totalling %.3fMB, %i are (usually) unnecessary model skins totalling %.3fMB\n", numgltextures, t / 1048576.0, sc, s / 1048576.0);
+       Con_Printf("total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", numgltextures, t / 1048576.0, p / 1048576.0, loaded, loadedt / 1048576.0, loadedp / 1048576.0, numgltextures - loaded, (t - loadedt) / 1048576.0, (p - loadedp) / 1048576.0);
 }
 
-void GL_TextureStats_PrintTotal(void)
+void GL_TextureStats_f(void)
 {
-       int i, s = 0, sc = 0, t = 0;
+       int i;
        gltexture_t *glt;
+       Con_Printf("kbytes original crc  loaded mip alpha name\n");
        for (i = 0, glt = gltextures;i < numgltextures;i++, glt++)
-       {
-               t += glt->texeldatasize;
-               if (glt->identifier[0] == '&')
-               {
-                       sc++;
-                       s += glt->texeldatasize;
-               }
-       }
-       Con_Printf("%i textures, totalling %.3fMB, %i are (usually) unnecessary model skins totalling %.3fMB\n", numgltextures, t / 1048576.0, sc, s / 1048576.0);
+               GL_TextureStats_Print(glt->identifier, (glt->texeldatasize + 1023) / 1024, (glt->inputtexeldatasize + 1023) / 1024, glt->internalflags & GLTEXF_UPLOADED, glt->crc, glt->flags & TEXF_MIPMAP, glt->flags & TEXF_ALPHA, glt->inputtexels != NULL);
+       GL_TextureStats_PrintTotal();
 }
 
 char engineversion[40];
 
 //void GL_UploadTexture (gltexture_t *glt);
-void gl_textures_start()
+void r_textures_start()
 {
 //     int i;
 //     gltexture_t *glt;
@@ -161,38 +165,39 @@ void gl_textures_start()
 //             GL_UploadTexture(glt);
 }
 
-void gl_textures_shutdown()
+void r_textures_shutdown()
 {
 }
 
-void GL_Textures_Init (void)
+void R_Textures_Init (void)
 {
        Cmd_AddCommand("r_texturestats", GL_TextureStats_f);
-       Cvar_RegisterVariable (&gl_max_size);
-       Cvar_RegisterVariable (&gl_picmip);
-       Cvar_RegisterVariable (&gl_lerpimages);
+       Cvar_RegisterVariable (&r_max_size);
+       Cvar_RegisterVariable (&r_picmip);
+       Cvar_RegisterVariable (&r_lerpimages);
        Cvar_RegisterVariable (&r_upload);
+       Cvar_RegisterVariable (&r_precachetextures);
 #ifdef NORENDER
        r_upload.value = 0;
 #endif
 
        // 3dfx can only handle 256 wide textures
        if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide"))
-               Cvar_Set ("gl_max_size", "256");
+               Cvar_Set ("r_max_size", "256");
 
        gltextures = qmalloc(sizeof(gltexture_t) * MAX_GLTEXTURES);
        memset(gltextures, 0, sizeof(gltexture_t) * MAX_GLTEXTURES);
        Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
 
-       R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
+       R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown);
 }
 
 /*
 ================
-GL_FindTexture
+R_FindTexture
 ================
 */
-int GL_FindTexture (char *identifier)
+int R_FindTexture (char *identifier)
 {
        int             i;
        gltexture_t     *glt;
@@ -206,7 +211,7 @@ int GL_FindTexture (char *identifier)
        return -1;
 }
 
-void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
+void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
 {
        int             j, xi, oldx = 0, f, fstep, l1, l2, endx;
        fstep = (int) (inwidth*65536.0f/outwidth);
@@ -240,12 +245,12 @@ void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
 
 /*
 ================
-GL_ResampleTexture
+R_ResampleTexture
 ================
 */
-void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight)
+void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight)
 {
-       if (gl_lerpimages.value)
+       if (r_lerpimages.value)
        {
                int             i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
                byte    *inrow, *out, *row1, *row2;
@@ -256,8 +261,8 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,
                row2 = qmalloc(outwidth*4);
                inrow = indata;
                oldy = 0;
-               GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
-               GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+               R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+               R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
                for (i = 0, f = 0;i < outheight;i++,f += fstep)
                {
                        yi = f >> 16;
@@ -267,9 +272,9 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,
                                if (yi == oldy+1)
                                        memcpy(row1, row2, outwidth*4);
                                else
-                                       GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+                                       R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
                                if (yi < endy)
-                                       GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+                                       R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
                                else
                                        memcpy(row2, row1, outwidth*4);
                                oldy = yi;
@@ -326,61 +331,6 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,
        }
 }
 
-void GL_FreeTexels(gltexture_t *glt)
-{
-       if (glt->texels[0])
-               qfree(glt->texels[0]);
-       glt->texels[0] = 0;
-}
-
-void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped)
-{
-       int i, w, h, size;
-       if (glt->texels[0])
-               GL_FreeTexels(glt);
-       glt->texelsize[0][0] = width;
-       glt->texelsize[0][1] = height;
-       if (mipmapped)
-       {
-               size = 0;
-               w = width;h = height;
-               i = 0;
-               while (i < MAXMIPS)
-               {
-                       glt->texelsize[i][0] = w;
-                       glt->texelsize[i][1] = h;
-                       glt->texels[i++] = (void *)size;
-                       size += w*h*4;
-                       if (w > 1)
-                       {
-                               w >>= 1;
-                               if (h > 1)
-                                       h >>= 1;
-                       }
-                       else if (h > 1)
-                               h >>= 1;
-                       else
-                               break;
-               }
-               glt->texeldatasize = size;
-               while (i < MAXMIPS)
-                       glt->texels[i++] = NULL;
-               glt->texels[0] = qmalloc(size);
-               for (i = 1;i < MAXMIPS && glt->texels[i];i++)
-                       glt->texels[i] += (int) glt->texels[0];
-       }
-       else
-       {
-               size = width*height*4;
-               glt->texeldatasize = size;
-               glt->texels[0] = qmalloc(size);
-               for (i = 1;i < MAXMIPS;i++)
-                       glt->texels[i] = NULL;
-       }
-       if (!glt->texels[0])
-               Sys_Error("GL_AllocTexels: out of memory\n");
-}
-
 // in can be the same as out
 void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
 {
@@ -451,18 +401,68 @@ void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int
        }
 }
 
-void GL_UploadTexture (gltexture_t *glt)
+void GL_Upload32(int glslot, byte *data, int width, int height, int flags)
 {
-       int mip, width, height;
+       int mip, width2, height2, width3, height3, internalformat;
+       byte *gammadata, *buffer;
+
        if (!r_upload.value)
                return;
-       glBindTexture(GL_TEXTURE_2D, glt->texnum);
-       width = glt->width;
-       height = glt->height;
-       for (mip = 0;mip < MAXMIPS && glt->texels[mip];mip++)
-               glTexImage2D(GL_TEXTURE_2D, mip, glt->alpha ? 4 : 3, glt->texelsize[mip][0], glt->texelsize[mip][1], 0, GL_RGBA, GL_UNSIGNED_BYTE, glt->texels[mip]);
-       if (glt->mipmap)
+
+       // 3 and 4 are converted by the driver to it's preferred format for the current display mode
+       internalformat = 3;
+       if (flags & TEXF_ALPHA)
+               internalformat = 4;
+
+       // calculate power of 2 size
+       width2 = 1;while (width2 < width) width2 <<= 1;
+       height2 = 1;while (height2 < height) height2 <<= 1;
+       // calculate final size (mipmapped downward to this)
+       width3 = width2 >> (int) r_picmip.value;
+       height3 = height2 >> (int) r_picmip.value;
+       while (width3 > (int) r_max_size.value) width3 >>= 1;
+       while (height3 > (int) r_max_size.value) height3 >>= 1;
+       if (width3 < 1) width3 = 1;
+       if (height3 < 1) height3 = 1;
+
+       gammadata = qmalloc(width*height*4);
+       buffer = qmalloc(width2*height2*4);
+       if (!gammadata || !buffer)
+               Host_Error("GL_Upload32: out of memory\n");
+
+       Image_CopyRGBAGamma(data, gammadata, width*height);
+
+       R_ResampleTexture(gammadata, width, height, buffer, width2, height2);
+
+       qfree(gammadata);
+
+       while (width2 > width3 || height2 > height3)
        {
+               GL_MipReduce(buffer, buffer, width2, height2, width3, height3);
+
+               if (width2 > width3)
+                       width2 >>= 1;
+               if (height2 > height3)
+                       height2 >>= 1;
+       }
+
+       glBindTexture(GL_TEXTURE_2D, glslot);
+       mip = 0;
+       glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+       if (flags & TEXF_MIPMAP)
+       {
+               while (width2 > 1 || height2 > 1)
+               {
+                       GL_MipReduce(buffer, buffer, width2, height2, 1, 1);
+
+                       if (width2 > 1)
+                               width2 >>= 1;
+                       if (height2 > 1)
+                               height2 >>= 1;
+
+                       glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+               }
+
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
        }
@@ -472,6 +472,64 @@ void GL_UploadTexture (gltexture_t *glt)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
        }
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+       qfree(buffer);
+}
+
+void GL_Upload8 (int glslot, byte *data, int width, int height, int flags)
+{
+       byte *data32;
+       data32 = qmalloc(width*height*4);
+       Image_Copy8bitRGBA(data, data32, width*height, d_8to24table);
+       GL_Upload32(glslot, data32, width, height, flags);
+       qfree(data32);
+}
+
+void GL_UploadTexture (gltexture_t *glt)
+{
+       if (glt->inputtexels == NULL)
+               return;
+       if (glt->flags & TEXF_RGBA)
+               GL_Upload32(glt->texnum, glt->inputtexels, glt->width, glt->height, glt->flags);
+       else // 8bit
+               GL_Upload8(glt->texnum, glt->inputtexels, glt->width, glt->height, glt->flags);
+       glt->internalflags |= GLTEXF_UPLOADED;
+       qfree(glt->inputtexels);
+       glt->inputtexels = NULL;
+}
+
+int R_CalcTexelDataSize (int width, int height, int mipmapped)
+{
+       int width2, height2, size;
+       width2 = 1;while (width2 < width) width2 <<= 1;
+       height2 = 1;while (height2 < height) height2 <<= 1;
+       // calculate final size (mipmapped downward to this)
+       width2 >>= (int) r_picmip.value;
+       height2 >>= (int) r_picmip.value;
+       while (width2 > (int) r_max_size.value) width2 >>= 1;
+       while (height2 > (int) r_max_size.value) height2 >>= 1;
+       if (width2 < 1) width2 = 1;
+       if (height2 < 1) height2 = 1;
+
+       size = 0;
+       if (mipmapped)
+       {
+               while (width2 > 1 || height2 > 1)
+               {
+                       size += width2 * height2;
+                       if (width2 > 1)
+                               width2 >>= 1;
+                       if (height2 > 1)
+                               height2 >>= 1;
+               }
+               size++; // count the last 1x1 mipmap
+       }
+       else
+               size = width2*height2;
+
+       size *= 4; // RGBA
+
+       return size;
 }
 
 /*
@@ -479,49 +537,77 @@ void GL_UploadTexture (gltexture_t *glt)
 GL_LoadTexture
 ================
 */
-int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
+rtexture_t *R_LoadTexture (char *identifier, int width, int height, byte *data, int flags)
 {
+       int                             i, bytesperpixel, internalflags, precache;
+       gltexture_t             *glt;
        unsigned short  crc;
-       int                             i, width2, height2, width3, height3, w, h, mip;
-       gltexture_t             *glt, *freeglt;
-       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
-       //char                  cachefilename[1024], *cachefile;
 
        if (isDedicated)
-               return 1;
+               return NULL;
 
-       freeglt = NULL;
+       if (!identifier[0])
+               Host_Error("R_LoadTexture: no identifier\n");
 
-       // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
-       crc = CRC_Block(data, width*height*bytesperpixel);
-       // see if the texture is already present
-       if (identifier[0])
+       // clear the alpha flag if the texture has no transparent pixels
+       if (flags & TEXF_ALPHA)
        {
-               for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+               int alpha = false;
+               if (flags & TEXF_RGBA)
                {
-                       if (glt->inuse)
+                       for (i = 0;i < width * height;i++)
                        {
-                               if (!strcmp (identifier, glt->identifier))
+                               if (data[i * 4 + 3] < 255)
                                {
-                                       // LordHavoc: everyone hates cache mismatchs, so I fixed it
-                                       if (crc != glt->crc || width != glt->width || height != glt->height)
-                                       {
-                                               Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
-                                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
-                                       }
-                                       if ((gl_lerpimages.value != 0) != glt->lerped)
-                                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
-                                       return glt->texnum;
+                                       alpha = true;
+                                       break;
                                }
                        }
-                       else
-                               freeglt = glt;
                }
+               else
+               {
+                       for (i = 0;i < width * height;i++)
+                       {
+                               if (data[i] == 255)
+                               {
+                                       alpha = true;
+                                       break;
+                               }
+                       }
+               }
+               if (!alpha)
+                       flags &= ~TEXF_ALPHA;
        }
+
+       if (flags & TEXF_RGBA)
+               bytesperpixel = 4;
        else
-               i = 0;
-       // LordHavoc: although this could be an else condition as it was in the original id code,
-       //            it is more clear this way
+               bytesperpixel = 1;
+
+       internalflags = 0;
+       if (r_lerpimages.value != 0)
+               internalflags |= GLTEXF_LERPED;
+
+       // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
+       crc = CRC_Block(data, width*height*bytesperpixel);
+       // see if the texture is already present
+       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+       {
+               if (!strcmp (identifier, glt->identifier))
+               {
+                       // LordHavoc: everyone hates cache mismatchs, so I fixed it
+                       if (crc != glt->crc || width != glt->width || height != glt->height || flags != glt->flags)
+                       {
+                               Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
+                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                       }
+                       if (internalflags != glt->internalflags)
+                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                       return (rtexture_t *)glt;
+               }
+       }
+
+/*
        if (freeglt)
        {
                glt = freeglt;
@@ -529,152 +615,52 @@ int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolea
        }
        else
        {
+*/
                // LordHavoc: check if there are still slots available
                if (numgltextures >= MAX_GLTEXTURES)
                        Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
                glt = &gltextures[numgltextures++];
-               glt->texnum = texture_extension_number;
-               texture_extension_number++;
+               glt->texnum = gl_texture_number++;
                strcpy (glt->identifier, identifier);
-       }
+//     }
 
 // LordHavoc: label to drop out of the loop into the setup code
 GL_LoadTexture_setup:
-       // calculate power of 2 size
-       width2 = 1;while (width2 < width) width2 <<= 1;
-       height2 = 1;while (height2 < height) height2 <<= 1;
-       // calculate final size (mipmapped downward to this)
-       width3 = width2 >> (int) gl_picmip.value;
-       height3 = height2 >> (int) gl_picmip.value;
-       while (width3 > (int) gl_max_size.value) width3 >>= 1;
-       while (height3 > (int) gl_max_size.value) height3 >>= 1;
-       if (width3 < 1) width3 = 1;
-       if (height3 < 1) height3 = 1;
-
-       // final storage
-       GL_AllocTexels(glt, width3, height3, mipmap);
        glt->crc = crc; // LordHavoc: used to verify textures are identical
        glt->width = width;
        glt->height = height;
-       glt->mipmap = mipmap;
-       glt->bytesperpixel = bytesperpixel;
-       glt->lerped = gl_lerpimages.value != 0;
-       glt->alpha = false; // updated later
-       glt->inuse = true;
-       /*
-       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
-       sprintf(cachefilename, "%s%x%x%x.texels", identifier, width3, height3, crc);
-       for (i = 0;cachefilename[i];i++)
-       {
-               if (cachefilename[i] <= ' ' || cachefilename[i] >= 127 || cachefilename[i] == '/' || cachefilename[i] == '\\' || cachefilename[i] == ':' || cachefilename[i] == '*' || cachefilename[i] == '?')
-                       cachefilename[i] = '@';
-               if (cachefilename[i] >= 'A' && cachefilename[i] <= 'Z')
-                       cachefilename[i] += 'a' - 'A';
-       }
-       cachefile = COM_LoadMallocFile(cachefilename, true);
-       if (cachefile)
-       {
-               if (cachefile[0] == 'D' && cachefile[1] == 'P' && cachefile[2] == 'C' && cachefile[3] == 'T')
-               {
-                       memcpy(glt->texels[0], cachefile + 4, width3*height3*4);
-                       qfree(cachefile);
-//                     Con_Printf("loaded cache texture %s\n", cachefilename);
-                       goto cacheloaded;
-               }
-               else
-                       qfree(cachefile);
-       }
-       */
-       if (width == width3 && height == height3) // perfect match
-       {
-               if (bytesperpixel == 1) // 8bit
-                       Image_Copy8bitRGBA(data, glt->texels[0], width*height, d_8to24table);
-               else
-                       Image_CopyRGBAGamma(data, glt->texels[0], width*height);
-       }
-       else if (width == width2 && height == height2) // perfect match for top level, but needs to be reduced
-       {
-               byte *temptexels2;
-               temptexels2 = qmalloc(width2*height2*4); // scaleup buffer
-               if (bytesperpixel == 1) // 8bit
-                       Image_Copy8bitRGBA(data, temptexels2, width*height, d_8to24table);
-               else
-                       Image_CopyRGBAGamma(data, temptexels2, width*height);
-               while (width2 > width3 || height2 > height3)
-               {
-                       w = width2;h = height2;
-                       if (width2 > width3) width2 >>= 1;
-                       if (height2 > height3) height2 >>= 1;
-                       if (width2 <= width3 && height2 <= height3) // size achieved
-                               GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
-                       else
-                               GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
-               }
-               qfree(temptexels2);
-       }
-       else // scaling...
-       {
-               byte *temptexels;
-               // pre-scaleup buffer
-               temptexels = qmalloc(width*height*4);
-               if (bytesperpixel == 1) // 8bit
-                       Image_Copy8bitRGBA(data, temptexels, width*height, d_8to24table);
-               else
-                       Image_CopyRGBAGamma(data, temptexels, width*height);
-               if (width2 != width3 || height2 != height3) // reduced by gl_pic_mip or gl_max_size
-               {
-                       byte *temptexels2;
-                       temptexels2 = qmalloc(width2*height2*4); // scaleup buffer
-                       GL_ResampleTexture(temptexels, width, height, temptexels2, width2, height2);
-                       while (width2 > width3 || height2 > height3)
-                       {
-                               w = width2;h = height2;
-                               if (width2 > width3) width2 >>= 1;
-                               if (height2 > height3) height2 >>= 1;
-                               if (width2 <= width3 && height2 <= height3) // size achieved
-                                       GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
-                               else
-                                       GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
-                       }
-                       qfree(temptexels2);
-               }
-               else // copy directly
-                       GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
-               qfree(temptexels);
-       }
-       /*
-       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
-       Con_Printf("writing cache texture %s\n", cachefilename);
-       cachefile = qmalloc(width3*height3*4 + 4);
-       cachefile[0] = 'D';
-       cachefile[1] = 'P';
-       cachefile[2] = 'C';
-       cachefile[3] = 'T';
-       memcpy(cachefile + 4, glt->texels[0], width3*height3*4);
-       COM_WriteFile(cachefilename, cachefile, width3*height3*4 + 4);
-       qfree(cachefile);
-cacheloaded:
-       */
-       if (alpha)
+       glt->flags = flags;
+       glt->internalflags = internalflags;
+
+       if (glt->inputtexels)
+               qfree(glt->inputtexels);
+       glt->inputtexeldatasize = width*height*bytesperpixel;
+       glt->inputtexels = qmalloc(glt->inputtexeldatasize);
+
+       memcpy(glt->inputtexels, data, glt->inputtexeldatasize);
+
+       glt->texeldatasize = R_CalcTexelDataSize(width, height, flags & TEXF_MIPMAP);
+
+       precache = false;
+       if (r_precachetextures.value >= 1)
        {
-               byte    *in = glt->texels[0] + 3;
-               for (i = 0;i < width*height;i++, in += 4)
-                       if (*in < 255)
-                       {
-                               glt->alpha = true;
-                               break;
-                       }
+               if (flags & TEXF_PRECACHE)
+                       precache = true;
+               if (r_precachetextures.value >= 2)
+                       precache = true;
        }
-       // this loop is skipped if there are no mipmaps to generate
-       for (mip = 1;mip < MAXMIPS && glt->texels[mip];mip++)
-               GL_MipReduce(glt->texels[mip-1], glt->texels[mip], glt->texelsize[mip-1][0], glt->texelsize[mip-1][1], 1, 1);
-       GL_UploadTexture(glt);
-       GL_FreeTexels(glt);
 
-//     if (bytesperpixel == 1) // 8bit
-//             GL_Upload8 (data, width, height, mipmap, alpha);
-//     else // 32bit
-//             GL_Upload32 (data, width, height, mipmap, true);
+       if (precache)
+               GL_UploadTexture(glt);
 
-       return glt->texnum;
+       return (rtexture_t *)glt;
+}
+
+// only used for lightmaps
+int R_GetTextureSlots(int count)
+{
+       int i;
+       i = gl_texture_number;
+       gl_texture_number += count;
+       return i;
 }
index 5b37779c65f60a020fafcc3bac95f7af26213a7d..c3ccd0d20a24931cb948df1a79c898ab924b673d 100644 (file)
--- a/gl_warp.c
+++ b/gl_warp.c
@@ -25,8 +25,8 @@ extern        model_t *loadmodel;
 
 int            skytexturenum;
 
-int            solidskytexture;
-int            alphaskytexture;
+rtexture_t *solidskytexture;
+rtexture_t *alphaskytexture;
 float  speedscale;             // for top sky and bottom sky
 
 msurface_t     *warpface;
@@ -176,7 +176,7 @@ void GL_SubdivideSurface (msurface_t *fa)
 
 
 
-int skyboxside[6];
+rtexture_t *skyboxside[6];
 
 char skyname[256];
 
@@ -211,7 +211,7 @@ void R_LoadSkyBox (void)
                                continue;
                        }
                }
-               skyboxside[i] = GL_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, false, false, 4);
+               skyboxside[i] = R_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, TEXF_RGBA | TEXF_PRECACHE);
                qfree(image_rgba);
        }
 }
@@ -257,42 +257,42 @@ void R_SkyBox()
                glColor3f(0.5,0.5,0.5);
        else
                glColor3f(1,1,1);
-       glBindTexture(GL_TEXTURE_2D, skyboxside[3]); // front
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[3])); // front
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0,  1, -1,  1);
        R_SkyBoxPolyVec(1, 1,  1, -1, -1);
        R_SkyBoxPolyVec(0, 1,  1,  1, -1);
        R_SkyBoxPolyVec(0, 0,  1,  1,  1);
        glEnd();
-       glBindTexture(GL_TEXTURE_2D, skyboxside[1]); // back
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[1])); // back
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0, -1,  1,  1);
        R_SkyBoxPolyVec(1, 1, -1,  1, -1);
        R_SkyBoxPolyVec(0, 1, -1, -1, -1);
        R_SkyBoxPolyVec(0, 0, -1, -1,  1);
        glEnd();
-       glBindTexture(GL_TEXTURE_2D, skyboxside[0]); // right
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[0])); // right
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0,  1,  1,  1);
        R_SkyBoxPolyVec(1, 1,  1,  1, -1);
        R_SkyBoxPolyVec(0, 1, -1,  1, -1);
        R_SkyBoxPolyVec(0, 0, -1,  1,  1);
        glEnd();
-       glBindTexture(GL_TEXTURE_2D, skyboxside[2]); // left
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[2])); // left
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0, -1, -1,  1);
        R_SkyBoxPolyVec(1, 1, -1, -1, -1);
        R_SkyBoxPolyVec(0, 1,  1, -1, -1);
        R_SkyBoxPolyVec(0, 0,  1, -1,  1);
        glEnd();
-       glBindTexture(GL_TEXTURE_2D, skyboxside[4]); // up
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[4])); // up
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0,  1, -1,  1);
        R_SkyBoxPolyVec(1, 1,  1,  1,  1);
        R_SkyBoxPolyVec(0, 1, -1,  1,  1);
        R_SkyBoxPolyVec(0, 0, -1, -1,  1);
        glEnd();
-       glBindTexture(GL_TEXTURE_2D, skyboxside[5]); // down
+       glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[5])); // down
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0,  1,  1, -1);
        R_SkyBoxPolyVec(1, 1,  1, -1, -1);
@@ -331,7 +331,6 @@ void skydomecalc(float *dome, float dx, float dy, float dz)
        }
 }
 
-extern cvar_t gl_vertexarrays;
 void skydome(float *source, float s, float texscale)
 {
        vec_t vert[33*33][3], tex[33*33][2], *v, *t;
@@ -346,33 +345,15 @@ void skydome(float *source, float s, float texscale)
                *v++ = *source++ + r_refdef.vieworg[1];
                *v++ = *source++ + r_refdef.vieworg[2];
        }
-       if (gl_vertexarrays.value)
-       {
-               qglTexCoordPointer(2, GL_FLOAT, 0, tex);
-               qglVertexPointer(3, GL_FLOAT, 0, vert);
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-               glEnableClientState(GL_VERTEX_ARRAY);
-//             qglInterleavedArrays(GL_T2F_V3F, 0, vert);
-               for (i = 0;i < (32*66);i+=66)
-                       qglDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &skydomeindices[i]);
-               glDisableClientState(GL_VERTEX_ARRAY);
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-       }
-       else
-       {
-               index = skydomeindices;
-               for (i = 0;i < (32*66);i+=66)
-               {
-                       glBegin(GL_TRIANGLE_STRIP);
-                       for (j = 0;j < 66;j++)
-                       {
-                               // Matrox G200 (and possibly G400) drivers don't support TexCoord2fv...
-                               glTexCoord2f(tex[*index][0], tex[*index][1]);
-                               glVertex3fv(&vert[*index++][0]);
-                       }
-                       glEnd();
-               }
-       }
+       glTexCoordPointer(2, GL_FLOAT, 0, tex);
+       glVertexPointer(3, GL_FLOAT, 0, vert);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+       glEnableClientState(GL_VERTEX_ARRAY);
+//     glInterleavedArrays(GL_T2F_V3F, 0, vert);
+       for (i = 0;i < (32*66);i+=66)
+               glDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &skydomeindices[i]);
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 }
 
 void R_SkyDome()
@@ -465,7 +446,7 @@ void R_InitSky (byte *src, int bytesperpixel)
                ((byte *)&transpix)[3] = 0;
        }
 
-       solidskytexture = GL_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, false, false, 4);
+       solidskytexture = R_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, TEXF_RGBA | TEXF_PRECACHE);
 
        if (bytesperpixel == 4)
        {
@@ -486,6 +467,6 @@ void R_InitSky (byte *src, int bytesperpixel)
                        }
        }
 
-       alphaskytexture = GL_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, false, true, 4);
+       alphaskytexture = R_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
index b6d2d32b103346404e4f40689f444b034c210e08..c9e0e039906f944f4de6f7fcd0524bbe62a8a902 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -37,18 +37,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <GL/gl.h>
 //#include <GL/glu.h>
 
+extern qboolean isG200;
+extern qboolean isRagePro;
+extern qboolean gl_mtexable;
+extern qboolean gl_supportslockarrays;
+
 extern void GL_BeginRendering (int *x, int *y, int *width, int *height);
 extern void GL_EndRendering (void);
 
-extern int texture_extension_number;
-
 extern float   gldepthmin, gldepthmax;
 
-extern void GL_Upload32 (void *data, int width, int height,  qboolean mipmap, qboolean alpha);
-extern void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
-extern int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel);
-extern int GL_FindTexture (char *identifier);
-
 typedef struct
 {
        float   x, y, z;
@@ -109,14 +107,11 @@ extern    cvar_t  r_drawentities;
 extern cvar_t  r_drawviewmodel;
 extern cvar_t  r_speeds;
 extern cvar_t  r_fullbright;
-extern cvar_t  r_shadows;
 extern cvar_t  r_wateralpha;
 extern cvar_t  r_dynamic;
 extern cvar_t  r_novis;
 extern cvar_t  r_waterripple;
 
-extern cvar_t  gl_max_size;
-
 extern float   r_world_matrix[16];
 
 extern const char *gl_vendor;
@@ -132,8 +127,6 @@ extern      const char *gl_extensions;
 #define APIENTRY /* */
 #endif
 
-extern qboolean gl_mtexable;
-
 // LordHavoc: ARB multitexure support
 extern int             gl_mtex_enum;
 
@@ -142,13 +135,15 @@ extern int                gl_mtex_enum;
 #define GLAPIENTRY APIENTRY
 #endif
 
-// Micro$oft dropped GL support beyond 1.1, so...
-#ifdef WIN32
+// multitexture
+extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
+extern void (GLAPIENTRY *qglSelectTexture) (GLenum);
+extern void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count);
+extern void (GLAPIENTRY *qglUnlockArraysEXT) (void);
 
-//#define GL_POLYGON_OFFSET_POINT                      0x2A01
-//#define GL_POLYGON_OFFSET_LINE                       0x2A02
-//#define GL_POLYGON_OFFSET_FILL                       0x8037
 
+#ifndef GL_ACTIVE_TEXTURE_ARB
+// multitexture
 #define GL_ACTIVE_TEXTURE_ARB                  0x84E0
 #define GL_CLIENT_ACTIVE_TEXTURE_ARB   0x84E1
 #define GL_MAX_TEXTURES_UNITS_ARB              0x84E2
@@ -157,39 +152,10 @@ extern int                gl_mtex_enum;
 #define GL_TEXTURE2_ARB                                        0x84C2
 #define GL_TEXTURE3_ARB                                        0x84C3
 // LordHavoc: ARB supports 32+ texture units, but hey I only use 2 anyway...
+#endif
 
-// LordHavoc: vertex array defines
-#define GL_VERTEX_ARRAY                                        0x8074
-#define GL_NORMAL_ARRAY                                        0x8075
-#define GL_COLOR_ARRAY                                 0x8076
-#define GL_TEXTURE_COORD_ARRAY                 0x8078
-
-//extern void (GLAPIENTRY *qglPolygonOffset)(GLfloat factor, GLfloat units);
-extern void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-//extern void (GLAPIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr);
-extern void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-extern void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-extern void (GLAPIENTRY *qglArrayElement)(GLint i);
-//extern void (GLAPIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count);
-extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-
-extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-extern void (GLAPIENTRY *qglSelectTexture) (GLenum);
-//extern void (GLAPIENTRY *glColorTableEXT)(int, int, int, int, int, const void*);
-
+#ifdef WIN32
 #else
-
-//#define qglPolygonOffset glPolygonOffset
-#define qglVertexPointer glVertexPointer
-//#define qglNormalPointer glNormalPointer
-#define qglColorPointer glColorPointer
-#define qglTexCoordPointer glTexCoordPointer
-#define qglArrayElement glArrayElement
-//#define qglDrawArrays glDrawArrays
-#define qglDrawElements glDrawElements
-
-extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-extern void (GLAPIENTRY *qglSelectTexture) (GLenum);
 //#ifndef MESA
 //extern void (GLAPIENTRY *glColorTableEXT)(int, int, int, int, int, const void*);
 //#endif
@@ -220,10 +186,14 @@ extern vec_t fogdensity;
 
 #include "r_modules.h"
 
-extern cvar_t gl_vertexarrays;
 extern qboolean lighthalf;
 
-extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap);
+#include "r_lerpanim.h"
+
+void GL_LockArray(int first, int count);
+void GL_UnlockArray();
+
+void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap);
 
 extern cvar_t r_render;
 extern cvar_t r_upload;
diff --git a/host.c b/host.c
index e179da68ed45d6084b5ca7d84a29e918f18064c7..3d687b6d0a224a91d335e7e4e07217c2af33d126 100644 (file)
--- a/host.c
+++ b/host.c
@@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /*
 
-A server can allways be started, even if the system started out as a client
+A server can always be started, even if the system started out as a client
 to a remote system.
 
 A client can NOT be started if the system started as a dedicated server.
@@ -35,6 +35,7 @@ Memory is cleared / released when a server or client begins, not when they end.
 quakeparms_t host_parms;
 
 qboolean       host_initialized;               // true if into command execution
+qboolean       hostloopactive = 0;             // LordHavoc: used to turn Host_Error into Sys_Error if Host_Frame has not yet run
 
 double         host_frametime;
 double         host_realframetime;             // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling)
@@ -118,15 +119,26 @@ Host_Error
 This shuts down both the client and server
 ================
 */
-char           hosterrorstring[1024];
+char hosterrorstring[4096];
+extern qboolean hostloopactive;
 void Host_Error (char *error, ...)
 {
        va_list         argptr;
        static  qboolean inerror = false;
-       
+
+       // LordHavoc: if host_frame loop has not been run yet, do a Sys_Error instead
+       if (!hostloopactive)
+       {
+               char string[4096];
+               va_start (argptr,error);
+               vsprintf (string,error,argptr);
+               va_end (argptr);
+               Sys_Error ("%s", string);
+       }
+
        if (inerror)
        {
-               char string[1024];
+               char string[4096];
                va_start (argptr,error);
                vsprintf (string,error,argptr);
                va_end (argptr);
@@ -538,6 +550,7 @@ qboolean Host_FilterTime (float time)
        }
 
        host_frametime *= slowmo.value;
+       cl.frametime = host_frametime;
        
        return true;
 }
@@ -570,16 +583,17 @@ Host_ServerFrame
 
 ==================
 */
-double frametimetotal = 0, lastservertime = 0;
 void Host_ServerFrame (void)
 {
+       static double frametimetotal = 0, lastservertime = 0;
        frametimetotal += host_frametime;
        // LordHavoc: cap server at sys_ticrate in listen games
        if (!isDedicated && svs.maxclients > 1 && ((realtime - lastservertime) < sys_ticrate.value))
                return;
 // run the world state
-       sv_frametime = pr_global_struct->frametime = frametimetotal;
+       sv.frametime = pr_global_struct->frametime = frametimetotal;
        frametimetotal = 0;
+       lastservertime = realtime;
 //     pr_global_struct->frametime = host_frametime;
 
 // set the time and clear the general datagram
@@ -617,6 +631,7 @@ void _Host_Frame (float time)
 
        if (setjmp (host_abortserver) )
                return;                 // something bad happened, or the server disconnected
+       hostloopactive = 1;
 
 // keep the random time dependent
        rand ();
@@ -667,9 +682,7 @@ void _Host_Frame (float time)
 
 // fetch results from server
        if (cls.state == ca_connected)
-       {
                CL_ReadFromServer ();
-       }
 
 // update video
        if (host_speeds.value)
@@ -693,11 +706,11 @@ void _Host_Frame (float time)
 
        if (host_speeds.value)
        {
-               pass1 = (time1 - time3)*1000;
+               pass1 = (time1 - time3)*1000000;
                time3 = Sys_FloatTime ();
-               pass2 = (time2 - time1)*1000;
-               pass3 = (time3 - time2)*1000;
-               Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
+               pass2 = (time2 - time1)*1000000;
+               pass3 = (time3 - time2)*1000000;
+               Con_Printf ("%6ius total %6ius server %6ius gfx %6ius snd\n",
                                        pass1+pass2+pass3, pass1, pass2, pass3);
        }
        
index 4783279deb7cab63c3dc2fc58ad19aff5b0707e8..f9f3225681ec4db763e4e19ec9132bd3b2c931b6 100644 (file)
@@ -923,7 +923,7 @@ void Host_Kill_f (void)
 
        if (sv_player->v.health <= 0)
        {
-               SV_ClientPrintf ("Can't suicide -- allready dead!\n");
+               SV_ClientPrintf ("Can't suicide -- already dead!\n");
                return;
        }
        
@@ -985,7 +985,7 @@ void Host_PreSpawn_f (void)
 
        if (host_client->spawned)
        {
-               Con_Printf ("prespawn not valid -- allready spawned\n");
+               Con_Printf ("prespawn not valid -- already spawned\n");
                return;
        }
        
@@ -1016,7 +1016,7 @@ void Host_Spawn_f (void)
 
        if (host_client->spawned)
        {
-               Con_Printf ("Spawn not valid -- allready spawned\n");
+               Con_Printf ("Spawn not valid -- already spawned\n");
                return;
        }
 
@@ -1026,7 +1026,7 @@ void Host_Spawn_f (void)
 
 // run the entrance script
        if (sv.loadgame)
-       {       // loaded games are fully inited allready
+       {       // loaded games are fully inited already
                // if this is the last client to be connected, unpause
                sv.paused = false;
 
@@ -1469,59 +1469,12 @@ void Host_Viewframe_f (void)
 
 void PrintFrameName (model_t *m, int frame)
 {
-       if (m->type != mod_alias)
-               return;
-       switch(m->aliastype)
-       {
-       case ALIASTYPE_MDL:
-               {
-                       maliashdr_t *mheader;
-                       maliasframe_t *frameinfo;
-
-                       mheader = (maliashdr_t *)Mod_Extradata (m);
-                       if (!mheader)
-                               return;
-                       if (frame < 0 || frame >= mheader->numframes)
-                               frame = 0;
-                       frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame];
-                       
-                       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
-               }
-               break;
-       case ALIASTYPE_MD2:
-               {
-                       md2mem_t *mheader;
-                       md2memframe_t *frameinfo;
-
-                       mheader = (md2mem_t *)Mod_Extradata (m);
-                       if (!mheader)
-                               return;
-                       if (frame < 0 || frame >= mheader->num_frames)
-                               frame = 0;
-                       frameinfo = (md2memframe_t *)(mheader->ofs_frames + (int) mheader) + frame;
-                       
-                       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
-               }
-               break;
-       case ALIASTYPE_ZYM:
-               {
-                       zymtype1header_t *mheader;
-                       zymscene_t *scene;
-
-                       mheader = (zymtype1header_t *)Mod_Extradata (m);
-                       if (!mheader)
-                               return;
-                       if (frame < 0 || frame >= mheader->numscenes)
-                               frame = 0;
-                       scene = (zymscene_t *)(mheader->lump_scenes.start + (int) mheader) + frame;
-                       
-                       Con_Printf ("frame %i: %s\n", frame, scene->name);
-               }
-               break;
-       default:
-               Con_Printf("frame %i: (unknown alias model type)\n", frame);
-               break;
-       }
+       int data;
+       data = (int) Mod_Extradata(m);
+       if (m->ofs_scenes && data)
+               Con_Printf("frame %i: %s\n", frame, ((animscene_t *) (m->ofs_scenes + data))[frame].name);
+       else
+               Con_Printf("frame %i\n", frame);
 }
 
 /*
diff --git a/image.c b/image.c
index 622ff52687276523088be08e3863975d7480a6e1..7b05a23fc75460c1005d0d1a92f4ee916361fbe0 100644 (file)
--- a/image.c
+++ b/image.c
@@ -490,48 +490,49 @@ byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, in
        }
 }
 
-int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
+rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
 {
-       int texnum;
        byte *data;
+       rtexture_t *rt;
        if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
                return 0;
-       texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
+       rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
        qfree(data);
-       return texnum;
+       return rt;
 }
 
-int loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
+rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
 {
-       int texnum;
        byte *data;
+       rtexture_t *rt;
        if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight)))
                return 0;
-       texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
+       rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
        qfree(data);
-       return texnum;
+       return rt;
 }
 
-int image_masktexnum;
-int loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
+rtexture_t *image_masktex;
+rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
 {
-       int texnum, count;
+       int count;
        byte *data;
        char *filename2;
-       image_masktexnum = 0;
+       rtexture_t *rt;
+       image_masktex = NULL;
        if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
                return 0;
-       texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
+       rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
        count = image_makemask(data, data, image_width * image_height);
        if (count)
        {
                filename2 = qmalloc(strlen(filename) + 6);
                sprintf(filename2, "%s_mask", filename);
-               image_masktexnum = GL_LoadTexture (filename2, image_width, image_height, data, mipmap, true, 4);
+               image_masktex = R_LoadTexture (filename2, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0));
                qfree(filename2);
        }
        qfree(data);
-       return texnum;
+       return rt;
 }
 
 void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data)
diff --git a/image.h b/image.h
index ebaafd584bea79ff59c07daf06bceb4da81a9356..60a9759cf0306394f1d80924d988a95572a2e1be 100644 (file)
--- a/image.h
+++ b/image.h
@@ -3,11 +3,11 @@ extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
 extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
 extern int image_makemask (byte *in, byte *out, int size);
 extern byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
-extern int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap);
+extern rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
 extern byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight);
-extern int loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap);
-extern int image_masktexnum;
-extern int loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap);
+extern rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+extern rtexture_t *image_masktex;
+extern rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
 extern void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data);
 extern void Image_WriteTGARGB (char *filename, int width, int height, byte *data);
 extern void Image_WriteTGARGBA (char *filename, int width, int height, byte *data);
index 524d0d0ff07d4d493a3cc2b8a15175ee2fee7822..ea8460d752dcd34f0a5d42574a4550c9d283a89f 100644 (file)
@@ -355,13 +355,14 @@ void IN_Move(usercmd_t *cmd)
 
        if ((in_mlook.state & 1)) V_StopPitchDrift();
 
+       // LordHavoc: changed limits on pitch from -70 to 80, to -90 to 90
        if ((in_mlook.state & 1) && !(in_strafe.state & 1)) {
                cl.viewangles[PITCH] += m_pitch.value * mouse_y;
-               if (cl.viewangles[PITCH] > 80) {
-                       cl.viewangles[PITCH] = 80;
+               if (cl.viewangles[PITCH] > 90) {
+                       cl.viewangles[PITCH] = 90;
                }
-               if (cl.viewangles[PITCH] < -70) {
-                       cl.viewangles[PITCH] = -70;
+               if (cl.viewangles[PITCH] < -90) {
+                       cl.viewangles[PITCH] = -90;
                }
        } else {
                if ((in_strafe.state & 1) && noclip_anglehack) {
index 9b9f4fcb3626cc35543d0691b0f798d4f3a7d262..fb055bbb416e991c11aa2ff4d92029188d1cddb3 100644 (file)
--- a/in_win.c
+++ b/in_win.c
@@ -702,14 +702,15 @@ void IN_MouseMove (usercmd_t *cmd)
 
        if (in_mlook.state & 1)
                V_StopPitchDrift ();
-               
+       
+       // LordHavoc: changed limits on pitch from -70 to 80, to -90 to 90
        if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
        {
                cl.viewangles[PITCH] += m_pitch.value * mouse_y;
-               if (cl.viewangles[PITCH] > 80)
-                       cl.viewangles[PITCH] = 80;
-               if (cl.viewangles[PITCH] < -70)
-                       cl.viewangles[PITCH] = -70;
+               if (cl.viewangles[PITCH] > 90)
+                       cl.viewangles[PITCH] = 90;
+               if (cl.viewangles[PITCH] < -90)
+                       cl.viewangles[PITCH] = -90;
        }
        else
        {
@@ -1090,7 +1091,7 @@ void IN_JoyMove (usercmd_t *cmd)
                speed = cl_movespeedkey.value;
        else
                speed = 1;
-       aspeed = speed * host_frametime;
+       aspeed = speed * host_realframetime;
 
        // loop through the axes
        for (i = 0; i < JOY_MAX_AXES; i++)
index 6d54c3fbdf24805c9cbed0ddd2a0576a03527cf1..ea8fb19154f49ed0ba95a19e247321d59429ca80 100644 (file)
--- a/makefile
+++ b/makefile
@@ -1,5 +1,13 @@
+
+#uncomment one of these according to your sound driver
+#if you use ALSA version 0.9.x
 SND=snd_alsa_0_9.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 cpu_noasm.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o
+#if you use ALSA version 0.5.x
+#SND=snd_alsa_0_5.o
+#if you use the kernel sound driver or OSS
+#SND=snd_oss.o
+
+OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o
 
 OPTIMIZATIONS= -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations
 
index ba4f3d4a94fc37671126dba8f14f5fcb7316f719..9d847add2d8d3bfd2a7504241c8ba4284df62c26 100644 (file)
--- a/mathlib.c
+++ b/mathlib.c
@@ -31,8 +31,125 @@ int nanmask = 255<<23;
 
 #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
 
+float m_bytenormals[NUMVERTEXNORMALS][3] =
+{
+{-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188}, 
+{-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017}, 
+{-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000}, 
+{0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718}, 
+{0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651}, 
+{0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651}, 
+{0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188}, 
+{0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567}, 
+{-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191}, 
+{-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856}, 
+{-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325}, 
+{-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863}, 
+{-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621}, 
+{-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000}, 
+{0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863}, 
+{0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460}, 
+{0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242}, 
+{-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863}, 
+{0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017}, 
+{0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460}, 
+{0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000}, 
+{0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621}, 
+{0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785}, 
+{0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325}, 
+{0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567}, 
+{0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000}, 
+{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866}, 
+{0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000}, 
+{0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866}, 
+{0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567}, 
+{0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856}, 
+{0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866}, 
+{0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567}, 
+{0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731}, 
+{0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856}, 
+{0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718}, 
+{0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785}, 
+{0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191}, 
+{0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718}, 
+{-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651}, 
+{-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188}, 
+{-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056}, 
+{0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423}, 
+{0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188}, 
+{-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056}, 
+{0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718}, 
+{0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651}, 
+{0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188}, 
+{0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863}, 
+{0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785}, 
+{0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325}, 
+{0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242}, 
+{0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460}, 
+{0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242}, 
+{0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460}, 
+{0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621}, 
+{0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863}, 
+{-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460}, 
+{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621}, 
+{-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000}, 
+{-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863}, 
+{-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856}, 
+{-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325}, 
+{-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188}, 
+{-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017}, 
+{-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785}, 
+{-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188}, 
+{0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017}, 
+{0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651}, 
+{0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191}, 
+{0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000}, 
+{-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000}, 
+{-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000}, 
+{-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856}, 
+{-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000}, 
+{-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866}, 
+{-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567}, 
+{-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731}, 
+{-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191}, 
+{-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785}, 
+{-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325}, 
+};
+
+byte NormalToByte(vec3_t n)
+{
+       int i, best;
+       float bestdistance, distance;
+
+       best = 0;
+       bestdistance = DotProduct (n, m_bytenormals[0]);
+       for (i = 1;i < NUMVERTEXNORMALS;i++)
+       {
+               distance = DotProduct (n, m_bytenormals[i]);
+               if (distance > bestdistance)
+               {
+                       bestdistance = distance;
+                       best = i;
+               }
+       }
+       return best;
+}
+
+// note: uses byte partly to force unsigned for the validity check
+void ByteToNormal(byte num, vec3_t n)
+{
+       if (num < NUMVERTEXNORMALS)
+               VectorCopy(m_bytenormals[num], n)
+       else
+               VectorClear(n) // FIXME: complain?
+}
+
+#if 0
+// LordHavoc: no longer used at all
 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
 {
+#if 0
+       // LordHavoc: the old way...
        float d;
        vec3_t n;
        float inv_denom;
@@ -48,21 +165,32 @@ void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
        dst[0] = p[0] - d * n[0];
        dst[1] = p[1] - d * n[1];
        dst[2] = p[2] - d * n[2];
+#else
+       // LordHavoc: optimized to death and beyond
+       float d;
+
+       // LordHavoc: the normal is a unit vector by definition,
+       //            therefore inv_denom was pointless.
+       d = DotProduct(normal, p);
+       dst[0] = p[0] - d * normal[0];
+       dst[1] = p[1] - d * normal[1];
+       dst[2] = p[2] - d * normal[2];
+#endif
 }
+#endif
 
-/*
-** assumes "src" is normalized
-*/
+// assumes "src" is normalized
 void PerpendicularVector( vec3_t dst, const vec3_t src )
 {
+#if 0
+       // LordHavoc: the old way...
        int     pos;
        int i;
-       float minelem = 1.0F;
+       float minelem, d;
        vec3_t tempvec;
 
-       /*
-       ** find the smallest magnitude axially aligned vector
-       */
+       // find the smallest magnitude axially aligned vector
+       minelem = 1.0F;
        for ( pos = 0, i = 0; i < 3; i++ )
        {
                if ( fabs( src[i] ) < minelem )
@@ -71,27 +199,91 @@ void PerpendicularVector( vec3_t dst, const vec3_t src )
                        minelem = fabs( src[i] );
                }
        }
-       tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
+       VectorClear(tempvec);
        tempvec[pos] = 1.0F;
 
-       /*
-       ** project the point onto the plane defined by src
-       */
+       // project the point onto the plane defined by src
        ProjectPointOnPlane( dst, tempvec, src );
 
-       /*
-       ** normalize the result
-       */
-       VectorNormalize( dst );
+       // normalize the result
+       VectorNormalize(dst);
+#else
+       // LordHavoc: optimized to death and beyond
+       int     pos;
+       float minelem;
+
+       if (src[0])
+       {
+               dst[0] = 0;
+               if (src[1])
+               {
+                       dst[1] = 0;
+                       if (src[2])
+                       {
+                               dst[2] = 0;
+                               pos = 0;
+                               minelem = fabs(src[0]);
+                               if (fabs(src[1]) < minelem)
+                               {
+                                       pos = 1;
+                                       minelem = fabs(src[1]);
+                               }
+                               if (fabs(src[2]) < minelem)
+                                       pos = 2;
+
+                               dst[pos] = 1;
+                               dst[0] -= src[pos] * src[0];
+                               dst[1] -= src[pos] * src[1];
+                               dst[2] -= src[pos] * src[2];
+
+                               // normalize the result
+                               VectorNormalize(dst);
+                       }
+                       else
+                               dst[2] = 1;
+               }
+               else
+               {
+                       dst[1] = 1;
+                       dst[2] = 0;
+               }
+       }
+       else
+       {
+               dst[0] = 1;
+               dst[1] = 0;
+               dst[2] = 0;
+       }
+#endif
 }
 
+
 #ifdef _WIN32
 #pragma optimize( "", off )
 #endif
 
 
+// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
+void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
+{
+       float d;
+
+       right[0] = forward[2];
+       right[1] = -forward[0];
+       right[2] = forward[1];
+
+       d = DotProduct(forward, right);
+       right[0] -= d * forward[0];
+       right[1] -= d * forward[1];
+       right[2] -= d * forward[2];
+       VectorNormalize(right);
+       CrossProduct(right, forward, up);
+}
+
 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
 {
+#if 0
+       // LordHavoc: the old way, cryptic brute force...
        float   m[3][3];
        float   im[3][3];
        float   zrot[3][3];
@@ -140,9 +332,130 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
        R_ConcatRotations( tmpmat, im, rot );
 
        for ( i = 0; i < 3; i++ )
-       {
                dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
-       }
+#elif 0
+       // LordHavoc: on the path to unintelligible code...
+//     float   m[3][3];
+//     float   im[3][3];
+//     float   zrot[3][3];
+       float   tmpmat[3][3];
+//     float   rot[3][3];
+       float   angle, c, s;
+//     int     i;
+       vec3_t vr, vu, vf;
+
+       angle = DEG2RAD(degrees);
+
+       c = cos(angle);
+       s = sin(angle);
+
+       vf[0] = dir[0];
+       vf[1] = dir[1];
+       vf[2] = dir[2];
+
+       PerpendicularVector(vr, dir);
+       CrossProduct(vr, vf, vu);
+
+//     m   [0][0] = vr[0];m   [0][1] = vu[0];m   [0][2] = vf[0];
+//     m   [1][0] = vr[1];m   [1][1] = vu[1];m   [1][2] = vf[1];
+//     m   [2][0] = vr[2];m   [2][1] = vu[2];m   [2][2] = vf[2];
+//     im  [0][0] = vr[0];im  [0][1] = vr[1];im  [0][2] = vr[2];
+//     im  [1][0] = vu[0];im  [1][1] = vu[1];im  [1][2] = vu[2];
+//     im  [2][0] = vf[0];im  [2][1] = vf[1];im  [2][2] = vf[2];
+//     zrot[0][0] =     c;zrot[0][1] =     s;zrot[0][2] =     0;
+//     zrot[1][0] =    -s;zrot[1][1] =     c;zrot[1][2] =     0;
+//     zrot[2][0] =     0;zrot[2][1] =     0;zrot[2][2] =     1;
+
+//     tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
+//     tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
+//     tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
+//     tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
+//     tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
+//     tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
+//     tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
+//     tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
+//     tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
+
+       tmpmat[0][0] = vr[0] *  c + vu[0] * -s;
+       tmpmat[0][1] = vr[0] *  s + vu[0] *  c;
+//     tmpmat[0][2] =                           vf[0];
+       tmpmat[1][0] = vr[1] *  c + vu[1] * -s;
+       tmpmat[1][1] = vr[1] *  s + vu[1] *  c;
+//     tmpmat[1][2] =                           vf[1];
+       tmpmat[2][0] = vr[2] *  c + vu[2] * -s;
+       tmpmat[2][1] = vr[2] *  s + vu[2] *  c;
+//     tmpmat[2][2] =                           vf[2];
+
+//     rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
+//     rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
+//     rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
+//     rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
+//     rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
+//     rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
+//     rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
+//     rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
+//     rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
+
+//     rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
+//     rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
+//     rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
+//     rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
+//     rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
+//     rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
+//     rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
+//     rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
+//     rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
+
+//     dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
+//     dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
+//     dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
+
+       dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
+              + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
+              + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
+       dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
+              + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
+              + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
+       dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
+              + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
+              + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
+#else
+       // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
+       float   t0, t1;
+       float   angle, c, s;
+       vec3_t  vr, vu, vf;
+
+       angle = DEG2RAD(degrees);
+
+       c = cos(angle);
+       s = sin(angle);
+
+       vf[0] = dir[0];
+       vf[1] = dir[1];
+       vf[2] = dir[2];
+
+//     PerpendicularVector(vr, dir);
+//     CrossProduct(vr, vf, vu);
+       VectorVectors(vf, vr, vu);
+
+       t0 = vr[0] *  c + vu[0] * -s;
+       t1 = vr[0] *  s + vu[0] *  c;
+       dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
+              + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
+              + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
+
+       t0 = vr[1] *  c + vu[1] * -s;
+       t1 = vr[1] *  s + vu[1] *  c;
+       dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
+              + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
+              + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
+
+       t0 = vr[2] *  c + vu[2] * -s;
+       t1 = vr[2] *  s + vu[2] *  c;
+       dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
+              + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
+              + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
+#endif
 }
 
 #ifdef _WIN32
@@ -164,6 +477,20 @@ float      anglemod(float a)
        return a;
 }
 
+// LordHavoc note 1:
+// BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
+// assembly in an attempt to accelerate it further, very inefficient
+// considering that signbits of the frustum planes only changed each
+// frame, and the world planes changed only at load time.
+// So, to optimize it further I took the obvious route of storing a function
+// pointer in the plane struct itself, and shrunk each of the individual
+// cases to a single return statement.
+// LordHavoc note 2:
+// realized axial cases would be a nice speedup for world geometry, although
+// never useful for the frustum planes.
+int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
+int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
+int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
 int BoxOnPlaneSide0 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
 int BoxOnPlaneSide1 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
@@ -175,39 +502,53 @@ int BoxOnPlaneSide7 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->norm
 
 void BoxOnPlaneSideClassify(mplane_t *p)
 {
-       if (p->normal[2] < 0) // 4
+       switch(p->type)
        {
-               if (p->normal[1] < 0) // 2
+       case 0: // x axis
+               p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
+               break;
+       case 1: // y axis
+               p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
+               break;
+       case 2: // z axis
+               p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
+               break;
+       default:
+               if (p->normal[2] < 0) // 4
                {
-                       if (p->normal[0] < 0) // 1
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
+                       if (p->normal[1] < 0) // 2
+                       {
+                               if (p->normal[0] < 0) // 1
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
+                               else
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
+                       }
                        else
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
+                       {
+                               if (p->normal[0] < 0) // 1
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
+                               else
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
+                       }
                }
                else
                {
-                       if (p->normal[0] < 0) // 1
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
+                       if (p->normal[1] < 0) // 2
+                       {
+                               if (p->normal[0] < 0) // 1
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
+                               else
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
+                       }
                        else
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
-               }
-       }
-       else
-       {
-               if (p->normal[1] < 0) // 2
-               {
-                       if (p->normal[0] < 0) // 1
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
-                       else
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
-               }
-               else
-               {
-                       if (p->normal[0] < 0) // 1
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
-                       else
-                               p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
+                       {
+                               if (p->normal[0] < 0) // 1
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
+                               else
+                                       p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
+                       }
                }
+               break;
        }
 }
 
@@ -222,19 +563,35 @@ void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
        angle = angles[PITCH] * (M_PI*2 / 360);
        sp = sin(angle);
        cp = cos(angle);
-       angle = angles[ROLL] * (M_PI*2 / 360);
-       sr = sin(angle);
-       cr = cos(angle);
-
-       forward[0] = cp*cy;
-       forward[1] = cp*sy;
-       forward[2] = -sp;
-       right[0] = (-1*sr*sp*cy+-1*cr*-sy);
-       right[1] = (-1*sr*sp*sy+-1*cr*cy);
-       right[2] = -1*sr*cp;
-       up[0] = (cr*sp*cy+-sr*-sy);
-       up[1] = (cr*sp*sy+-sr*cy);
-       up[2] = cr*cp;
+       // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables
+       // (they are NOT used uninitialized, but oh well)
+       cr = 0;
+       sr = 0;
+       if (right || up)
+       {
+               angle = angles[ROLL] * (M_PI*2 / 360);
+               sr = sin(angle);
+               cr = cos(angle);
+       }
+
+       if (forward)
+       {
+               forward[0] = cp*cy;
+               forward[1] = cp*sy;
+               forward[2] = -sp;
+       }
+       if (right)
+       {
+               right[0] = (-1*sr*sp*cy+-1*cr*-sy);
+               right[1] = (-1*sr*sp*sy+-1*cr*cy);
+               right[2] = -1*sr*cp;
+       }
+       if (up)
+       {
+               up[0] = (cr*sp*cy+-sr*-sy);
+               up[1] = (cr*sp*sy+-sr*cy);
+               up[2] = cr*cp;
+       }
 }
 
 int VectorCompare (vec3_t v1, vec3_t v2)
index 3b669e90838d348fd991e06ee0fb933683cc1b8d..fde3d3e55bd3f2bf60c631466768e7c8dea16c12 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -20,8 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // mathlib.h
 
 typedef float vec_t;
+typedef vec_t vec2_t[2];
 typedef vec_t vec3_t[3];
+typedef vec_t vec4_t[4];
 typedef vec_t vec5_t[5];
+typedef vec_t vec6_t[6];
+typedef vec_t vec7_t[7];
+typedef vec_t vec8_t[8];
 
 typedef        int     fixed4_t;
 typedef        int     fixed8_t;
@@ -53,6 +58,8 @@ extern        int nanmask;
 #define VectorDistance2(a, b) ((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2]))
 #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
 #define VectorLength(a) sqrt(DotProduct(a, a))
+#define VectorScaleQuick(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);}
+#define 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];}
 
 
 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
@@ -70,6 +77,12 @@ void VectorInverse (vec3_t v);
 void VectorScale (vec3_t in, vec_t scale, vec3_t out);
 int Q_log2(int val);
 
+#define NUMVERTEXNORMALS       162
+extern float m_bytenormals[NUMVERTEXNORMALS][3];
+
+byte NormalToByte(vec3_t n);
+void ByteToNormal(byte num, vec3_t n);
+
 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
 
@@ -79,6 +92,8 @@ int GreatestCommonDivisor (int i1, int i2);
 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
 float  anglemod(float a);
 
+// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
+void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up);
 
 void BoxOnPlaneSideClassify(struct mplane_s *p);
 
diff --git a/menu.c b/menu.c
index 28de58ec0a7350862d67f4765d3fbcb6fb19f772..0e856961216ef82944cac1c9def5fd967b71e118 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -1333,7 +1333,7 @@ void M_AdjustSliders (int dir)
                Cvar_SetValue ("volume", volume.value);
                break;
 
-       case 8: // allways run
+       case 8: // always run
                if (cl_forwardspeed.value > 200)
                {
                        Cvar_SetValue ("cl_forwardspeed", 200);
index ba66d7241efe9b62b83df73e8bce0ad2d5781c59..f29d3a9e537f204392b061c8d65c2c318a61c632 100644 (file)
@@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
+cvar_t r_mipskins = {"r_mipskins", "1", true};
+
 /*
 ===============
 Mod_AliasInit
@@ -27,6 +29,7 @@ Mod_AliasInit
 */
 void Mod_AliasInit (void)
 {
+       Cvar_RegisterVariable(&r_mipskins);
 }
 
 int                    posenum;
@@ -40,11 +43,9 @@ int vertonseam[MAXVERTS];
 int vertremap[MAXVERTS];
 unsigned short temptris[MAXVERTS][3];
 
-#define NUMVERTEXNORMALS       162
-extern float   r_avertexnormals[NUMVERTEXNORMALS][3];
-void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
+void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
 {
-       int i, j;
+       int i, j, invalidnormals = 0;
        vec3_t temp;
        for (i = 0;i < inverts;i++)
        {
@@ -64,19 +65,27 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert
                if (j >= 0)
                {
                        VectorCopy(v[i].v, out[j].v);
-                       out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
-                       out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
-                       out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+                       out[j].lightnormalindex = v[i].lightnormalindex;
+                       if (out[j].lightnormalindex >= NUMVERTEXNORMALS)
+                       {
+                               invalidnormals++;
+                               out[j].lightnormalindex = 0;
+                       }
                }
                j = vertremap[i+inverts]; // onseam
                if (j >= 0)
                {
                        VectorCopy(v[i].v, out[j].v);
-                       out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
-                       out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
-                       out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+                       out[j].lightnormalindex = v[i].lightnormalindex;
+                       if (out[j].lightnormalindex >= NUMVERTEXNORMALS)
+                       {
+                               invalidnormals++;
+                               out[j].lightnormalindex = 0;
+                       }
                }
        }
+       if (invalidnormals)
+               Con_Printf("Mod_ConvertAliasVerts: %i invalid normal indices found\n", invalidnormals);
 }
 
 /*
@@ -84,17 +93,18 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert
 Mod_LoadAliasFrame
 =================
 */
-void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
+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(frame->name, pdaliasframe->name);
-       frame->start = posenum;
-       frame->length = 1;
-       frame->rate = 10.0f; // unnecessary but...
+       strcpy(scene->name, pdaliasframe->name);
+       scene->firstframe = posenum;
+       scene->framecount = 1;
+       scene->framerate = 10.0f; // unnecessary but...
+       scene->loop = true;
 
        pinframe = (trivertx_t *)(pdaliasframe + 1);
 
@@ -113,7 +123,7 @@ void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader
 Mod_LoadAliasGroup
 =================
 */
-void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
+void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
 {
        int             i, numframes;
        void    *ptemp;
@@ -121,13 +131,14 @@ void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader,
        
        numframes = LittleLong (((daliasgroup_t *)pin)->numframes);
 
-       strcpy(frame->name, "group");
-       frame->start = posenum;
-       frame->length = numframes;
+       strcpy(scene->name, ((daliasframe_t *) (sizeof(daliasinterval_t) * numframes + sizeof(daliasgroup_t) + (int) pin))->name);
+       scene->firstframe = posenum;
+       scene->framecount = numframes;
        interval = LittleFloat (((daliasinterval_t *)(((daliasgroup_t *)pin) + 1))->interval); // FIXME: support variable framerate groups?
        if (interval < 0.01f)
                Host_Error("Mod_LoadAliasGroup: invalid interval");
-       frame->rate = 1.0f / interval;
+       scene->framerate = 1.0f / interval;
+       scene->loop = true;
 
        ptemp = (void *)(((daliasinterval_t *)(((daliasgroup_t *)pin) + 1)) + numframes);
 
@@ -219,7 +230,7 @@ void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
        }
 }
 
-int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+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];
@@ -244,12 +255,12 @@ int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short
                out++;
        }
        if (passed)
-               return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+               return R_LoadTexture (name, width, height, out - width*height, (r_mipskins.value ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
        else
-               return 0;
+               return NULL;
 }
 
-int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+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];
@@ -270,9 +281,9 @@ int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits
                out++;
        }
        if (passed)
-               return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+               return R_LoadTexture (name, width, height, out - width*height, (r_mipskins.value ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
        else
-               return 0;
+               return NULL;
 }
 
 int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
@@ -292,7 +303,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, int *skintexnum)
+void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex)
 {
 #if 0
        int skin_normal, skin_pants, skin_shirt, skin_glow, skin_body, temp;
@@ -341,26 +352,31 @@ void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *s
                }
        }
 #else
-       skintexnum[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, true);
-       skintexnum[1] = 0;
-       skintexnum[2] = 0;
-       skintexnum[3] = loadtextureimage(va("%s_glow"  , basename), 0, 0, false, true);
-       skintexnum[4] = 0;
-       if (skintexnum[0])
+       skintex[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, r_mipskins.value, true);
+       skintex[1] = NULL;
+       skintex[2] = NULL;
+       skintex[3] = loadtextureimage(va("%s_glow"  , basename), 0, 0, false, r_mipskins.value, true);
+       skintex[4] = NULL;
+       if (skintex[0])
        {
-               skintexnum[1] = loadtextureimage(va("%s_pants" , basename), 0, 0, false, true);
-               skintexnum[2] = loadtextureimage(va("%s_shirt" , basename), 0, 0, false, true);
+               skintex[1] = loadtextureimage(va("%s_pants" , basename), 0, 0, false, r_mipskins.value, true);
+               skintex[2] = loadtextureimage(va("%s_shirt" , basename), 0, 0, false, r_mipskins.value, true);
        }
        else
        {
-               skintexnum[0] = loadtextureimage(basename, 0, 0, false, true);
-               if (!skintexnum[0])
+               skintex[0] = loadtextureimage(basename, 0, 0, false, true, true);
+               if (!skintex[0])
                {
-                       skintexnum[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FBD, va("&%s_normal", basename)); // normal (no special colors)
-                       skintexnum[1] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("&%s_pants", basename)); // pants
-                       skintexnum[2] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("&%s_shirt", basename)); // shirt
-                       skintexnum[3] = GL_SkinSplit(skindata, skintemp, width, height, 0xC000, va("%s_glow", basename)); // glow
-                       skintexnum[4] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename)); // body (normal + pants + shirt, but not glow)
+                       skintex[1] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants
+                       skintex[2] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt
+                       skintex[3] = GL_SkinSplit(skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), true); // glow
+                       if (skintex[1] || skintex[2])
+                       {
+                               skintex[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors)
+                               skintex[4] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), true); // body (normal + pants + shirt, but not glow)
+                       }
+                       else
+                               skintex[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), true); // no special colors
                }
        }
 #endif
@@ -380,7 +396,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
        daliasskingroup_t               *pinskingroup;
        int             groupskins;
        daliasskininterval_t    *pinskinintervals;
-       int             skinranges, skincount, *skintexnum, *skinrange, skinnum;
+       int             skinranges, skincount, *skinrange, skinnum;
+       rtexture_t **skintex;
        void    *temp;
        byte    *skintemp = NULL;
        
@@ -414,7 +431,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
        pskintype = temp;
 
        skinrange = loadmodel->skinanimrange;
-       skintexnum = loadmodel->skinanim;
+       skintex = loadmodel->skinanim;
 //     skinrange = Hunk_AllocName (sizeof(int) * (skinranges + skincount), loadname);  
 //     skintexnum = skinrange + skinranges * 2;
 //     loadmodel->skinanimrange = (int) skinrange - (int) pheader;
@@ -429,8 +446,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
                        *skinrange++ = 1; // single skin
                        skinnum++;
                        sprintf (name, "%s_%i", loadmodel->name, i);
-                       Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum);
-                       skintexnum += 5;
+                       Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintex);
+                       skintex += 5;
                        pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                }
                else
@@ -447,8 +464,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps
                        for (j = 0;j < groupskins;j++)
                        {
                                sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
-                               Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum);
-                               skintexnum += 5;
+                               Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintex);
+                               skintex += 5;
                                pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                        }
                }
@@ -482,8 +499,8 @@ void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
 Mod_LoadAliasModel
 =================
 */
-#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%d exceeds %d - %d)\n", mod->name, VALUE, MIN, MAX);
-#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX);
+#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", mod->name, VALUE, MIN, MAX);
+#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX);
 void Mod_LoadAliasModel (model_t *mod, void *buffer)
 {
        int                                     i, j, version, numframes, start, end, total, numverts, numtris, numposes, numskins, skinwidth, skinheight, f, totalverts;
@@ -495,8 +512,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        float                           *pouttexcoords, scales, scalet;
        maliashdr_t                     *mheader;
        unsigned short          *pouttris;
-       maliasframe_t           *frame;
-       trivert2                        *posevert;
+       trivertx_t                      *posevert;
+       animscene_t                     *animscenes;
 
        start = Hunk_LowMark ();
 
@@ -547,7 +564,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        // rebuild the model
        mheader = Hunk_AllocName (sizeof(maliashdr_t), va("%s model header", loadname));
        mod->flags = LittleLong (pinmodel->flags);
-       mod->type = mod_alias;
 // endian-adjust and copy the data, starting with the alias model header
        mheader->numverts = numverts;
        mod->numtris = mheader->numtris = numtris;
@@ -640,9 +656,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
 
 // load the frames
        posenum = 0;
-       frame = Hunk_AllocName(sizeof(maliasframe_t) * numframes, va("%s frame info", loadname));
-       mheader->framedata = (int) frame - (int) mheader;
-       posevert = Hunk_AllocName(sizeof(trivert2) * numposes * totalverts, va("%s vertex data", loadname));
+       posevert = Hunk_AllocName(sizeof(trivertx_t) * numposes * totalverts, va("%s vertex data", loadname));
        mheader->posedata = (int) posevert - (int) mheader;
        pframetype = (daliasframetype_t *)&pintriangles[numtris];
 
@@ -650,14 +664,18 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000;
        aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000000000;
 
-       for (i=0 ; i<numframes ; i++)
+       animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
+
+       for (i = 0;i < numframes;i++)
        {
                if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE)
-                       pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
+                       pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, mheader, numverts, totalverts, &posevert, animscenes + i);
                else
-                       pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
+                       pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, mheader, numverts, totalverts, &posevert, animscenes + i);
        }
 
+       mod->ofs_scenes = (int) animscenes - (int) mheader;
+
        // 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;
@@ -669,8 +687,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
 
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
-       total = end - start;
-       
+       mod->cachesize = total = end - start;
+
        Cache_Alloc (&mod->cache, total, loadname);
        if (!mod->cache.data)
                return;
@@ -679,9 +697,9 @@ 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, trivert2 *out)
+void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
 {
-       int i;
+       int i, invalidnormals = 0;
        vec3_t temp;
        for (i = 0;i < numverts;i++)
        {
@@ -696,62 +714,15 @@ 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];
-               out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
-               out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
-               out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
-       }               
-       /*
-       int i, j;
-       vec3_t t1, t2;
-       struct
-       {
-               vec3_t v;
-               vec3_t normal;
-               int count;
-       } tempvert[MD2MAX_VERTS];
-       temptris_t *tris;
-       // decompress vertices
-       for (i = 0;i < numverts;i++)
-       {
-               VectorCopy(v[i].v, out[i].v);
-               tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0];
-               tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1];
-               tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2];
-               tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0;
-               tempvert[i].count = 0;
-               // update bounding box
-               if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0];
-               if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1];
-               if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2];
-               if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0];
-               if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1];
-               if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2];
-       }
-       // calculate surface normals
-       tris = temptris;
-       for (i = 0;i < numtris;i++)
-       {
-               VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1);
-               VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2);
-               CrossProduct(t1, t2, tris->normal);
-               VectorNormalize(tris->normal);
-               // add surface normal to vertices
-               for (j = 0;j < 3;j++)
+               out[i].lightnormalindex = v[i].lightnormalindex;
+               if (out[i].lightnormalindex >= NUMVERTEXNORMALS)
                {
-                       VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
-                       tempvert[tris->v[j]].count++;
+                       invalidnormals++;
+                       out[i].lightnormalindex = 0;
                }
-               tris++;
-       }
-       // average normals and write out 1.7bit format
-       for (i = 0;i < pheader->numtris;i++)
-       {
-               VectorNormalize(tempvert[i].normal);
-               out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0);
-               out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0);
-               out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0);
        }
-       */
+       if (invalidnormals)
+               Con_Printf("Mod_ConvertQ2AliasVerts: %i invalid normal indices found\n", invalidnormals);
 }
 
 /*
@@ -766,9 +737,10 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        md2mem_t                        *pheader;
        md2triangle_t           *pintriangles, *pouttriangles;
        md2frame_t                      *pinframe;
-       md2memframe_t           *poutframe;
+       md2frame_t                      *poutframe;
        char                            *pinskins;
 //     temptris_t                      *tris;
+       animscene_t                     *animscenes;
 
        start = Hunk_LowMark ();
 
@@ -785,7 +757,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        mod->type = mod_alias;
        mod->aliastype = ALIASTYPE_MD2;
 
-       framesize = sizeof(md2memframesize_t) + LittleLong(pinmodel->num_xyz) * sizeof(trivert2);
+       framesize = sizeof(md2framesize_t) + LittleLong(pinmodel->num_xyz) * sizeof(trivertx_t);
        // LordHavoc: calculate size for in memory version
        size = sizeof(md2mem_t)
                 + LittleLong(pinmodel->num_st) * sizeof(md2stvert_t)
@@ -818,7 +790,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                Host_Error ("%s has invalid number of vertices: %i", mod->name, LittleLong(pinmodel->num_xyz));
        if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES)
                Host_Error ("%s has invalid number of frames: %i", mod->name, LittleLong(pinmodel->num_frames));
-       if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MD2MAX_SKINS)
+       if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MAX_SKINS)
                Host_Error ("%s has invalid number of skins: %i", mod->name, LittleLong(pinmodel->num_skins));
 
        pheader->framesize = framesize;
@@ -832,7 +804,8 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 // load the skins
        if (pheader->num_skins)
        {
-               int *skin, *skinrange;
+               rtexture_t **skin;
+               int *skinrange;
                skinrange = loadmodel->skinanimrange;
                skin = loadmodel->skinanim;
 //             skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);  
@@ -844,11 +817,11 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                {
                        *skinrange++ = i;
                        *skinrange++ = 1;
-                       *skin++ = loadtextureimage (pinskins, 0, 0, true, true);
-                       *skin++ = 0; // the extra 4 layers are currently unused
-                       *skin++ = 0;
-                       *skin++ = 0;
-                       *skin++ = 0;
+                       *skin++ = loadtextureimage (pinskins, 0, 0, true, r_mipskins.value, true);
+                       *skin++ = NULL; // the extra 4 layers are currently unused
+                       *skin++ = NULL;
+                       *skin++ = NULL;
+                       *skin++ = NULL;
                        pinskins += MD2MAX_SKINNAME;
                }
        }
@@ -860,9 +833,9 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        pheader->ofs_tris = (int) pouttriangles - (int) pheader;
 //     tris = temptris;
        // swap the triangle list
-       for (i=0 ; i<pheader->num_tris ; i++)
+       for (i = 0;i < pheader->num_tris;i++)
        {
-               for (j=0 ; j<3 ; j++)
+               for (j = 0;j < 3;j++)
                {
                        temptris[i][j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]);
                        pouttriangles->index_st[j] = LittleShort (pintriangles->index_st[j]);
@@ -883,19 +856,31 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        pinframe = (void*) ((int) pinmodel + LittleLong(pinmodel->ofs_frames));
        poutframe = (void*) pouttriangles;
        pheader->ofs_frames = (int) poutframe - (int) pheader;
-       for (i=0 ; i<pheader->num_frames ; i++)
+
+       animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
+
+       for (i = 0;i < pheader->num_frames;i++)
        {
+               strcpy(poutframe->name, pinframe->name);
                for (j = 0;j < 3;j++)
                {
-                       strcpy(poutframe->name, pinframe->name);
                        poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
                        poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
                }
                Mod_ConvertQ2AliasVerts (pheader->num_xyz, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]);
+
+               strcpy(animscenes[i].name, poutframe->name);
+               animscenes[i].firstframe = i;
+               animscenes[i].framecount = 1;
+               animscenes[i].framerate = 10;
+               animscenes[i].loop = true;
+
                pinframe = (void*) &pinframe->verts[j];
                poutframe = (void*) &poutframe->verts[j];
        }
 
+       mod->ofs_scenes = (int) animscenes - (int) pheader;
+
        // LordHavoc: model bbox
        for (j = 0;j < 3;j++)
        {
@@ -912,7 +897,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
-       total = end - start;
+       mod->cachesize = total = end - start;
        
        Cache_Alloc (&mod->cache, total, loadname);
        if (!mod->cache.data)
@@ -931,11 +916,13 @@ void swapintblock(int *m, int size)
 
 void Mod_LoadZymoticModel (model_t *mod, void *buffer)
 {
-       int i, pbase, start, end, total, *skin, *skinrange, *texturenum;
+       int i, pbase, start, end, total, *skinrange;
+       rtexture_t **texture, **skin;
        char *shadername;
        zymtype1header_t *pinmodel, *pheader;
        zymscene_t *scene;
        zymbone_t *bone;
+       animscene_t *animscenes;
 
        start = Hunk_LowMark ();
 
@@ -999,17 +986,18 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
 //     loadmodel->skinanim = (int) skin - (int) pheader;
        *skinrange++ = 0;
        *skinrange++ = 1;
-       *skin++ = 0;
-       *skin++ = 0;
-       *skin++ = 0;
-       *skin++ = 0;
-       *skin++ = 0;
+       *skin++ = NULL;
+       *skin++ = NULL;
+       *skin++ = NULL;
+       *skin++ = NULL;
+       *skin++ = NULL;
        loadmodel->numskins = 1;
 
        // go through the lumps, swapping things
 
 //     zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
        scene = (void *) (pheader->lump_scenes.start + pbase);
+       animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
        for (i = 0;i < pheader->numscenes;i++)
        {
                scene->mins[0] = BigFloat(scene->mins[0]);
@@ -1023,8 +1011,16 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
                scene->flags = BigLong(scene->flags);
                scene->start = BigLong(scene->start);
                scene->length = BigLong(scene->length);
+
+               memcpy(animscenes[i].name, scene->name, 32);
+               animscenes[i].firstframe = scene->start;
+               animscenes[i].framecount = scene->length;
+               animscenes[i].framerate = scene->framerate;
+               animscenes[i].loop = (scene->flags & ZYMSCENEFLAG_NOLOOP) == 0;
+
                scene++;
        }
+       mod->ofs_scenes = (int) animscenes - pbase;
 
 //     zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data
        swapintblock((void *) (pheader->lump_poses.start + pbase), pheader->lump_poses.length);
@@ -1052,13 +1048,13 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
 
 //     zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
        shadername = (void *) (pheader->lump_shaders.start + pbase);
-       texturenum = (void *) shadername;
+       texture = (void *) shadername;
        for (i = 0;i < pheader->numshaders;i++)
        {
-               int j;
-               j = loadtextureimage(shadername, 0, 0, true, true);
+               rtexture_t *rt;
+               rt = loadtextureimage(shadername, 0, 0, true, r_mipskins.value, true);
                shadername += 32;
-               *texturenum++ = j; // reuse shader name list for texture numbers
+               *texture++ = rt; // reuse shader name list for texture pointers
        }
 
 //     zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
@@ -1073,7 +1069,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer)
 
 // move the complete, relocatable alias model to the cache
        end = Hunk_LowMark ();
-       total = end - start;
+       mod->cachesize = total = end - start;
        
        Cache_Alloc (&mod->cache, total, loadname);
        if (!mod->cache.data)
index 73e831076c7cad76ac10dbee94dbb999fbd7ab9e..4d30cdaee3c9c1e6ef580216731a10f391921127 100644 (file)
@@ -61,13 +61,6 @@ typedef struct mtriangle_s {
 } mtriangle_t;
 */
 
-// LordHavoc: new vertex format
-typedef struct {
-       byte v[3]; // location
-       signed char n[3]; // surface normal for lighting *127.0
-} trivert2;
-
-#define        MAX_SKINS       32
 typedef struct {
        int                     ident;
        int                     version;
@@ -86,14 +79,6 @@ typedef struct {
        float           size;
 } daliashdr_t;
 
-typedef struct
-{
-       char name[16]; // LordHavoc: only kept this for reasons of viewthing support
-       unsigned short start;
-       unsigned short length;
-       float rate; // in poses per second
-} maliasframe_t;
-
 typedef struct
 {
        vec3_t          scale;
@@ -102,7 +87,6 @@ typedef struct
        int                     numtris;
        int                     numframes;
        int                     numposes;
-       int                     framedata; // LordHavoc: unsigned short start
        int                     texdata; // LordHavoc: texture coordinate array
        int                     posedata; // LordHavoc: vertex data for all the poses
        int                     tridata; // LordHavoc: vertex indices for the triangles
@@ -129,7 +113,6 @@ typedef struct
 #define        MD2MAX_TRIANGLES        4096
 #define MD2MAX_VERTS           4096
 #define MD2MAX_FRAMES          1024
-#define MD2MAX_SKINS   32
 #define        MD2MAX_SKINNAME 64
 // sanity checking size
 #define MD2MAX_SIZE    (16777216)
@@ -154,21 +137,12 @@ typedef struct
        trivertx_t      verts[1];       // variable sized
 } md2frame_t;
 
-// LordHavoc: memory representation is different than disk
-typedef struct
-{
-       float           scale[3];       // multiply byte verts by this
-       float           translate[3];   // then add this
-       char            name[16];       // LordHavoc: kept for viewthing
-       trivert2        verts[1];       // variable sized
-} md2memframe_t;
-
-// must match md2memframe_t, this is just used for sizeof()
+// must match md2frame_t, this is just used for sizeof()
 typedef struct
 {
        float           scale[3];       // multiply byte verts by this
        float           translate[3];   // then add this
-} md2memframesize_t;
+} md2framesize_t;
 
 
 // the glcmd format:
index 86d565a24653ac3bf030e3d89b90124f02d9f762..33350406d3740fcc3c207eb2542cf73d83e96d1c 100644 (file)
@@ -39,7 +39,56 @@ void Mod_BrushInit (void)
        memset (mod_novis, 0xff, sizeof(mod_novis));
 }
 
-// Mod_PointInLeaf moved to cpu_noasm.c
+/*
+===============
+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");
+
+       node = model->nodes;
+       if (node->contents < 0)
+               return (mleaf_t *)node;
+       while (1)
+       {
+               node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist];
+               if (node->contents < 0)
+                       return (mleaf_t *)node;
+       }
+       
+       return NULL;    // never reached
+}
+/*
+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");
+
+       node = model->nodes;
+       while (1)
+       {
+               if (node->contents < 0)
+                       return (mleaf_t *)node;
+               plane = node->plane;
+               d = DotProduct (p,plane->normal) - plane->dist;
+               if (d > 0)
+                       node = node->children[0];
+               else
+                       node = node->children[1];
+       }
+       
+       return NULL;    // never reached
+}
+*/
 
 /*
 ===================
@@ -104,7 +153,7 @@ Mod_LoadTextures
 */
 void Mod_LoadTextures (lump_t *l)
 {
-       int             i, j, num, max, altmax, bytesperpixel, freeimage, transparent, fullbrights;
+       int             i, j, num, max, altmax;
        miptex_t        *mt;
        texture_t       *tx, *tx2;
        texture_t       *anims[10];
@@ -156,143 +205,135 @@ void Mod_LoadTextures (lump_t *l)
                for (;j < 16;j++)
                        tx->name[j] = 0;
 
-               tx->width = mt->width;
-               tx->height = mt->height;
                for (j=0 ; j<MIPLEVELS ; j++)
                        tx->offsets[j] = 0;
-               freeimage = true;
-               transparent = true;
-               fullbrights = false;
-               bytesperpixel = 4;
-               data = loadimagepixels(tx->name, false, 0, 0); //tx->width, tx->height);
-               if (!data) // no external texture found
+               tx->transparent = false;
+               data = loadimagepixels(tx->name, false, 0, 0);
+               if (data)
+               {
+                       if (!hlbsp && !strncmp(tx->name,"sky",3) && image_width == 256 && image_height == 128) // LordHavoc: HL sky textures are entirely unrelated
+                       {
+                               tx->width = image_width;
+                               tx->height = image_height;
+                               tx->transparent = false;
+                               tx->texture = NULL;
+                               tx->glowtexture = NULL;
+                               R_InitSky (data, 4);
+                       }
+                       else
+                       {
+                               tx->width = mt->width;
+                               tx->height = mt->height;
+                               tx->transparent = true;
+                               tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                               tx->glowtexture = NULL;
+                       }
+                       qfree(data);
+               }
+               else
                {
-                       if (hlbsp)
+                       if (!hlbsp && !strncmp(tx->name,"sky",3) && mt->width == 256 && mt->height == 128) // LordHavoc: HL sky textures are entirely unrelated
                        {
-                               if (mt->offsets[0]) // texture included
+                               tx->width = mt->width;
+                               tx->height = mt->height;
+                               tx->transparent = false;
+                               tx->texture = NULL;
+                               tx->glowtexture = NULL;
+                               R_InitSky ((byte *)((int) mt + mt->offsets[0]), 1);
+                       }
+                       else
+                       {
+                               if (hlbsp)
                                {
-                                       freeimage = true;
-                                       transparent = true;
-                                       bytesperpixel = 4;
-                                       data = W_ConvertWAD3Texture(mt);
-                                       tx->width = image_width;
-                                       tx->height = image_height;
-                                       /*
-                                       byte *in, *out, *pal;
-//                                     int palsize;
-                                       int d, p;
-                                       bytesperpixel = 4;
-                                       freeimage = true;
-                                       transparent = false;
-                                       in = (byte *)((int) mt + mt->offsets[0]);
-                                       data = out = qmalloc(mt->width * mt->height * 4);
-                                       pal = in + (((mt->width * mt->height) * 85) >> 6);
-//                                     palsize = pal[1] * 0x100 + pal[0];
-//                                     if (palsize >= 256)
-//                                             palsize = 256;
-                                       pal += 2;
-                                       for (d = 0;d < mt->width * mt->height;d++)
+                                       if (mt->offsets[0]) // texture included
                                        {
-                                               p = *in++;
-                                               if (mt->name[0] == '{' && p == 255)
+                                               data = W_ConvertWAD3Texture(mt);
+                                               if (data)
                                                {
-                                                       out[0] = out[1] = out[2] = out[3] = 0;
-                                                       transparent = true;
+                                                       tx->width = mt->width;
+                                                       tx->height = mt->height;
+                                                       tx->transparent = true;
+                                                       tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                                       qfree(data);
                                                }
-                                               else
+                                       }
+                                       if (!data)
+                                       {
+                                               data = W_GetTexture(mt->name);
+                                               // get the size from the wad texture
+                                               if (data)
                                                {
-                                                       p *= 3;
-                                                       out[0] = pal[p];
-                                                       out[1] = pal[p+1];
-                                                       out[2] = pal[p+2];
-                                                       out[3] = 255;
+                                                       tx->width = image_width;
+                                                       tx->height = image_height;
+                                                       tx->transparent = true;
+                                                       tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                                       qfree(data);
                                                }
-                                               out += 4;
                                        }
-                                       */
-                               }
-                               if (!data)
-                               {
-                                       freeimage = true;
-                                       transparent = true;
-                                       bytesperpixel = 4;
-                                       data = W_GetTexture(mt->name);
-                                       tx->width = image_width;
-                                       tx->height = image_height;
-                               }
-                               if (!data)
-                               {
-                                       freeimage = false;
-                                       transparent = false;
-                                       bytesperpixel = 1;
-                                       data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]);
-                                       tx->width = tx->height = 16;
+                                       if (!data)
+                                       {
+                                               tx->width = r_notexture_mip->width;
+                                               tx->height = r_notexture_mip->height;
+                                               tx->transparent = false;
+                                               tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
+                                               tx->glowtexture = NULL;
+                                       }
                                }
-                       }
-                       else
-                       {
-                               if (mt->offsets[0]) // texture included
+                               else
                                {
-                                       freeimage = false;
-                                       transparent = false;
-                                       bytesperpixel = 1;
-                                       data = (byte *)((int) mt + mt->offsets[0]);
-                                       tx->width = mt->width;
-                                       tx->height = mt->height;
-                                       if (r_fullbrights.value && tx->name[0] != '*')
+                                       if (mt->offsets[0]) // texture included
                                        {
-                                               for (j = 0;j < tx->width*tx->height;j++)
+                                               int fullbrights;
+                                               data = (byte *)((int) mt + mt->offsets[0]);
+                                               tx->width = mt->width;
+                                               tx->height = mt->height;
+                                               tx->transparent = false;
+                                               fullbrights = false;
+                                               if (r_fullbrights.value && tx->name[0] != '*')
                                                {
-                                                       if (data[j] >= 224) // fullbright
+                                                       for (j = 0;j < tx->width*tx->height;j++)
                                                        {
-                                                               fullbrights = true;
-                                                               break;
+                                                               if (data[j] >= 224) // fullbright
+                                                               {
+                                                                       fullbrights = true;
+                                                                       break;
+                                                               }
                                                        }
                                                }
+                                               if (fullbrights)
+                                               {
+                                                       char name[64];
+                                                       byte *data2;
+                                                       data2 = qmalloc(tx->width*tx->height);
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                               data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
+                                                       tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       strcpy(name, tx->name);
+                                                       strcat(name, "_glow");
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                               data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
+                                                       tx->glowtexture = R_LoadTexture (name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       qfree(data2);
+                                               }
+                                               else
+                                               {
+                                                       tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data, TEXF_MIPMAP | TEXF_PRECACHE);
+                                                       tx->glowtexture = NULL;
+                                               }
+                                       }
+                                       else // no texture, and no external replacement texture was found
+                                       {
+                                               tx->width = r_notexture_mip->width;
+                                               tx->height = r_notexture_mip->height;
+                                               tx->transparent = false;
+                                               tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE);
+                                               tx->glowtexture = NULL;
                                        }
-                               }
-                               else // no texture, and no external replacement texture was found
-                               {
-                                       freeimage = false;
-                                       transparent = false;
-                                       bytesperpixel = 1;
-                                       data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]);
-                                       tx->width = tx->height = 16;
                                }
                        }
                }
-               if (!hlbsp && !strncmp(tx->name,"sky",3) && tx->width == 256 && tx->height == 128) // LordHavoc: HL sky textures are entirely unrelated
-               {
-                       tx->transparent = false;
-                       R_InitSky (data, bytesperpixel);
-               }
-               else
-               {
-                       if (fullbrights)
-                       {
-                               char name[64];
-                               byte *data2;
-                               tx->transparent = false;
-                               data2 = qmalloc(tx->width*tx->height);
-                               for (j = 0;j < tx->width*tx->height;j++)
-                                       data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
-                               tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data2, true, false, 1);
-                               strcpy(name, tx->name);
-                               strcat(name, "_glow");
-                               for (j = 0;j < tx->width*tx->height;j++)
-                                       data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
-                               tx->gl_glowtexturenum = GL_LoadTexture (name, tx->width, tx->height, data2, true, false, 1);
-                               qfree(data2);
-                       }
-                       else
-                       {
-                               tx->transparent = transparent;
-                               tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data, true, transparent, bytesperpixel);
-                               tx->gl_glowtexturenum = 0;
-                       }
-               }
-               if (freeimage)
-                       qfree(data);
        }
 
 //
@@ -304,7 +345,7 @@ void Mod_LoadTextures (lump_t *l)
                if (!tx || tx->name[0] != '+')
                        continue;
                if (tx->anim_next)
-                       continue;       // allready sequenced
+                       continue;       // already sequenced
 
        // find the number of frames in the animation
                memset (anims, 0, sizeof(anims));
@@ -773,7 +814,7 @@ void Mod_LoadFaces (lump_t *l)
 //             if (!strncmp(out->texinfo->texture->name,"*",1))                // turbulent
                if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
                {
-                       out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
+                       out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED | SURF_LIGHTBOTHSIDES);
                        // LordHavoc: some turbulent textures should be fullbright and solid
                        if (!strncmp(out->texinfo->texture->name,"*lava",5)
                         || !strncmp(out->texinfo->texture->name,"*teleport",9)
index 2ca09612d0ff60e0feff67193c26c3778ce20d67..33b050691d2b6e448dc2e4a3168e250ebcf7b507 100644 (file)
@@ -55,8 +55,8 @@ typedef struct texture_s
 {
        char            name[16];
        unsigned        width, height;
-       int                     gl_texturenum;
-       int                     gl_glowtexturenum; // LordHavoc: fullbrights on walls
+       rtexture_t      *texture;
+       rtexture_t      *glowtexture; // LordHavoc: fullbrights on walls
        struct msurface_s       *texturechain;  // for gl_texsort drawing
        int                     anim_total;                             // total tenths in sequence ( 0 = no)
        int                     anim_min, anim_max;             // time for this frame min <=time< max
@@ -77,6 +77,8 @@ typedef struct texture_s
 // LordHavoc: added these for lava and teleport textures
 #define SURF_DRAWNOALPHA       0x100
 #define SURF_DRAWFULLBRIGHT    0x200
+// LordHavoc: light both sides
+#define SURF_LIGHTBOTHSIDES            0x400
 
 // !!! if this is changed, it must be changed in asm_draw.h too !!!
 typedef struct
index d9d0efbcc665a81f6049fad450e50704f65f1927..1aaac8e46b4b42988b2f36cbb739c815c12f1d1d 100644 (file)
@@ -34,7 +34,8 @@ extern void Mod_LoadQ2AliasModel (model_t *mod, void *buffer);
 extern void Mod_LoadZymoticModel (model_t *mod, void *buffer);
 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
 
-#define        MAX_MOD_KNOWN   512
+// LordHavoc: increased from 512 to 2048
+#define        MAX_MOD_KNOWN   2048
 model_t        mod_known[MAX_MOD_KNOWN];
 int            mod_numknown;
 
@@ -87,7 +88,7 @@ void Mod_ClearAll (void)
        model_t *mod;
        
        for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
-               if (mod->type != mod_alias)
+               if (!mod->cachesize)
                        mod->needload = true;
 }
 
@@ -137,10 +138,8 @@ void Mod_TouchModel (char *name)
        mod = Mod_FindName (name);
        
        if (!mod->needload)
-       {
-               if (mod->type == mod_alias)
+               if (mod->cachesize)
                        Cache_Check (&mod->cache);
-       }
 }
 
 /*
@@ -157,7 +156,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
 
        if (!mod->needload)
        {
-               if (mod->type == mod_alias)
+               if (mod->cachesize)
                {
                        d = Cache_Check (&mod->cache);
                        if (d)
@@ -263,7 +262,7 @@ void Mod_Print (void)
        Con_Printf ("Cached models:\n");
        for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
        {
-               Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
+               Con_Printf ("%4iK : %8p : %s\n", (mod->cachesize + 1023) / 1024, mod->cache.data, mod->name);
        }
 }
 
index d3a701a792545c0cc6b076c1eba9381e83fef611..1d50a07bfed351842ef712d163d71ea61afe0d13 100644 (file)
@@ -35,6 +35,19 @@ m*_t structures are in-memory
 
 typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
 
+typedef struct animscene_s
+{
+       char name[32]; // for viewthing support
+       int firstframe;
+       int framecount;
+       int loop; // true or false
+       float framerate;
+}
+animscene_t;
+
+#define MAX_SKINS 256
+
+
 #include "model_brush.h"
 #include "model_sprite.h"
 #include "model_alias.h"
@@ -42,7 +55,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
 typedef struct model_s
 {
        char            name[MAX_QPATH];
-       qboolean        needload;               // bmodels and sprites don't cache normally
+       qboolean        needload;               // bmodels don't cache normally
 
        modtype_t       type;
        int                     aliastype; // LordHavoc: Q2 model support
@@ -108,11 +121,16 @@ typedef struct model_s
        // LordHavoc: useful for sprites and models
        int                     numtris;
        int                     numskins;
-       int                     skinanimrange[1024]; // array of start and length pairs, note: offset from ->cache.data
-       int                     skinanim[1024*5]; // texture numbers for each frame (indexed by animrange), note: offset from ->cache.data, second note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow)
+       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
 
 // additional model data
        cache_user_t    cache;          // only access through Mod_Extradata
+       int                     cachesize;              // size of cached data (zero if not cached)
 
 } model_t;
 
index 4db67bca50b0eb800e967a02f7bfb6b74f5e6ad9..fda321eec23754dc85853fa60b6c13f03a9f85f0 100644 (file)
@@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
+cvar_t r_mipsprites = {"r_mipsprites", "1", true};
+
 /*
 ===============
 Mod_SpriteInit
@@ -31,6 +33,7 @@ Mod_SpriteInit
 */
 void Mod_SpriteInit (void)
 {
+       Cvar_RegisterVariable(&r_mipsprites);
 }
 
 void Mod_Sprite_StripExtension(char *in, char *out)
@@ -53,7 +56,7 @@ void Mod_Sprite_StripExtension(char *in, char *out)
 Mod_LoadSpriteFrame
 =================
 */
-void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel)
 {
        dspriteframe_t          *pinframe;
        mspriteframe_t          *pspriteframe;
@@ -67,14 +70,12 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
        height = LittleLong (pinframe->height);
        size = width * height * bytesperpixel;
 
-       pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t), va("%s frames", loadname));
+       pspriteframe = frame;
 
        memset (pspriteframe, 0, sizeof (mspriteframe_t));
 
-       *ppframe = pspriteframe;
-
-       pspriteframe->width = width;
-       pspriteframe->height = height;
+//     pspriteframe->width = width;
+//     pspriteframe->height = height;
        origin[0] = LittleLong (pinframe->origin[0]);
        origin[1] = LittleLong (pinframe->origin[1]);
 
@@ -85,11 +86,11 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
 
        Mod_Sprite_StripExtension(loadmodel->name, tempname);
        sprintf (name, "%s_%i", tempname, framenum);
-       pspriteframe->gl_texturenum = loadtextureimagewithmask(name, 0, 0, false, true);
-       pspriteframe->gl_fogtexturenum = image_masktexnum;
-       if (pspriteframe->gl_texturenum == 0)
+       pspriteframe->texture = loadtextureimagewithmask(name, 0, 0, false, r_mipsprites.value, true);
+       pspriteframe->fogtexture = image_masktex;
+       if (!pspriteframe->texture)
        {
-               pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, bytesperpixel);
+               pspriteframe->texture = R_LoadTexture (name, width, height, (byte *)(pinframe + 1), TEXF_ALPHA | (bytesperpixel > 1 ? TEXF_RGBA : 0) | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
                // make fog version (just alpha)
                pixbuf = pixel = qmalloc(width*height*4);
                inpixel = (byte *)(pinframe + 1);
@@ -119,7 +120,7 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
                        }
                }
                sprintf (name, "%s_%ifog", loadmodel->name, framenum);
-               pspriteframe->gl_fogtexturenum = GL_LoadTexture (name, width, height, pixbuf, true, true, 4);
+               pspriteframe->fogtexture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
                qfree(pixbuf);
        }
 
@@ -132,45 +133,15 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
 Mod_LoadSpriteGroup
 =================
 */
-void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
+void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int framenum, int bytesperpixel)
 {
-       dspritegroup_t          *pingroup;
-       mspritegroup_t          *pspritegroup;
-       int                                     i, numframes;
-       dspriteinterval_t       *pin_intervals;
-       float                           *poutintervals;
-       void                            *ptemp;
-
-       pingroup = (dspritegroup_t *)pin;
-
-       numframes = LittleLong (pingroup->numframes);
-
-       pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + (numframes - 1) * sizeof (pspritegroup->frames[0]), va("%s frames", loadname));
+       int i;
+       void *ptemp;
 
-       pspritegroup->numframes = numframes;
+       ptemp = (void *)(sizeof(dspriteinterval_t) * numframes + sizeof(dspritegroup_t) + (int) pin);
 
-       *ppframe = (mspriteframe_t *)pspritegroup;
-
-       pin_intervals = (dspriteinterval_t *)(pingroup + 1);
-
-       poutintervals = Hunk_AllocName (numframes * sizeof (float), va("%s frames", loadname));
-
-       pspritegroup->intervals = poutintervals;
-
-       for (i=0 ; i<numframes ; i++)
-       {
-               *poutintervals = LittleFloat (pin_intervals->interval);
-               if (*poutintervals <= 0.0)
-                       Host_Error ("Mod_LoadSpriteGroup: interval<=0");
-
-               poutintervals++;
-               pin_intervals++;
-       }
-
-       ptemp = (void *)pin_intervals;
-
-       for (i=0 ; i<numframes ; i++)
-               ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i, bytesperpixel);
+       for (i = 0;i < numframes;i++)
+               ptemp = Mod_LoadSpriteFrame (ptemp, frame++, framenum * 100 + i, bytesperpixel);
 
        return ptemp;
 }
@@ -183,15 +154,16 @@ Mod_LoadSpriteModel
 */
 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
 {
-       int                                     i;
-       int                                     version;
+       int                                     i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight;
        dsprite_t                       *pin;
        msprite_t                       *psprite;
-       int                                     numframes;
-       int                                     size;
        dspriteframetype_t      *pframetype;
-       // LordHavoc: 32bit textures
-       int             bytesperpixel;
+       dspriteframe_t          *pframe;
+       animscene_t                     *animscenes;
+       mspriteframe_t          *frames;
+       dspriteframe_t          **framedata;
+
+       start = Hunk_LowMark ();
 
        mod->flags = EF_FULLBRIGHT;
        // LordHavoc: hack to allow sprites to be non-fullbright
@@ -204,6 +176,9 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
                }
        }
 
+       // build a list of frames while parsing
+       framedata = qmalloc(65536*sizeof(dspriteframe_t));
+
        pin = (dsprite_t *)buffer;
 
        version = LittleLong (pin->version);
@@ -214,31 +189,28 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
        }
        // LordHavoc: 32bit textures
        if (version != SPRITE_VERSION && version != SPRITE32_VERSION)
-               Host_Error ("%s has wrong version number "
-                                "(%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION);
+               Host_Error ("%s has wrong version number (%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION);
        bytesperpixel = 1;
        if (version == SPRITE32_VERSION)
                bytesperpixel = 4;
 
        numframes = LittleLong (pin->numframes);
 
-       size = sizeof (msprite_t) +     (numframes - 1) * sizeof (psprite->frames);
+       psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
 
-       psprite = Hunk_AllocName (size, va("%s info", loadname));
-
-       mod->cache.data = psprite;
+//     mod->cache.data = psprite;
 
        psprite->type = LittleLong (pin->type);
-       psprite->maxwidth = LittleLong (pin->width);
-       psprite->maxheight = LittleLong (pin->height);
-       psprite->beamlength = LittleFloat (pin->beamlength);
+       maxwidth = LittleLong (pin->width);
+       maxheight = LittleLong (pin->height);
+//     psprite->beamlength = LittleFloat (pin->beamlength);
        mod->synctype = LittleLong (pin->synctype);
-       psprite->numframes = numframes;
+//     psprite->numframes = numframes;
 
-       mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
-       mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
-       mod->mins[2] = -psprite->maxheight/2;
-       mod->maxs[2] = psprite->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
@@ -250,18 +222,75 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
 
        pframetype = (dspriteframetype_t *)(pin + 1);
 
-       for (i=0 ; i<numframes ; i++)
+       animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
+
+       realframes = 0;
+
+       for (i = 0;i < numframes;i++)
        {
                spriteframetype_t       frametype;
 
                frametype = LittleLong (pframetype->type);
-               psprite->frames[i].type = frametype;
 
+               sprintf(animscenes[i].name, "frame%i", i);
+               animscenes[i].firstframe = realframes;
+               animscenes[i].loop = true;
                if (frametype == SPR_SINGLE)
-                       pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
+               {
+                       animscenes[i].framecount = 1;
+                       animscenes[i].framerate = 10;
+                       pframe = (dspriteframe_t *) (pframetype + 1);
+                       framedata[realframes] = pframe;
+                       size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
+                       pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
+                       realframes++;
+               }
                else
-                       pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
+               {
+                       j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes);
+                       animscenes[i].framecount = j;
+                       // FIXME: support variable framerate?
+                       animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval);
+                       pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype);
+                       while (j--)
+                       {
+                               framedata[realframes] = pframe;
+                               size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
+                               pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
+                               realframes++;
+                       }
+                       pframetype = (dspriteframetype_t *) pframe;
+               }
        }
 
+       mod->ofs_scenes = (int) animscenes - (int) psprite;
+
+       frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname));
+
+       realframes = 0;
+       for (i = 0;i < numframes;i++)
+       {
+               for (j = 0;j < animscenes[i].framecount;j++)
+               {
+                       Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel);
+                       realframes++;
+               }
+       }
+
+       psprite->ofs_frames = (int) frames - (int) psprite;
+
+       qfree(framedata);
+
        mod->type = mod_sprite;
+
+// move the complete, relocatable sprite model to the cache
+       end = Hunk_LowMark ();
+       mod->cachesize = total = end - start;
+       
+       Cache_Alloc (&mod->cache, total, loadname);
+       if (!mod->cache.data)
+               return;
+       memcpy (mod->cache.data, psprite, total);
+
+       Hunk_FreeToLowMark (start);
 }
index c07c8883601554cc9d9c8d26e0960af722d14f63..595f226610c58fbf3d73d791826408ca2583bab9 100644 (file)
@@ -31,32 +31,19 @@ SPRITE MODELS
 // FIXME: shorten these?
 typedef struct mspriteframe_s
 {
-       int             width;
-       int             height;
+//     int             width;
+//     int             height;
        float   up, down, left, right;
-       int             gl_texturenum, gl_fogtexturenum;
+       rtexture_t *texture, *fogtexture;
 } mspriteframe_t;
 
-typedef struct
-{
-       int                             numframes;
-       float                   *intervals;
-       mspriteframe_t  *frames[1];
-} mspritegroup_t;
-
-typedef struct
-{
-       spriteframetype_t       type;
-       mspriteframe_t          *frameptr;
-} mspriteframedesc_t;
-
 typedef struct
 {
        int                                     type;
-       int                                     maxwidth;
-       int                                     maxheight;
-       int                                     numframes;
-       float                           beamlength;             // remove?
-       void                            *cachespot;             // remove?
-       mspriteframedesc_t      frames[1];
+//     int                                     maxwidth;
+//     int                                     maxheight;
+//     int                                     numframes;
+//     float                           beamlength;             // remove?
+//     void                            *cachespot;             // remove?
+       int                                     ofs_frames;
 } msprite_t;
diff --git a/net.h b/net.h
index 71dc2541dd00036fb1e401d4bcc51079849e6451..b41cadce9fc363ff982869960625476ce4b34a49 100644 (file)
--- a/net.h
+++ b/net.h
@@ -28,7 +28,7 @@ struct qsockaddr
 
 #define        NET_NAMELEN                     64
 
-#define NET_MAXMESSAGE         8192
+#define NET_MAXMESSAGE         16384
 #define NET_HEADERSIZE         (2 * sizeof(unsigned int))
 #define NET_DATAGRAMSIZE       (MAX_DATAGRAM + NET_HEADERSIZE)
 
index e9c3effd649dd5fe565ad19e91860221c1ac6803..e4ba51a93fcb5255775f504610455b0d36361f45 100644 (file)
--- a/pr_cmds.c
+++ b/pr_cmds.c
@@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 ===============================================================================
 */
 
+
 char *PF_VarString (int        first)
 {
        int             i;
@@ -44,60 +45,65 @@ char *PF_VarString (int     first)
        return out;
 }
 
-char *QSG_EXTENSIONS = "\
-DP_BLOOD \
-DP_BLOODSHOWER \
-DP_CORPSE \
-DP_DRAWONLYTOCLIENT \
-DP_EXPLOSION3 \
-DP_PARTICLECUBE \
-DP_PARTICLERAIN \
-DP_PARTICLESNOW \
-DP_GETLIGHT \
-DP_NODRAWTOCLIENT \
-DP_RANDOMVEC \
+char *ENGINE_EXTENSIONS = "\
+DP_ENT_ALPHA \
+DP_ENT_COLORMOD \
+DP_ENT_DELTACOMPRESS \
+DP_ENT_GLOW \
+DP_ENT_SCALE \
+DP_ENT_VIEWMODEL \
+DP_GFX_FOG \
+DP_HALFLIFE_MAP \
+DP_INPUTBUTTONS \
+DP_MONSTERWALK \
+DP_MOVETYPEFOLLOW \
+DP_SOLIDCORPSE \
 DP_REGISTERCVAR \
-DP_SPARK \
 DP_SPRITE32 \
-DP_MODEL32 \
-DP_TRACEBOX \
-DP_MINMAXBOUND \
-DP_FINDFLOAT \
-NEH_PLAY2 \
-QSG_ALPHA \
-QSG_BUTTONS \
-QSG_CHANGEPITCH \
-QSG_COLORMOD \
-QSG_DELTA \
-QSG_ETOS \
-QSG_FOG \
-QSG_FOLLOW \
-QSG_GLOW \
-QSG_MATH \
-QSG_MONSTERWALK \
-QSG_QUAKE2MODEL \
-QSG_SCALE \
-QSG_SKYBOX \
-QSG_TRACETOSS \
-QSG_VIEWMODEL \
-QSG_COPYENT \
+DP_SV_DRAWONLYTOCLIENT \
+DP_SV_NODRAWTOCLIENT \
+DP_SV_SETCOLOR \
+DP_SV_EFFECT \
+DP_TE_BLOOD \
+DP_TE_BLOODSHOWER \
+DP_TE_EXPLOSIONRGB \
+DP_TE_PARTICLECUBE \
+DP_TE_PARTICLERAIN \
+DP_TE_PARTICLESNOW \
+DP_TE_SPARK \
+DP_QC_CHANGEPITCH \
+DP_QC_COPYENTITY \
+DP_QC_ETOS \
+DP_QC_FINDFLOAT \
+DP_QC_FINDCHAIN \
+DP_QC_FINDCHAINFLOAT \
+DP_QC_GETLIGHT \
+DP_QC_SINCOSSQRTPOW \
+DP_QC_MINMAXBOUND \
+DP_QC_RANDOMVEC \
+DP_QC_TRACEBOX \
+DP_QC_TRACETOSS \
+DP_QUAKE2_MODEL \
+NEH_CMD_PLAY2 \
 ";
 
 qboolean checkextension(char *name)
 {
        int len;
-       char *e;
+       char *e, *start;
        len = strlen(name);
-       for (e = QSG_EXTENSIONS;*e;e++)
+       for (e = ENGINE_EXTENSIONS;*e;e++)
        {
                while (*e == ' ')
                        e++;
                if (!*e)
                        break;
-               if (!strncasecmp(e, name, len))
-                       return true;
+               start = e;
                while (*e && *e != ' ')
                        e++;
+               if (e - start == len)
+                       if (!strncasecmp(e, name, len))
+                               return true;
        }
        return false;
 }
@@ -132,8 +138,7 @@ void PF_error (void)
        edict_t *ed;
        
        s = PF_VarString(0);
-       Con_Printf ("======SERVER ERROR in %s:\n%s\n"
-       ,pr_strings + pr_xfunction->s_name,s);
+       Con_Printf ("======SERVER ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
        ed = PROG_TO_EDICT(pr_global_struct->self);
        ED_Print (ed);
 
@@ -156,13 +161,13 @@ void PF_objerror (void)
        edict_t *ed;
        
        s = PF_VarString(0);
-       Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
-       ,pr_strings + pr_xfunction->s_name,s);
+       Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
        ed = PROG_TO_EDICT(pr_global_struct->self);
        ED_Print (ed);
        ED_Free (ed);
-       
-       Host_Error ("Program error");
+
+// LordHavoc: bug fix - no longer kills server
+//     Host_Error ("Program error");
 }
 
 
@@ -180,6 +185,20 @@ void PF_makevectors (void)
        AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
 }
 
+/*
+==============
+PF_vectorvectors
+
+Writes new values for v_forward, v_up, and v_right based on the given forward vector
+vectorvectors(vector, vector)
+==============
+*/
+void PF_vectorvectors (void)
+{
+       VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
+       VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
+}
+
 /*
 =================
 PF_setorigin
@@ -203,6 +222,7 @@ void PF_setorigin (void)
 
 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
 {
+       /*
        float   *angles;
        vec3_t  rmin, rmax;
        float   bounds[2][3];
@@ -210,11 +230,14 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
        float   a;
        vec3_t  base, transformed;
        int             i, j, k, l;
+       */
+       int             i;
        
        for (i=0 ; i<3 ; i++)
                if (min[i] > max[i])
                        PR_RunError ("backwards mins/maxs");
 
+       /*
        rotate = false;         // FIXME: implement rotation properly again
 
        if (!rotate)
@@ -271,7 +294,13 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
        VectorCopy (rmin, e->v.mins);
        VectorCopy (rmax, e->v.maxs);
        VectorSubtract (max, min, e->v.size);
+       */
        
+// set derived values
+       VectorCopy (min, e->v.mins);
+       VectorCopy (max, e->v.maxs);
+       VectorSubtract (max, min, e->v.size);
+
        SV_LinkEdict (e, false);
 }
 
@@ -280,6 +309,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
 PF_setsize
 
 the size box is rotated by the current angle
+LordHavoc: no it isn't...
 
 setsize (entity, minvector, maxvector)
 =================
@@ -528,11 +558,19 @@ void PF_vectoangles (void)
        }
        else
        {
-               yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
-               if (yaw < 0)
-                       yaw += 360;
+               // LordHavoc: optimized a bit
+               if (value1[0])
+               {
+                       yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
+                       if (yaw < 0)
+                               yaw += 360;
+               }
+               else if (value1[1] > 0)
+                       yaw = 90;
+               else
+                       yaw = 270;
 
-               forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
+               forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
                pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
                if (pitch < 0)
                        pitch += 360;
@@ -633,7 +671,7 @@ Each entity can have eight independant sound sources, like voice,
 weapon, feet, etc.
 
 Channel 0 is an auto-allocate channel, the others override anything
-allready running on that entity/channel pair.
+already running on that entity/channel pair.
 
 An attenuation of 0 will play full volume everywhere in the level.
 Larger attenuations will drop off.
@@ -675,9 +713,9 @@ break()
 */
 void PF_break (void)
 {
-Con_Printf ("break statement\n");
-*(int *)-4 = 0;        // dump to debugger
-//     PR_RunError ("break statement");
+//     Con_Printf ("break statement\n");
+//     *(int *)-4 = 0; // dump to debugger
+       PR_RunError ("break statement");
 }
 
 /*
@@ -864,7 +902,7 @@ PF_checkclient
 Returns a client (or object that has a client enemy) that would be a
 valid target.
 
-If there are more than one valid options, they are cycled each frame
+If there is more than one valid option, they are cycled each frame
 
 If (self.origin + self.viewofs) is not in the PVS of the current target,
 it is not returned at all.
@@ -872,7 +910,6 @@ it is not returned at all.
 name checkclient ()
 =================
 */
-#define        MAX_CHECK       16
 int c_invis, c_notvis;
 void PF_checkclient (void)
 {
@@ -1108,8 +1145,11 @@ void PF_Find (void)
        e = G_EDICTNUM(OFS_PARM0);
        f = G_INT(OFS_PARM1);
        s = G_STRING(OFS_PARM2);
-       if (!s)
-               PR_RunError ("PF_Find: bad search string");
+       if (!s || !s[0])
+       {
+               RETURN_EDICT(sv.edicts);
+               return;
+       }
                
        for (e++ ; e < sv.num_edicts ; e++)
        {
@@ -1156,6 +1196,72 @@ void PF_FindFloat (void)
        RETURN_EDICT(sv.edicts);
 }
 
+// chained search for strings in entity fields
+// entity(.string field, string match) findchain = #402;
+void PF_findchain (void)
+{
+       int             i;      
+       int             f;
+       char    *s, *t;
+       edict_t *ent, *chain;
+
+       chain = (edict_t *)sv.edicts;
+
+       f = G_INT(OFS_PARM0);
+       s = G_STRING(OFS_PARM1);
+       if (!s || !s[0])
+       {
+               RETURN_EDICT(sv.edicts);
+               return;
+       }
+               
+       ent = NEXT_EDICT(sv.edicts);
+       for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
+       {
+               if (ent->free)
+                       continue;
+               t = E_STRING(ent,f);
+               if (!t)
+                       continue;
+               if (strcmp(t,s))
+                       continue;
+
+               ent->v.chain = EDICT_TO_PROG(chain);
+               chain = ent;
+       }
+
+       RETURN_EDICT(chain);
+}
+
+// LordHavoc: chained search for float, int, and entity reference fields
+// entity(.string field, float match) findchainfloat = #403;
+void PF_findchainfloat (void)
+{
+       int             i;      
+       int             f;
+       float   s;
+       edict_t *ent, *chain;
+
+       chain = (edict_t *)sv.edicts;
+
+       f = G_INT(OFS_PARM0);
+       s = G_FLOAT(OFS_PARM1);
+               
+       ent = NEXT_EDICT(sv.edicts);
+       for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
+       {
+               if (ent->free)
+                       continue;
+               if (E_FLOAT(ent,f) != s)
+                       continue;
+
+               ent->v.chain = EDICT_TO_PROG(chain);
+               chain = ent;
+       }
+
+       RETURN_EDICT(chain);
+}
+
 void PR_CheckEmptyString (char *s)
 {
        if (s[0] <= ' ')
@@ -1192,7 +1298,7 @@ void PF_precache_sound (void)
        PR_RunError ("PF_precache_sound: overflow");
 }
 
-int blahblah = 0;
+extern qboolean hlbsp;
 void PF_precache_model (void)
 {
        char    *s;
@@ -1202,6 +1308,8 @@ void PF_precache_model (void)
                PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
                
        s = G_STRING(OFS_PARM0);
+       if (hlbsp && ((!s) || (!s[0])))
+               return;
        G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
        PR_CheckEmptyString (s);
 
@@ -1210,11 +1318,7 @@ void PF_precache_model (void)
                if (!sv.model_precache[i])
                {
                        sv.model_precache[i] = s;
-                       if (sv.active < 0)
-                               blahblah++;
                        sv.models[i] = Mod_ForName (s, true);
-                       if (sv.active < 0)
-                               blahblah++;
                        return;
                }
                if (!strcmp(sv.model_precache[i], s))
@@ -1699,9 +1803,17 @@ void PF_makestatic (void)
        
        ent = G_EDICT(OFS_PARM0);
 
-       MSG_WriteByte (&sv.signon,svc_spawnstatic);
-
-       MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
+       i = SV_ModelIndex(pr_strings + ent->v.model);
+       if (i >= 256)
+       {
+               MSG_WriteByte (&sv.signon,svc_spawnstatic2);
+               MSG_WriteShort (&sv.signon, i);
+       }
+       else
+       {
+               MSG_WriteByte (&sv.signon,svc_spawnstatic);
+               MSG_WriteByte (&sv.signon, i);
+       }
 
        MSG_WriteByte (&sv.signon, ent->v.frame);
        MSG_WriteByte (&sv.signon, ent->v.colormap);
@@ -1829,7 +1941,7 @@ void PF_registercvar (void)
        name = G_STRING(OFS_PARM1);
        value = G_STRING(OFS_PARM2);
        G_FLOAT(OFS_RETURN) = 0;
-// first check to see if it has allready been defined
+// first check to see if it has already been defined
        if (Cvar_FindVar (name))
                return;
        
@@ -1988,6 +2100,405 @@ void PF_setcolor (void)
        MSG_WriteByte (&sv.reliable_datagram, i);
 }
 
+/*
+=================
+PF_effect
+
+effect(origin, modelname, startframe, framecount, framerate)
+=================
+*/
+void PF_effect (void)
+{
+       char *s;
+       s = G_STRING(OFS_PARM1);
+       if (!s || !s[0])
+               PR_RunError("effect: no model specified\n");
+
+       SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
+}
+
+void PF_te_blood (void)
+{
+       if (G_FLOAT(OFS_PARM2) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_BLOOD);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // velocity
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
+       // count
+       MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
+}
+
+void PF_te_bloodshower (void)
+{
+       if (G_FLOAT(OFS_PARM3) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
+       // min
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // max
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // speed
+       MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
+       // count
+       MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
+}
+
+void PF_te_explosionrgb (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // color
+       MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
+       MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
+       MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
+}
+
+void PF_te_particlecube (void)
+{
+       if (G_FLOAT(OFS_PARM3) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
+       // min
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // max
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // velocity
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       // count
+       MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
+       // color
+       MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
+       // gravity true/false
+       MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
+       // randomvel
+       MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
+}
+
+void PF_te_particlerain (void)
+{
+       if (G_FLOAT(OFS_PARM3) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
+       // min
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // max
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // velocity
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       // count
+       MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
+       // color
+       MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
+}
+
+void PF_te_particlesnow (void)
+{
+       if (G_FLOAT(OFS_PARM3) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
+       // min
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // max
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // velocity
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+       // count
+       MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
+       // color
+       MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
+}
+
+void PF_te_spark (void)
+{
+       if (G_FLOAT(OFS_PARM2) < 1)
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SPARK);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // velocity
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
+       MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
+       // count
+       MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
+}
+
+void PF_te_gunshotquad (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_spikequad (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_superspikequad (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_explosionquad (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_smallflash (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_customflash (void)
+{
+       if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
+               return;
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // radius
+       MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
+       // lifetime
+       MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
+       // color
+       MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
+       MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
+       MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
+}
+
+void PF_te_gunshot (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_spike (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SPIKE);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_superspike (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_explosion (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_tarexplosion (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_wizspike (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_knightspike (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_lavasplash (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_teleport (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_TELEPORT);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+}
+
+void PF_te_explosion2 (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
+       // origin
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
+       // color
+       MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
+}
+
+void PF_te_lightning1 (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
+       // owner entity
+       MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
+       // start
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // end
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+}
+
+void PF_te_lightning2 (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
+       // owner entity
+       MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
+       // start
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // end
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+}
+
+void PF_te_lightning3 (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
+       // owner entity
+       MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
+       // start
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // end
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+}
+
+void PF_te_beam (void)
+{
+       MSG_WriteByte(&sv.datagram, svc_temp_entity);
+       MSG_WriteByte(&sv.datagram, TE_BEAM);
+       // owner entity
+       MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
+       // start
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
+       // end
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
+       MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
+}
+
 void PF_Fixme (void)
 {
        PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
@@ -2085,37 +2596,67 @@ PF_precache_file,
 
 PF_setspawnparms,
 
-PF_Fixme,                      // #79 LordHavoc: dunno who owns 79-89, so these are just padding
-PF_Fixme,                      // #80 
-PF_Fixme,                      // #81
-PF_Fixme,                      // #82
-PF_Fixme,                      // #83
-PF_Fixme,                      // #84
-PF_Fixme,                      // #85
-PF_Fixme,                      // #86
-PF_Fixme,                      // #87
-PF_Fixme,                      // #88
-PF_Fixme,                      // #89
-
-PF_tracebox,           // #90 LordHavoc builtin range (9x)
-PF_randomvec,          // #91
-PF_GetLight,           // #92
-PF_registercvar,       // #93
-PF_min,                                // #94
-PF_max,                                // #95
-PF_bound,                      // #96
-PF_pow,                                // #97
-PF_FindFloat,          // #98
-PF_checkextension,     // #99
+PF_Fixme,                              // #79 LordHavoc: dunno who owns 79-89, so these are just padding
+PF_Fixme,                              // #80 
+PF_Fixme,                              // #81
+PF_Fixme,                              // #82
+PF_Fixme,                              // #83
+PF_Fixme,                              // #84
+PF_Fixme,                              // #85
+PF_Fixme,                              // #86
+PF_Fixme,                              // #87
+PF_Fixme,                              // #88
+PF_Fixme,                              // #89
+
+PF_tracebox,                   // #90 LordHavoc builtin range (9x)
+PF_randomvec,                  // #91
+PF_GetLight,                   // #92
+PF_registercvar,               // #93
+PF_min,                                        // #94
+PF_max,                                        // #95
+PF_bound,                              // #96
+PF_pow,                                        // #97
+PF_FindFloat,                  // #98
+PF_checkextension,             // #99
 #define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme,
 #define aa a a a a a a a a a a
 aa // #200
 aa // #300
 aa // #400
-PF_copyentity,         // #400 LordHavoc: builtin range (4xx)
-PF_setcolor,           // #401
+PF_copyentity,                 // #400 LordHavoc: builtin range (4xx)
+PF_setcolor,                   // #401
+PF_findchain,                  // #402
+PF_findchainfloat,             // #403
+PF_effect,                             // #404
+PF_te_blood,                   // #405
+PF_te_bloodshower,             // #406
+PF_te_explosionrgb,            // #407
+PF_te_particlecube,            // #408
+PF_te_particlerain,            // #409
+PF_te_particlesnow,            // #410
+PF_te_spark,                   // #411
+PF_te_gunshotquad,             // #412
+PF_te_spikequad,               // #413
+PF_te_superspikequad,  // #414
+PF_te_explosionquad,   // #415
+PF_te_smallflash,              // #416
+PF_te_customflash,             // #417
+PF_te_gunshot,                 // #418
+PF_te_spike,                   // #419
+PF_te_superspike,              // #420
+PF_te_explosion,               // #421
+PF_te_tarexplosion,            // #422
+PF_te_wizspike,                        // #423
+PF_te_knightspike,             // #424
+PF_te_lavasplash,              // #425
+PF_te_teleport,                        // #426
+PF_te_explosion2,              // #427
+PF_te_lightning1,              // #428
+PF_te_lightning2,              // #429
+PF_te_lightning3,              // #430
+PF_te_beam,                            // #431
+PF_vectorvectors,              // #432
 };
 
 builtin_t *pr_builtins = pr_builtin;
 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
-
index 0488c176a985883d2bf0ed856974e2e8692c1ee7..1ef5b19a0cbcc93b8bdba1351373d26e681a8313 100644 (file)
@@ -39,6 +39,7 @@ int           type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *
 ddef_t *ED_FieldAtOfs (int ofs);
 qboolean       ED_ParseEpair (void *base, ddef_t *key, char *s);
 
+cvar_t pr_checkextension = {"pr_checkextension", "1"};
 cvar_t nomonsters = {"nomonsters", "0"};
 cvar_t gamecfg = {"gamecfg", "0"};
 cvar_t scratch1 = {"scratch1", "0"};
@@ -111,6 +112,7 @@ int eval_colormod;
 int eval_ping;
 int eval_movement;
 int eval_pmodel;
+int eval_punchvector;
 
 dfunction_t *SV_PlayerPhysicsQC;
 dfunction_t *EndFrameQC;
@@ -158,6 +160,7 @@ void FindEdictFieldOffsets()
        eval_ping = FindFieldOffset("ping");
        eval_movement = FindFieldOffset("movement");
        eval_pmodel = FindFieldOffset("pmodel");
+       eval_punchvector = FindFieldOffset("punchvector");
 
        // LordHavoc: allowing QuakeC to override the player movement code
        SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics");
@@ -1288,6 +1291,7 @@ void PR_Init (void)
        Cmd_AddCommand ("edicts", ED_PrintEdicts);
        Cmd_AddCommand ("edictcount", ED_Count);
        Cmd_AddCommand ("profile", PR_Profile_f);
+       Cvar_RegisterVariable (&pr_checkextension);
        Cvar_RegisterVariable (&nomonsters);
        Cvar_RegisterVariable (&gamecfg);
        Cvar_RegisterVariable (&scratch1);
diff --git a/progs.h b/progs.h
index 278447b2e6e1c0ebd6ccc6d3bffdd3a9412f3e9e..4d4ce0ad18fa008edb27a86e28d1051d6a604b2b 100644 (file)
--- a/progs.h
+++ b/progs.h
@@ -89,6 +89,7 @@ extern int eval_colormod;
 extern int eval_ping;
 extern int eval_movement;
 extern int eval_pmodel;
+extern int eval_punchvector;
 
 #define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t*)((char*)&ed->v + fieldoffset) : NULL)
 
index 6de7bcb7f99e330b01dc7524de0c6ab2d0f57284..edad508ffd36e0b9a551710a8c16869aa80dc09a 100644 (file)
@@ -44,6 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // effects/model (can be used as model flags or entity effects)
 #define        EF_REFLECTIVE                   256             // LordHavoc: shiny metal objects :)
 #define EF_FULLBRIGHT                  512             // LordHavoc: fullbright
+#define EF_FLAME                               1024    // LordHavoc: on fire
 
 // if the high bit of the servercmd is set, the low bits are fast update flags:
 #define        U_MOREBITS      (1<<0)
@@ -81,7 +82,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define U_GLOWTRAIL    (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize)
 #define U_VIEWMODEL    (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such
 #define U_FRAME2       (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte)
-#define U_UNUSED27     (1<<27) // future expansion
+#define U_MODEL2       (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte)
 #define U_UNUSED28     (1<<28) // future expansion
 #define U_UNUSED29     (1<<29) // future expansion
 #define U_UNUSED30     (1<<30) // future expansion
@@ -102,6 +103,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define        SU_WEAPONFRAME  (1<<12)
 #define        SU_ARMOR                (1<<13)
 #define        SU_WEAPON               (1<<14)
+#define SU_EXTEND1             (1<<15)
+// first extend byte
+#define SU_PUNCHVEC1   (1<<16)
+#define SU_PUNCHVEC2   (1<<17)
+#define SU_PUNCHVEC3   (1<<18)
+#define SU_UNUSED19            (1<<19)
+#define SU_UNUSED20            (1<<20)
+#define SU_UNUSED21            (1<<21)
+#define SU_UNUSED22            (1<<22)
+#define SU_EXTEND2             (1<<23) // another byte to follow, future expansion
+// second extend byte
+#define SU_UNUSED24            (1<<24)
+#define SU_UNUSED25            (1<<25)
+#define SU_UNUSED26            (1<<26)
+#define SU_UNUSED27            (1<<27)
+#define SU_UNUSED28            (1<<28)
+#define SU_UNUSED29            (1<<29)
+#define SU_UNUSED30            (1<<30)
+#define SU_EXTEND3             (1<<31) // another byte to follow, future expansion
 
 // a sound with no channel is a local only sound
 #define        SND_VOLUME              (1<<0)          // a byte
@@ -176,13 +196,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define svc_cutscene           34
 
-#define        svc_showlmp                     35              // [string] slotname [string] lmpfilename [coord] x [coord] y
+#define        svc_showlmp                     35              // [string] slotname [string] lmpfilename [short] x [short] y
 #define        svc_hidelmp                     36              // [string] slotname
-#define        svc_skybox                      37              // [string] skyname
 
-#define svc_farclip                    50              // [coord] size (default is 6144)
-#define svc_fog                                51              // [byte] enable <optional past this point, only included if enable is true> [short] density*4096 [byte] red [byte] green [byte] blue
-//#define svc_playerposition   52              // only used in dpprotocol mode
+#define svc_unused1
+#define svc_fog                                51              // unfinished
+#define svc_effect                     52              // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
+#define svc_effect2                    53              // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
+#define        svc_sound2                      54              // short soundindex instead of byte
+#define        svc_spawnbaseline2      55              // short modelindex instead of byte
+#define svc_spawnstatic2       56              // short modelindex instead of byte
 
 //
 // client to server
@@ -232,4 +255,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define TE_SUPERSPIKEQUAD      59 // [vector] origin
 // LordHavoc: block2 - 70-80
 #define TE_EXPLOSIONQUAD       70 // [vector] origin
-#define        TE_BLOOD2                       71 // [vector] origin
\ No newline at end of file
+#define        TE_BLOOD2                       71 // [vector] origin
+#define TE_SMALLFLASH          72 // [vector] origin
+#define TE_CUSTOMFLASH         73 // [vector] origin [byte] radius / 8 - 1 [byte] lifetime / 256 - 1 [byte] red [byte] green [byte] blue
+#define TE_FLAMEJET                    74 // [vector] origin [vector] velocity [byte] count
index 3aee507574eff07f720c5d0faef432655bfc54c3..0232c8f39e716b8d128cd9ecad9d9b68e93ebfef 100644 (file)
@@ -64,8 +64,8 @@ extern int buildnumber;
 #define        ROLL    2
 
 
-#define        MAX_QPATH               64                      // max length of a quake game pathname
-#define        MAX_OSPATH              128                     // max length of a filesystem pathname
+#define        MAX_QPATH               128                     // max length of a quake game pathname
+#define        MAX_OSPATH              1024            // max length of a filesystem pathname
 
 #define        ON_EPSILON              0.1                     // point on plane side epsilon
 
@@ -79,8 +79,9 @@ extern int buildnumber;
 // LordHavoc: increased entity limit to 2048 from 600
 #define        MAX_EDICTS              2048            // FIXME: ouch! ouch! ouch!
 #define        MAX_LIGHTSTYLES 64
-#define        MAX_MODELS              256                     // these are sent over the net as bytes
-#define        MAX_SOUNDS              256                     // so they cannot be blindly increased
+// LordHavoc: increased model and sound limits from 256 and 256 to 1024 and 1024 (and added protocol extensions accordingly)
+#define        MAX_MODELS              1024                    // these are sent over the net as bytes
+#define        MAX_SOUNDS              1024                    // so they cannot be blindly increased
 
 #define        SAVEGAME_COMMENT_LENGTH 39
 
@@ -204,6 +205,8 @@ typedef struct
 } entity_state_t;
 
 
+#include "r_textures.h"
+
 #include "wad.h"
 #include "draw.h"
 #include "cvar.h"
@@ -271,8 +274,6 @@ extern      int                     host_framecount;        // incremented every frame, never reset
 extern double          realtime;                       // not bounded in any way, changed at
                                                                                // start of every frame, never reset
 
-extern double          sv_frametime;
-
 void Host_ClearMemory (void);
 void Host_ServerFrame (void);
 void Host_InitCommands (void);
index 5416a693c05c42b3cff473651f6761d66fc837f4..c6a2b81c681ddb172aa4a4fc7de91674d64dacdd 100644 (file)
@@ -7,7 +7,7 @@ cvar_t crosshair_flashrange = {"crosshair_flashrange", "0.1", true};
 
 #define NUMCROSSHAIRS 5
 
-int crosshairtex[NUMCROSSHAIRS];
+rtexture_t *crosshairtex[NUMCROSSHAIRS];
 
 byte *crosshairtexdata[NUMCROSSHAIRS] =
 {
@@ -106,7 +106,7 @@ void crosshairload(int num, byte *in)
                data[i][0] = data[i][1] = data[i][2] = 255;
                data[i][3] = (in[i] - '0') * 255 / 7;
        }
-       crosshairtex[num] = GL_LoadTexture(va("crosshair%02d", num), 16, 16, &data[0][0], false, true, 4);
+       crosshairtex[num] = R_LoadTexture(va("crosshair%02d", num), 16, 16, &data[0][0], TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
 void r_crosshairs_start()
index bff9f5cff00be67a2bd96f84aed097129ba9f9e0..a69d4fe2c3334798e0e6c18b057ffe5de9b18458 100644 (file)
@@ -23,12 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
 
 #define MAX_EXPLOSIONS 64
-#define EXPLOSIONBANDS 16
-#define EXPLOSIONSEGMENTS 16
-#define EXPLOSIONVERTS ((EXPLOSIONBANDS+1)*(EXPLOSIONSEGMENTS+1))
+#define EXPLOSIONGRID 16
+#define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1))
 #define EXPLOSIONTRIS (EXPLOSIONVERTS*2)
 #define EXPLOSIONSTARTRADIUS (0.0f)
-#define EXPLOSIONSTARTVELOCITY (400.0f)
+#define EXPLOSIONSTARTVELOCITY (500.0f)
 #define EXPLOSIONFADESTART (1.5f)
 #define EXPLOSIONFADERATE (6.0f)
 
@@ -36,10 +35,12 @@ vec3_t explosionspherevert[EXPLOSIONVERTS];
 vec3_t explosionspherevertvel[EXPLOSIONVERTS];
 float explosiontexcoords[EXPLOSIONVERTS][2];
 int explosiontris[EXPLOSIONTRIS][3];
+int explosionnoiseindex[EXPLOSIONVERTS];
 vec3_t explosionpoint[EXPLOSIONVERTS];
 
 typedef struct explosion_s
 {
+       float starttime;
        float alpha;
        vec3_t vert[EXPLOSIONVERTS];
        vec3_t vertvel[EXPLOSIONVERTS];
@@ -48,8 +49,8 @@ explosion_t;
 
 explosion_t explosion[128];
 
-int            explosiontexture;
-int            explosiontexturefog;
+rtexture_t     *explosiontexture;
+rtexture_t     *explosiontexturefog;
 
 cvar_t r_explosionclip = {"r_explosionclip", "0"};
 
@@ -57,15 +58,16 @@ int R_ExplosionVert(int column, int row)
 {
        int i;
        float a, b, c;
-       i = row * (EXPLOSIONSEGMENTS + 1) + column;
-       a = row * M_PI * 2 / EXPLOSIONBANDS;
-       b = column * M_PI * 2 / EXPLOSIONSEGMENTS;
+       i = row * (EXPLOSIONGRID + 1) + column;
+       a = row * M_PI * 2 / EXPLOSIONGRID;
+       b = column * M_PI * 2 / EXPLOSIONGRID;
        c = cos(b);
        explosionpoint[i][0] = cos(a) * c;
        explosionpoint[i][1] = sin(a) * c;
        explosionpoint[i][2] = -sin(b);
-       explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONSEGMENTS;
-       explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONBANDS;
+       explosionnoiseindex[i] = (row & (EXPLOSIONGRID - 1)) * EXPLOSIONGRID + (column & (EXPLOSIONGRID - 1));
+       explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONGRID;
+       explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONGRID;
        return i;
 }
 
@@ -73,8 +75,8 @@ void r_explosion_start()
 {
        int x, y;
        byte noise1[128][128], noise2[128][128], data[128][128][4];
-       fractalnoise(&noise1[0][0], 128, 8);
-       fractalnoise(&noise2[0][0], 128, 8);
+       fractalnoise(&noise1[0][0], 128, 2);
+       fractalnoise(&noise2[0][0], 128, 2);
        for (y = 0;y < 128;y++)
        {
                for (x = 0;x < 128;x++)
@@ -91,11 +93,11 @@ void r_explosion_start()
                        data[y][x][3] = bound(0, a, 255);
                }
        }
-       explosiontexture = GL_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], true, true, 4);
+       explosiontexture = R_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        for (y = 0;y < 128;y++)
                for (x = 0;x < 128;x++)
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
-       explosiontexturefog = GL_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], true, true, 4);
+       explosiontexturefog = R_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
 void r_explosion_shutdown()
@@ -106,9 +108,9 @@ void R_Explosion_Init()
 {
        int i, x, y;
        i = 0;
-       for (y = 0;y < EXPLOSIONBANDS;y++)
+       for (y = 0;y < EXPLOSIONGRID;y++)
        {
-               for (x = 0;x < EXPLOSIONSEGMENTS;x++)
+               for (x = 0;x < EXPLOSIONGRID;x++)
                {
                        explosiontris[i][0] = R_ExplosionVert(x    , y    );
                        explosiontris[i][1] = R_ExplosionVert(x + 1, y    );
@@ -138,6 +140,9 @@ void R_Explosion_Init()
 void R_NewExplosion(vec3_t org)
 {
        int i, j;
+       float dist;
+       byte noise[EXPLOSIONGRID*EXPLOSIONGRID];
+       fractalnoise(noise, EXPLOSIONGRID, 2);
        for (i = 0;i < MAX_EXPLOSIONS;i++)
        {
                if (explosion[i].alpha <= 0.0f)
@@ -145,12 +150,13 @@ void R_NewExplosion(vec3_t org)
                        explosion[i].alpha = EXPLOSIONFADESTART;
                        for (j = 0;j < EXPLOSIONVERTS;j++)
                        {
-                               explosion[i].vert[j][0] = explosionspherevert[j][0] + org[0];
-                               explosion[i].vert[j][1] = explosionspherevert[j][1] + org[1];
-                               explosion[i].vert[j][2] = explosionspherevert[j][2] + org[2];
-                               explosion[i].vertvel[j][0] = explosionspherevertvel[j][0];
-                               explosion[i].vertvel[j][1] = explosionspherevertvel[j][1];
-                               explosion[i].vertvel[j][2] = explosionspherevertvel[j][2];
+                               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;
                        }
                        break;
                }
@@ -159,40 +165,32 @@ void R_NewExplosion(vec3_t org)
 
 void R_DrawExplosion(explosion_t *e)
 {
-       int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 255.0f, 255);
-       float s = cl.time * 1, t = cl.time * 0.75;
-       s -= (int) s;
-       t -= (int) t;
+       int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 128.0f, 128), texnum, fogtexnum;
+       float s, t;
+//     s = cl.time * 1;
+//     t = cl.time * 0.75;
+//     s -= (int) s;
+//     t -= (int) t;
+       s = 0;
+       t = 0;
        /*
        glColor4f(1,1,1,e->alpha);
        glDisable(GL_TEXTURE_2D);
 //     glBindTexture(GL_TEXTURE_2D, explosiontexture);
-       if (gl_vertexarrays.value)
-       {
-               qglVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]);
-//             qglTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]);
-               glEnableClientState(GL_VERTEX_ARRAY);
-//             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-               qglDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist);
-//             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-               glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
-       {
-               glBegin(GL_TRIANGLES);
-               for (i = 0;i < EXPLOSIONTRIS * 3;i++)
-               {
-                       index = *indexlist++;
-//                     glTexCoord2fv(explosiontexcoords[index]);
-                       glVertex3fv(e->vert[index]);
-               }
-               glEnd();
-       }
+       glVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]);
+//     glTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]);
+       glEnableClientState(GL_VERTEX_ARRAY);
+//     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist);
+//     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+       glDisableClientState(GL_VERTEX_ARRAY);
        glEnable(GL_TEXTURE_2D);
        */
+       texnum = R_GetTexture(explosiontexture);
+       fogtexnum = R_GetTexture(explosiontexturefog);
        for (i = 0;i < EXPLOSIONTRIS;i++)
        {
-               transpolybegin(explosiontexture, 0, explosiontexturefog, TPOLYTYPE_ALPHA);
+               transpolybegin(texnum, 0, fogtexnum, TPOLYTYPE_ALPHA);
                index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
                index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
                index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha);
@@ -244,6 +242,11 @@ void R_MoveExplosions()
        {
                if (explosion[i].alpha > 0.0f)
                {
+                       if (explosion[i].starttime > cl.time)
+                       {
+                               explosion[i].alpha = 0;
+                               continue;
+                       }
                        R_MoveExplosion(&explosion[i], frametime);
                }
        }
diff --git a/r_lerpanim.c b/r_lerpanim.c
new file mode 100644 (file)
index 0000000..7ac1c62
--- /dev/null
@@ -0,0 +1,183 @@
+
+#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)
+{
+       int sub1, sub2, numframes, f, i, data;
+       double sublerp, lerp, l;
+       animscene_t *scene, *scenes;
+
+       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;
+
+       if ((frame1 >= numframes))
+       {
+               Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1);
+               frame1 = 0;
+       }
+
+       if ((frame2 >= numframes))
+       {
+               Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2);
+               frame2 = 0;
+       }
+
+       if (frame1 < 0)
+               Host_Error ("R_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;
+
+       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)
+       {
+               scene = scenes + frame1;
+               lerp = 1 - 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;
+                       }
+                       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 = sub2;
+                       l = sublerp * lerp;
+               }
+               else
+               {
+                       f = scene->firstframe;
+                       l = 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;
+                               }
+                       }
+               }
+       }
+       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;
+                       }
+                       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 = sub2;
+                       l = sublerp * lerp;
+               }
+               else
+               {
+                       f = scene->firstframe;
+                       l = 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;
+                               }
+                       }
+               }
+       }
+}
diff --git a/r_lerpanim.h b/r_lerpanim.h
new file mode 100644 (file)
index 0000000..83eec6f
--- /dev/null
@@ -0,0 +1,9 @@
+
+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);
index b71ce66acb482aeb6945ac2f4c19ccc6f42c1851..39cde86d07df028f448a88452603ea3c70aadaf3 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -22,7 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 
 cvar_t r_lightmodels = {"r_lightmodels", "1"};
-cvar_t r_modelsdonttransformnormals = {"r_modelsdonttransformnormals", "0"};
+
+extern cvar_t gl_transform;
 
 void r_light_start()
 {
@@ -35,7 +36,6 @@ void r_light_shutdown()
 void R_Light_Init()
 {
        Cvar_RegisterVariable(&r_lightmodels);
-       Cvar_RegisterVariable(&r_modelsdonttransformnormals);
        R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
 }
 
@@ -91,7 +91,7 @@ void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                return;
 
        // for comparisons to minimum acceptable light
-       maxdist = light->radius * light->radius * LIGHTSCALE;
+       maxdist = light->radius * light->radius;
 
        // clamp radius to avoid exceeding 32768 entry division table
        if (maxdist > 4194304)
@@ -139,7 +139,7 @@ loc0:
                if (surf->flags & SURF_PLANEBACK)
                        dist = -dist;
 
-               if (dist < -0.25f)
+               if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
                        continue;
 
                dist2 = dist * dist;
@@ -256,7 +256,9 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                int             row = (model->numleafs+7)>>3;
                float   low[3], high[3], radius, dist, maxdist;
 
-               radius = light->radius * LIGHTSCALE1;
+               lightframe++;
+
+               radius = light->radius * 2;
 
                // clamp radius to avoid exceeding 32768 entry division table
                if (radius > 2048)
@@ -268,7 +270,6 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                // for comparisons to minimum acceptable light
                maxdist = radius*radius;
 
-               lightframe++;
                k = 0;
                while (k < row)
                {
@@ -312,7 +313,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                                if (surf->flags & SURF_PLANEBACK)
                                                                        dist = -dist;
                                                                // LordHavoc: make sure it is infront of the surface and not too far away
-                                                               if (dist >= -0.25f && dist < radius)
+                                                               if ((dist >= -0.25f || (surf->flags & SURF_LIGHTBOTHSIDES)) && dist < radius)
                                                                {
                                                                        int d;
                                                                        float dist2, impact[3];
@@ -666,19 +667,6 @@ loc0:
        }
 }
 
-void R_LightPoint (vec3_t color, vec3_t p)
-{
-       if (r_fullbright.value || !cl.worldmodel->lightdata)
-       {
-               color[0] = color[1] = color[2] = 255;
-               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);
-}
-
-// LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting
 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
 {
        int             i, j, k;
@@ -694,15 +682,17 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
                {
                        for (i=0 ; i<32 ; i++)
                        {
-                               if ((!((1 << (i&31)) & dlightbits[i>>5])) || cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
+                               if (!((1 << i) & dlightbits[j]))
                                        continue;
                                k = (j<<5)+i;
+                               if (cl_dlights[k].die < cl.time || !cl_dlights[k].radius)
+                                       continue;
                                VectorSubtract (org, cl_dlights[k].origin, dist);
                                f = DotProduct(dist, dist) + LIGHTOFFSET;
-                               r = cl_dlights[k].radius*cl_dlights[k].radius*LIGHTSCALE;
+                               r = cl_dlights[k].radius*cl_dlights[k].radius;
                                if (f < r)
                                {
-                                       brightness = r * (256.0f / LIGHTSCALE2) / f;
+                                       brightness = r * 128.0f / f;
                                        color[0] += brightness * cl_dlights[k].color[0];
                                        color[1] += brightness * cl_dlights[k].color[1];
                                        color[2] += brightness * cl_dlights[k].color[2];
@@ -712,7 +702,65 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
        }
 }
 
-// same as above but no bitmask to check
+void R_CompleteLightPoint (vec3_t color, vec3_t p)
+{
+       mleaf_t *leaf;
+       leaf = Mod_PointInLeaf(p, cl.worldmodel);
+       if (leaf->contents == CONTENTS_SOLID)
+       {
+               color[0] = color[1] = color[2] = 0;
+               return;
+       }
+
+       if (r_fullbright.value || !cl.worldmodel->lightdata)
+       {
+               color[0] = color[1] = color[2] = 255;
+               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);
+
+       R_DynamicLightPoint(color, p, leaf->dlightbits);
+}
+
+void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits)
+{
+       mleaf_t *leaf;
+       leaf = Mod_PointInLeaf(p, cl.worldmodel);
+       if (leaf->contents == CONTENTS_SOLID)
+       {
+               color[0] = color[1] = color[2] = 0;
+               dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
+               return;
+       }
+
+       if (r_fullbright.value || !cl.worldmodel->lightdata)
+       {
+               color[0] = color[1] = color[2] = 255;
+               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);
+
+       if (leaf->dlightframe == r_dlightframecount)
+       {
+               dlightbits[0] = leaf->dlightbits[0];
+               dlightbits[1] = leaf->dlightbits[1];
+               dlightbits[2] = leaf->dlightbits[2];
+               dlightbits[3] = leaf->dlightbits[3];
+               dlightbits[4] = leaf->dlightbits[4];
+               dlightbits[5] = leaf->dlightbits[5];
+               dlightbits[6] = leaf->dlightbits[6];
+               dlightbits[7] = leaf->dlightbits[7];
+       }
+       else
+               dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
+}
+
+/* // not currently used
 void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
 {
        int             i;
@@ -728,10 +776,10 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
                        continue;
                VectorSubtract (org, cl_dlights[i].origin, dist);
                f = DotProduct(dist, dist) + LIGHTOFFSET;
-               r = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
+               r = cl_dlights[i].radius*cl_dlights[i].radius;
                if (f < r)
                {
-                       brightness = r * (256.0f / LIGHTSCALE2) / f;
+                       brightness = r * 256.0f / f;
                        if (cl_dlights[i].dark)
                                brightness = -brightness;
                        color[0] += brightness * cl_dlights[i].color[0];
@@ -740,19 +788,12 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
                }
        }
 }
-
-void R_CompleteLightPoint (vec3_t color, vec3_t p)
-{
-       R_LightPoint(color, p);
-       R_DynamicLightPointNoMask(color, p);
-}
+*/
 
 extern float *aliasvert;
-extern float *modelaliasvert;
 extern float *aliasvertnorm;
 extern byte *aliasvertcolor;
 extern float modelalpha;
-extern int modeldlightbits[8];
 void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
 {
        // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
@@ -765,31 +806,10 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                vec3_t color;
                vec3_t origin;
        } nearlight[MAX_DLIGHTS];
+       int modeldlightbits[8];
        avc = aliasvertcolor;
        avn = aliasvertnorm;
        a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
-       if (currententity->effects & EF_FULLBRIGHT)
-       {
-               if (lighthalf)
-               {
-                       ((byte *)&color)[0] = (byte) ((float) (128.0f * currententity->colormod[0]));
-                       ((byte *)&color)[1] = (byte) ((float) (128.0f * currententity->colormod[1]));
-                       ((byte *)&color)[2] = (byte) ((float) (128.0f * currententity->colormod[2]));
-               }
-               else
-               {
-                       ((byte *)&color)[0] = (byte) ((float) (255.0f * currententity->colormod[0]));
-                       ((byte *)&color)[1] = (byte) ((float) (255.0f * currententity->colormod[1]));
-                       ((byte *)&color)[2] = (byte) ((float) (255.0f * currententity->colormod[2]));
-               }
-               ((byte *)&color)[3] = a;
-               for (i = 0;i < numverts;i++)
-               {
-                       *((int *)avc) = color;
-                       avc += 4;
-               }
-               return;
-       }
        if (lighthalf)
        {
                mod[0] = currententity->colormod[0] * 0.5f;
@@ -802,37 +822,11 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                mod[1] = currententity->colormod[1];
                mod[2] = currententity->colormod[2];
        }
-       basecolor[0] *= mod[0];
-       basecolor[1] *= mod[1];
-       basecolor[2] *= mod[2];
-       if (!r_lightmodels.value)
+       if (currententity->effects & EF_FULLBRIGHT)
        {
-               for (i = 0;i < MAX_DLIGHTS;i++)
-               {
-                       if (!modeldlightbits[i >> 5])
-                       {
-                               i |= 31;
-                               continue;
-                       }
-                       if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
-                               continue;
-                       VectorSubtract (center, cl_dlights[i].origin, dist);
-                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
-                       t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + LIGHTOFFSET;
-                       if (t2 < t1)
-                       {
-                               dist[0] = cl_dlights[i].color[0] * t1 * mod[0];
-                               dist[1] = cl_dlights[i].color[1] * t1 * mod[1];
-                               dist[2] = cl_dlights[i].color[2] * t1 * mod[2];
-                               t1 = (224.0f / LIGHTSCALE / LIGHTSCALE) / t2;
-                               basecolor[0] += dist[0] * t1;
-                               basecolor[1] += dist[1] * t1;
-                               basecolor[2] += dist[2] * t1;
-                       }
-               }
-               ((byte *)&color)[0] = bound(0, basecolor[0], 255);
-               ((byte *)&color)[1] = bound(0, basecolor[1], 255);
-               ((byte *)&color)[2] = bound(0, basecolor[2], 255);
+               ((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++)
                {
@@ -841,36 +835,43 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                }
                return;
        }
-       else
+       R_ModelLightPoint(basecolor, center, modeldlightbits);
+
+       basecolor[0] *= mod[0];
+       basecolor[1] *= mod[1];
+       basecolor[2] *= mod[2];
+       for (i = 0;i < MAX_DLIGHTS;i++)
        {
-               for (i = 0;i < MAX_DLIGHTS;i++)
+               if (!modeldlightbits[i >> 5])
                {
-                       if (!modeldlightbits[i >> 5])
+                       i |= 31;
+                       continue;
+               }
+               if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
+                       continue;
+               VectorSubtract (center, cl_dlights[i].origin, dist);
+               t2 = DotProduct(dist,dist) + LIGHTOFFSET;
+               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
                        {
-                               i |= 31;
-                               continue;
+                               VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
                        }
-                       if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
-                               continue;
-                       VectorSubtract (center, cl_dlights[i].origin, dist);
-                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
-                       t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + LIGHTOFFSET;
-                       if (t2 < t1)
-                       {
-                               if (r_modelsdonttransformnormals.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];
-//                             t1 = (128.0f / LIGHTSCALE2) / t2;
-//                             basecolor[0] += nearlight[nearlights].color[0] * t1;
-//                             basecolor[1] += nearlight[nearlights].color[1] * t1;
-//                             basecolor[2] += nearlight[nearlights].color[2] * t1;
+                       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)
                                nearlights++;
+                       else
+                       {
+                               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;
                        }
                }
        }
@@ -886,10 +887,7 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                int temp;
                vec3_t v;
                float *av;
-               if (r_modelsdonttransformnormals.value)
-                       av = modelaliasvert;
-               else
-                       av = aliasvert;
+               av = aliasvert;
                if (nearlights == 1)
                {
                        for (i = 0;i < numverts;i++)
@@ -898,10 +896,13 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                                t = DotProduct(avn,v);
                                if (t > 0)
                                {
-                                       t /= DotProduct(v,v);
-                                       temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[0] = temp;
-                                       temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[1] = temp;
-                                       temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[2] = temp;
+                                       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;
                                }
                                else
@@ -913,31 +914,35 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                }
                else
                {
-                       int i1, i2, i3, k;
                        for (i = 0;i < numverts;i++)
                        {
+                               int lit;
                                t1 = basecolor[0];
                                t2 = basecolor[1];
                                t3 = basecolor[2];
-                               k = false;
+                               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);
+                                               t /= (DotProduct(v,v) + LIGHTOFFSET);
                                                t1 += nearlight[j].color[0] * t;
                                                t2 += nearlight[j].color[1] * t;
                                                t3 += nearlight[j].color[2] * t;
-                                               k = true;
+                                               lit = true;
                                        }
                                }
-                               if (k)
+                               if (lit)
                                {
-                                       i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;avc[0] = i1;
-                                       i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;avc[1] = i2;
-                                       i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;avc[2] = i3;
+                                       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
index 509fe6440c4c98be7d2ccec158c0973aa89c2614..4d7bcb551a66b9bbefddef7142f41fab750cba6b 100644 (file)
--- a/r_light.h
+++ b/r_light.h
@@ -13,9 +13,9 @@ typedef struct
 } dlight_t;
 
 // LordHavoc: this affects the lighting scale of the whole game
-//#define LIGHTOFFSET 16384.0f
-//#define LIGHTSCALE1 2.0f
 #define LIGHTOFFSET 4096.0f
-#define LIGHTSCALE1 1.0f
-#define LIGHTSCALE (LIGHTSCALE1*LIGHTSCALE1)
-#define LIGHTSCALE2 LIGHTSCALE
+
+extern void R_CompleteLightPoint (vec3_t color, vec3_t p);
+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);
index 59d875ee32140db99dcda6f5407bd8b14095f5d6..fa183696f382d3f50a71b9d9a4e4b9f7f37b5fef 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -20,13 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#define MAX_PARTICLES                  4096    // default max # of particles at one time
+#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_blob, pt_blob2, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_flamingdebris, pt_smokingdebris, pt_flamefall
+       pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_flamingdebris, pt_smokingdebris, pt_flamefall, pt_glow, pt_decal, pt_blood, pt_bloodsplatter
 }
 ptype_t;
 
@@ -38,12 +38,17 @@ typedef struct particle_s
        float           die;
        ptype_t         type;
        float           scale;
-       short           texnum;
-       short           dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
+       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            pad1;
+       byte            pad2;
        float           alpha; // 0-255
        float           time2; // used for various things (snow fluttering, for example)
+       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 of bouncing particles)
        vec3_t          oldorg;
        vec3_t          vel2; // used for snow fluttering (base velocity, wind for instance)
+       vec3_t          direction; // used by decals
 }
 particle_t;
 
@@ -53,12 +58,10 @@ 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};
 
-int            particletexture;
-int            smokeparticletexture[8];
-int            rainparticletexture;
-int            bubbleparticletexture;
-int            explosiontexture;
-int            explosiontexturefog;
+rtexture_t *particletexture;
+rtexture_t *smokeparticletexture[8];
+rtexture_t *rainparticletexture;
+rtexture_t *bubbleparticletexture;
 
 particle_t     *particles;
 int                    r_numparticles;
@@ -68,12 +71,6 @@ vec3_t                       r_pright, r_pup, r_ppn;
 int                    numparticles;
 particle_t     **freeparticles; // list used only in compacting particles array
 
-// LordHavoc: reduced duplicate code, and allow particle allocation system independence
-#define ALLOCPARTICLE(part) \
-       if (numparticles >= r_numparticles)\
-               return;\
-       (part) = &particles[numparticles++];
-
 cvar_t r_particles = {"r_particles", "1"};
 cvar_t r_drawparticles = {"r_drawparticles", "1"};
 cvar_t r_dynamicparticles = {"r_dynamicparticles", "1", true};
@@ -115,7 +112,7 @@ void R_InitParticleTexture (void)
 {
        int             x,y,d,i,m;
        float   dx, dy;
-       byte    data[32][32][4], noise1[128][128], noise2[128][128];
+       byte    data[32][32][4], noise1[64][64], noise2[64][64];
        vec3_t  light;
 
        for (y = 0;y < 32;y++)
@@ -130,14 +127,14 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       particletexture = GL_LoadTexture ("particletexture", 32, 32, &data[0][0][0], true, true, 4);
+       particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 
        for (i = 0;i < 8;i++)
        {
                do
                {
-                       fractalnoise(&noise1[0][0], 128, 8);
-                       fractalnoise(&noise2[0][0], 128, 16);
+                       fractalnoise(&noise1[0][0], 64, 4);
+                       fractalnoise(&noise2[0][0], 64, 8);
                        m = 0;
                        for (y = 0;y < 32;y++)
                        {
@@ -168,7 +165,7 @@ void R_InitParticleTexture (void)
                }
                while (m < 192);
 
-               smokeparticletexture[i] = GL_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], true, true, 4);
+               smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
        }
 
        light[0] = 1;light[1] = 1;light[2] = 1;
@@ -181,7 +178,7 @@ 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 = GL_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], true, true, 4);
+       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);
@@ -193,7 +190,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
                }
        }
-       bubbleparticletexture = GL_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], true, true, 4);
+       bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
 }
 
 void r_part_start()
@@ -243,59 +240,104 @@ void R_Particles_Init (void)
        R_RegisterModule("R_Particles", r_part_start, r_part_shutdown);
 }
 
-#define particle(ptype, pcolor, ptex, plight, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\
+//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)\
 {\
        particle_t      *part;\
-       ALLOCPARTICLE(part)\
+       if (numparticles >= r_numparticles)\
+               return;\
+       part = &particles[numparticles++];\
        part->type = (ptype);\
        part->color = (pcolor);\
-       part->texnum = (ptex);\
+       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, plight, pscale, palpha, ptime, pbase, poscale, pvscale)\
+#define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\
 {\
        particle_t      *part;\
-       ALLOCPARTICLE(part)\
+       if (numparticles >= r_numparticles)\
+               return;\
+       part = &particles[numparticles++];\
        part->type = (ptype);\
        part->color = (pcolor);\
-       part->texnum = (ptex);\
+       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, plight, pscale, palpha, ptime, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
+#define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
 {\
        particle_t      *part;\
-       ALLOCPARTICLE(part)\
+       if (numparticles >= r_numparticles)\
+               return;\
+       part = &particles[numparticles++];\
        part->type = (ptype);\
        part->color = (pcolor);\
-       part->texnum = (ptex);\
+       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);\
+       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 = (ptime2);\
+       part->vel2[0] = (pvx2);\
+       part->vel2[1] = (pvy2);\
+       part->vel2[2] = (pvz2);\
 }
 
 /*
@@ -303,27 +345,19 @@ void R_Particles_Init (void)
 R_EntityParticles
 ===============
 */
-
-#define NUMVERTEXNORMALS       162
-extern float   r_avertexnormals[NUMVERTEXNORMALS][3];
-vec3_t avelocities[NUMVERTEXNORMALS];
-float  beamlength = 16;
-vec3_t avelocity = {23, 7, 3};
-float  partstep = 0.01;
-float  timescale = 0.01;
-
 void R_EntityParticles (entity_t *ent)
 {
-       int                     count;
        int                     i;
        float           angle;
        float           sp, sy, cp, cy;
        vec3_t          forward;
        float           dist;
+       float           beamlength;
+       static vec3_t avelocities[NUMVERTEXNORMALS];
        if (!r_particles.value) return; // LordHavoc: particles are optional
        
        dist = 64;
-       count = 50;
+       beamlength = 16;
 
        if (!avelocities[0][0])
                for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
@@ -342,7 +376,7 @@ void R_EntityParticles (entity_t *ent)
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               particle(pt_static, 0x6f, particletexture, false, 2, 255, 0, ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
+               particle(pt_static, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 0, 0, ent->origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
        }
 }
 
@@ -397,7 +431,7 @@ void R_ReadPointFile_f (void)
                        Con_Printf ("Not enough free particles\n");
                        break;
                }
-               particle(pt_static, (-c)&15, particletexture, false, 2, 255, 99999, org[0], org[1], org[2], 0, 0, 0);
+               particle(pt_static, (-c)&15, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0);
        }
 
        fclose (f);
@@ -442,13 +476,13 @@ 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], true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
+//     particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
 
        i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
        if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
        {
                for (i=0 ; i<128 ; i++)
-                       particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, false, lhrandom(1, 2), 255, 2, org, 16, 96);
+                       particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 2, 1.5, org, 16, 96);
        }
        else
                R_NewExplosion(org);
@@ -459,15 +493,15 @@ void R_ParticleExplosion (vec3_t org, int smoke)
 //             int color;
                float f, forg[3], fvel[3], fvel2[3];
 //             for (i = 0;i < 256;i++)
-//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192);
+//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192);
 //             for (i = 0;i < 256;i++)
-//                     particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, org, 15, 150);
+//                     particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org, 15, 150);
                for (i = 0;i < 32;i++)
                {
                        fvel[0] = lhrandom(-150, 150);
                        fvel[1] = lhrandom(-150, 150);
                        fvel[2] = lhrandom(-150, 150) + 80;
-//                     particle(pt_flamefall, 106 + (rand()%6), particletexture, 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]);
+//                     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++)
                        {
                                forg[0] = lhrandom(-20, 20) + org[0];
@@ -480,15 +514,15 @@ void R_ParticleExplosion (vec3_t org, int smoke)
                                fvel2[0] *= f;
                                fvel2[1] *= f;
                                fvel2[2] *= f;
-                               particle(pt_flamefall, 106 + (rand()%6), particletexture, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]);
+                               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 (i = 0;i < 16;i++)
-//                     particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 20, 192, 99, org, 20, 0);
+//                     particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org, 20, 0);
 //             for (i = 0;i < 50;i++)
-//                     particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, false, 3, 255, 99, org, 10, 200);
+//                     particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org, 10, 200);
 //             for (i = 0;i < 30;i++)
-//                     particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, false, 2, 255, 99, org, 10, 100);
+//                     particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org, 10, 100);
        }
        */
 }
@@ -505,7 +539,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++)
-               particle2(pt_fade, colorStart + (i % colorLength), particletexture, false, 1.5, 255, 0.3, org, 8, 192);
+               particle2(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org, 8, 192);
 }
 
 /*
@@ -520,9 +554,9 @@ void R_BlobExplosion (vec3_t org)
        if (!r_particles.value) return; // LordHavoc: particles are optional
        
        for (i=0 ; i<512 ; i++)
-               particle3(pt_blob, 66+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
+               particle3(pt_blob, 66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128);
        for (i=0 ; i<512 ; i++)
-               particle3(pt_blob2, 150+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
+               particle3(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128);
 }
 
 /*
@@ -540,15 +574,8 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                R_ParticleExplosion(org, false);
                return;
        }
-       color &= ~7;
-       if (count & 7)
-       {
-               particle2(pt_fade, color + (rand()&7), particletexture, false, 6, (count & 7) * 16 + (rand()&15), 1, org, 8, 15);
-               count &= ~7;
-       }
-       count >>= 3;
        while (count--)
-               particle2(pt_fade, color + (rand()&7), particletexture, false, 6, 128, 1, org, 8, 15);
+               particle2(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 1, 0, org, 8, 15);
 }
 
 // LordHavoc: added this for spawning sparks/dust (which have strong gravity)
@@ -562,26 +589,27 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        // smoke puff
-       particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 8, 160, 99, org[0], org[1], org[2], 0, 0, 0);
+       particle(pt_bulletsmoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 1, 160, 99, 0, org[0], org[1], org[2], lhrandom(-4, 4), lhrandom(-4, 4), 16);
        // sparks
        while(count--)
-//             particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, org, 4, 96);
-               particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, lhrandom(-4, 4) + org[0], lhrandom(-4, 4) + org[1], lhrandom(-4, 4) + org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 64);
+               particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 1.5, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 128);
 }
 
-void R_BloodPuff (vec3_t org)
+void R_BloodPuff (vec3_t org, vec3_t vel, int count)
 {
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 12, 128, 99, org[0], org[1], org[2], 0, 0, 0);
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 10, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 8, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
+       if (count > 100)
+               count = 100;
+       while(count > 0)
+       {
+               particle(pt_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 20), min(count, 10) * 25 + 5, 99, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+               count -= 10;
+       }
 }
 
 void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
 {
-       int                     j;
-       particle_t      *p;
        vec3_t          diff;
        vec3_t          center;
        vec3_t          velscale;
@@ -592,73 +620,37 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        center[1] = (mins[1] + maxs[1]) * 0.5;
        center[2] = (mins[2] + maxs[2]) * 0.5;
        // FIXME: change velspeed back to 2.0x after fixing mod
-       velscale[0] = velspeed * 0.5 / diff[0];
-       velscale[1] = velspeed * 0.5 / diff[1];
-       velscale[2] = velspeed * 0.5 / diff[2];
+       velscale[0] = velspeed * 2.0 / diff[0];
+       velscale[1] = velspeed * 2.0 / diff[1];
+       velscale[2] = velspeed * 2.0 / diff[2];
        
        while (count--)
        {
-               ALLOCPARTICLE(p)
-
-               p->texnum = smokeparticletexture[rand()&7];
-               p->dynlight = true;
-               p->scale = lhrandom(4, 6);
-               p->alpha = 96 + (rand()&63);
-               p->die = cl.time + 2;
-               p->type = pt_bloodcloud;
-               p->color = 251; //(rand()&3)+68;
-               for (j=0 ; j<3 ; j++)
-               {
-                       p->org[j] = diff[j] * (float) (rand()%1024) * (1.0 / 1024.0) + mins[j];
-                       p->vel[j] = (p->org[j] - center[j]) * velscale[j];
-               }
+               vec3_t org, vel;
+               org[0] = lhrandom(mins[0], maxs[0]);
+               org[1] = lhrandom(mins[1], maxs[1]);
+               org[2] = lhrandom(mins[2], maxs[2]);
+               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_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 25), 255, 99, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]);
        }
 }
 
 void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel)
 {
-       int                     j;
-       particle_t      *p;
-       vec3_t          diff;
        float           t;
        if (!r_particles.value) return; // LordHavoc: particles are optional
        if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
        if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
-       VectorSubtract(maxs, mins, diff);
-       
        while (count--)
-       {
-               ALLOCPARTICLE(p)
-
-               p->texnum = particletexture;
-               p->dynlight = false;
-               p->scale = 6;
-               p->alpha = 255;
-               p->die = cl.time + 1 + (rand()&15)*0.0625;
-               if (gravity)
-                       p->type = pt_grav;
-               else
-                       p->type = pt_static;
-               p->color = colorbase + (rand()&3);
-               for (j=0 ; j<3 ; j++)
-               {
-                       p->org[j] = diff[j] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[j];
-                       if (randomvel)
-                               p->vel[j] = dir[j] + (rand()%randomvel)-(randomvel*0.5);
-                       else
-                               p->vel[j] = 0;
-               }
-       }
+               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));
 }
 
 void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type)
 {
-       int                     i;
-       particle_t      *p;
-       vec3_t          diff;
-       vec3_t          org;
        vec3_t          vel;
        float           t, z;
        if (!r_particles.value) return; // LordHavoc: particles are optional
@@ -677,44 +669,53 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        }
        if (t < 0 || t > 2) // sanity check
                t = 2;
-       t += cl.time;
 
-       VectorSubtract(maxs, mins, diff);
-       
-       for (i=0 ; i<count ; i++)
+       switch(type)
        {
-               ALLOCPARTICLE(p)
-
-               vel[0] = dir[0] + (rand()&31) - 16;
-               vel[1] = dir[1] + (rand()&31) - 16;
-               vel[2] = dir[2] + (rand()&63) - 32;
-               org[0] = diff[0] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[0];
-               org[1] = diff[1] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[1];
-               org[2] = z;
-
-               p->alpha = 255;
-               p->die = t;
-               if (type == 1)
+       case 0:
+               while(count--)
                {
-                       p->scale = 2;
-                       p->texnum = particletexture;
-                       p->dynlight = false;
-                       p->type = pt_snow;
+                       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]);
                }
-               else // 0
+               break;
+       case 1:
+               while(count--)
                {
-                       p->scale = 3;
-                       p->texnum = rainparticletexture;
-                       p->dynlight = true;
-                       p->type = pt_rain;
+                       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]);
                }
-               p->color = colorbase + (rand()&3);
-               VectorCopy(org, p->org);
-               VectorCopy(vel, p->vel);
-               VectorCopy(vel, p->vel2);
+               break;
+       default:
+               Host_Error("R_ParticleRain: unknown type %i (0 = rain, 1 = snow)\n", type);
        }
 }
 
+void R_FlameCube (vec3_t mins, vec3_t maxs, int count)
+{
+       float           t;
+       if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
+       if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
+       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, 1, lhrandom(64, 255), 5, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 48));
+}
+
+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, 1, lhrandom(64, 255), 5, 1.5, org[0], org[1], org[2], vel[0] + lhrandom(-16, 16), vel[1] + lhrandom(-16, 16), vel[2] + lhrandom(-16, 16));
+}
+
+
 
 /*
 ===============
@@ -722,39 +723,28 @@ R_LavaSplash
 
 ===============
 */
-void R_LavaSplash (vec3_t org)
+void R_LavaSplash (vec3_t origin)
 {
        int                     i, j;
-       particle_t      *p;
        float           vel;
-       vec3_t          dir;
+       vec3_t          dir, org;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       for (i=-128 ; i<128 ; i+=16)
-               for (j=-128 ; j<128 ; j+=16)
+       for (i=-128 ; i<128 ; i+=8)
+       {
+               for (j=-128 ; j<128 ; j+=8)
                {
-                       ALLOCPARTICLE(p)
-               
-                       p->texnum = particletexture;
-                       p->dynlight = false;
-                       p->scale = 10;
-                       p->alpha = 128;
-                       p->die = cl.time + 2 + (rand()&31) * 0.02;
-                       p->color = 224 + (rand()&7);
-                       p->type = pt_grav;
-                       
-                       dir[0] = j + (rand()&7);
-                       dir[1] = i + (rand()&7);
+                       dir[0] = j + lhrandom(0, 8);
+                       dir[1] = i + lhrandom(0, 8);
                        dir[2] = 256;
-
-                       p->org[0] = org[0] + dir[0];
-                       p->org[1] = org[1] + dir[1];
-                       p->org[2] = org[2] + (rand()&63);
-
-                       VectorNormalize (dir);                                          
-                       vel = 50 + (rand()&63);
-                       VectorScale (dir, vel, p->vel);
+                       org[0] = origin[0] + dir[0];
+                       org[1] = origin[1] + dir[1];
+                       org[2] = origin[2] + lhrandom(0, 64);
+                       vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
+                       particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel);
+//                     particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 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));
                }
+       }
 }
 
 /*
@@ -766,194 +756,143 @@ R_TeleportSplash
 void R_TeleportSplash (vec3_t org)
 {
        int                     i, j, k;
-       particle_t      *p;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i=-16 ; i<16 ; i+=8)
                for (j=-16 ; j<16 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
-                       {
-                               ALLOCPARTICLE(p)
-               
-                               p->texnum = particletexture;
-                               p->dynlight = false;
-                               p->scale = 1;
-                               p->alpha = lhrandom(32,128);
-                               p->die = cl.time + 5;
-                               p->color = 254;
-                               p->type = pt_fade;
-                               
-                               p->org[0] = org[0] + i + (rand()&7);
-                               p->org[1] = org[1] + j + (rand()&7);
-                               p->org[2] = org[2] + k + (rand()&7);
-       
-                               p->vel[0] = i*2 + (rand()%25) - 12;
-                               p->vel[1] = j*2 + (rand()%25) - 12;
-                               p->vel[2] = k*2 + (rand()%25) - 12 + 40;
-                       }
+                               particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 5, 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));
 }
 
 void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 {
-       vec3_t          vec;
-       float           len, dec = 0, t, nt, speed;
-       int                     j, contents, bubbles;
-       particle_t      *p;
+       vec3_t          vec, dir, vel;
+       float           len, dec = 0, speed;
+       int                     contents, bubbles, polytype;
+       double          t;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       t = cl.oldtime;
-       nt = cl.time;
-       if (ent->trail_leftover < 0)
-               ent->trail_leftover = 0;
-       t += ent->trail_leftover;
-       ent->trail_leftover -= (cl.time - cl.oldtime);
+       VectorSubtract(end, start, dir);
+       VectorNormalize(dir);
+
+       /*
+       if (type == 0) // rocket glow
+               particle(pt_glow, 254, particletexture, TPOLYTYPE_ADD, false, 10, 160, 999, 0, start[0] - 12 * dir[0], start[1] - 12 * dir[1], start[2] - 12 * dir[2], 0, 0, 0);
+       */
+
+       t = ent->trail_time;
        if (t >= cl.time)
-               return;
+               return; // no particles to spawn this frame (sparse trail)
 
-       contents = Mod_PointInLeaf(start, cl.worldmodel)->contents;
-       if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
-               return;
+       if (t < cl.oldtime)
+               t = cl.oldtime;
 
        VectorSubtract (end, start, vec);
        len = VectorNormalizeLength (vec);
        if (len <= 0.01f)
+       {
+               // advance the trail time
+               ent->trail_time = cl.time;
                return;
-       speed = len / (nt - t);
+       }
+       speed = len / (cl.time - cl.oldtime);
+       VectorScale(vec, speed, vel);
 
-       bubbles = (contents == CONTENTS_WATER || contents == CONTENTS_SLIME);
+       // advance into this frame to reach the first puff location
+       dec = t - cl.oldtime;
+       dec *= speed;
+       VectorMA(start, dec, vec, start);
 
-       while (t < nt)
+       contents = Mod_PointInLeaf(start, cl.worldmodel)->contents;
+       if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
        {
-               ALLOCPARTICLE(p)
-               
-               p->vel[0] = p->vel[1] = p->vel[2] = 0;
-               p->die = cl.time + 2;
+               // advance the trail time
+               ent->trail_time = cl.time;
+               return;
+       }
 
+       bubbles = (contents == CONTENTS_WATER || contents == CONTENTS_SLIME);
+
+       polytype = TPOLYTYPE_ALPHA;
+       if (ent->effects & EF_ADDITIVE)
+               polytype = TPOLYTYPE_ADD;
+
+       while (t < cl.time)
+       {
                switch (type)
                {
                        case 0: // rocket trail
-                       case 1: // grenade trail
                                if (bubbles)
                                {
-                                       dec = type == 0 ? 0.01f : 0.02f;
-                                       p->texnum = bubbleparticletexture;
-                                       p->dynlight = false;
-                                       p->scale = lhrandom(1,2);
-                                       p->alpha = 255;
-                                       p->color = 254;
-                                       p->type = pt_bubble;
-                                       p->die = cl.time + 2;
-                                       for (j=0 ; j<3 ; j++)
-                                       {
-                                               p->vel[j] = (rand()&31)-16;
-                                               p->org[j] = start[j] + ((rand()&3)-2);
-                                       }
+                                       dec = 0.01f;
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
                                }
                                else
                                {
-                                       dec = type == 0 ? 0.02f : 0.04f;
-                                       p->texnum = smokeparticletexture[rand()&7];
-                                       p->dynlight = true;
-                                       p->scale = lhrandom(4, 8);
-                                       p->alpha = 160; //128 + (rand()&63);
-                                       p->color = 254;
-                                       p->type = pt_smoke;
-                                       p->die = cl.time + 10000;
-                                       VectorCopy(start, p->org);
-                                       /*
+                                       dec = 0.01f;
+                                       particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16);
                                        if (type == 0)
                                        {
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
+                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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);
                                        }
-                                       */
                                }
                                break;
 
-                               /*
-                       case 1: // smoke smoke
-                               dec = 0.016f;
-                               p->texnum = smokeparticletexture;
-                               p->dynlight = true;
-                               p->scale = lhrandom(6,9);
-                               p->alpha = 64;
-                               if (r_smokecolor.value)
-                                       p->color = r_smokecolor.value;
+                       case 1: // grenade trail
+                               // FIXME: make it gradually stop smoking
+                               if (bubbles)
+                               {
+                                       dec = 0.02f;
+                                       particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
+                               }
                                else
-                                       p->color = (rand()&3)+12;
-                               p->type = pt_smoke;
-                               p->die = cl.time + 1;
-                               VectorCopy(start, p->org);
+                               {
+                                       dec = 0.02f;
+                                       particle(pt_smoke, 6, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16);
+                               }
                                break;
-                               */
+
 
                        case 2: // blood
+                               dec = 0.025f;
+                               particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+                               break;
+
                        case 4: // slight blood
                                dec = 0.025f;
-                               p->texnum = smokeparticletexture[rand()&7];
-                               p->dynlight = true;
-                               p->scale = lhrandom(4, 6);
-                               p->alpha = type == 4 ? 192 : 255;
-                               p->color = 247; //(rand()&3)+68;
-                               p->type = pt_bloodcloud;
-                               p->die = cl.time + 9999;
-                               for (j=0 ; j<3 ; j++)
-                               {
-                                       p->vel[j] = (rand()&15)-8;
-                                       p->org[j] = start[j] + ((rand()&3)-2);
-                               }
+                               particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 192, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
                                break;
 
-                       case 3:
-                       case 5: // tracer
+                       case 3: // green tracer
                                dec = 0.02f;
-                               p->texnum = smokeparticletexture[rand()&7];
-                               p->dynlight = false;
-                               p->scale = 4;
-                               p->alpha = 64 + (rand()&31);
-                               p->color = type == 3 ? 56 : 234;
-                               p->type = pt_fade;
-                               p->die = cl.time + 10000;
-                               VectorCopy(start, p->org);
+                               particle(pt_fade,  56, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 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);
                                break;
 
                        case 6: // voor trail
                                dec = 0.05f; // sparse trail
-                               p->texnum = smokeparticletexture[rand()&7];
-                               p->dynlight = false;
-                               p->scale = lhrandom(3, 5);
-                               p->alpha = 255;
-                               p->color = 9*16 + 8 + (rand()&3);
-                               p->type = pt_fade;
-                               p->die = cl.time + 2;
-                               for (j=0 ; j<3 ; j++)
-                               {
-                                       p->vel[j] = (rand()&15)-8;
-                                       p->org[j] = start[j] + ((rand()&3)-2);
-                               }
+                               particle(pt_fade, 152 + (rand()&3), smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                                break;
 
                        case 7: // Nehahra smoke tracer
                                dec = 0.14f;
-                               p->texnum = smokeparticletexture[rand()&7];
-                               p->dynlight = true;
-                               p->scale = lhrandom(8, 12);
-                               p->alpha = 64;
-                               p->color = (rand()&3)+12;
-                               p->type = pt_smoke;
-                               p->die = cl.time + 10000;
-                               for (j=0 ; j<3 ; j++)
-                                       p->org[j] = start[j] + ((rand()&3)-2);
+                               particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
                                break;
                }
                
+               // advance to next time and position
                t += dec;
                dec *= speed;
                VectorMA (start, dec, vec, start);
        }
-       ent->trail_leftover = t - cl.time;
+       ent->trail_time = t;
 }
 
 void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
@@ -967,7 +906,7 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        VectorScale(vec, 3, vec);
        while (len--)
        {
-               particle(pt_smoke, color, particletexture, false, 8, 192, 99, start[0], start[1], start[2], 0, 0, 0);
+               particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 99, 0, start[0], start[1], start[2], 0, 0, 0);
                VectorAdd (start, vec, start);
        }
 }
@@ -1010,6 +949,35 @@ void R_MoveParticles (void)
                p->org[0] += p->vel[0]*frametime;
                p->org[1] += p->vel[1]*frametime;
                p->org[2] += p->vel[2]*frametime;
+               if (p->bounce)
+               {
+                       vec3_t normal;
+                       float dist;
+                       if (TraceLine(p->oldorg, p->org, v, normal) < 1)
+                       {
+                               VectorCopy(v, p->org);
+                               if (p->bounce < 0)
+                               {
+                                       VectorClear(p->vel);
+                                       p->type = pt_decal;
+                                       // have to negate the direction (why?)
+                                       VectorNegate(normal, p->direction);
+                                       p->bounce = 0;
+                                       p->time2 = cl.time + 30;
+                               }
+                               else
+                               {
+                                       dist = DotProduct(p->vel, normal) * -p->bounce;
+                                       VectorMAQuick(p->vel, dist, normal, p->vel);
+                                       if (DotProduct(p->vel, p->vel) < 0.03)
+                                       {
+                                               VectorClear(p->vel);
+                                               // hack - world is static, therefore there won't be any moving or disappearing surfaces to worry about
+                                               //p->bounce = 0;
+                                       }
+                               }
+                       }
+               }
                
                switch (p->type)
                {
@@ -1027,6 +995,9 @@ void R_MoveParticles (void)
                case pt_grav:
                        p->vel[2] -= gravity;
                        break;
+               case pt_slowgrav:
+                       p->vel[2] -= gravity * 0.05;
+                       break;
                case pt_snow:
                        if (cl.time > p->time2)
                        {
@@ -1035,28 +1006,92 @@ void R_MoveParticles (void)
                                p->vel[1] = (rand()&63)-32 + p->vel2[1];
                                p->vel[2] = (rand()&63)-32 + p->vel2[2];
                        }
+                       a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+                       if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
+                       {
+                               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)
+                               {
+                               case CONTENTS_LAVA:
+                               case CONTENTS_SLIME:
+                                       p->tex = smokeparticletexture[rand()&7];
+                                       p->type = pt_smokecloud;
+                                       p->alpha = 96;
+                                       p->scale = 5;
+                                       p->vel[2] = 96;
+                                       break;
+                               case CONTENTS_WATER:
+                                       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);
+                                       VectorCopy(v, p->org);
+                                       p->tex = smokeparticletexture[rand()&7];
+                                       p->type = pt_fade;
+                                       VectorClear(p->vel);
+                                       break;
+                               }
+                       }
                        break;
                case pt_bloodcloud:
 //                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
 //                     {
 //                             p->die = -1;
 //                             break;
+//                     }
+                       p->scale += frametime * 16;
+                       p->alpha -= frametime * 256;
+                       p->vel[2] -= gravity * 0.25;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
+               case pt_blood:
+//                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+//                     {
+//                             p->die = -1;
+//                             break;
 //                     }
                        p->scale += frametime * 16;
                        p->alpha -= frametime * 512;
+                       p->vel[2] -= gravity * 0.25;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
+               case pt_bloodsplatter:
+//                     if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+//                     {
+//                             p->die = -1;
+//                             break;
+//                     }
+                       p->alpha -= frametime * 128;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       p->vel[2] -= gravity * 0.5;
                        break;
                case pt_fallfadespark:
                        p->alpha -= frametime * 256;
                        p->vel[2] -= gravity;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
                case pt_fade:
                        p->alpha -= frametime * 512;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
                case pt_bubble:
                        a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
                        if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
                        {
-                               p->texnum = smokeparticletexture[rand()&7];
+                               p->tex = smokeparticletexture[rand()&7];
                                p->type = pt_splash;
                                p->alpha = 96;
                                p->scale = 5;
@@ -1076,19 +1111,38 @@ void R_MoveParticles (void)
                                p->vel[2] += lhrandom(-32,32);
                        }
                        p->alpha -= frametime * 64;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
 // LordHavoc: for smoke trails
+               case pt_bulletsmoke:
+                       p->scale += frametime * 60;
+                       p->alpha -= frametime * 512;
+                       p->vel[2] += gravity * 0.05;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
                case pt_smoke:
-                       p->scale += frametime * 16;
+                       p->scale += frametime * 20;
                        p->alpha -= frametime * 256;
+                       p->vel[2] += gravity * 0.05;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
                case pt_smokecloud:
                        p->scale += frametime * 64;
                        p->alpha -= frametime * 256;
+                       p->vel[2] += gravity * 0.05;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
                case pt_splash:
                        p->scale += frametime * 24;
                        p->alpha -= frametime * 512;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
                case pt_rain:
                        a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
@@ -1098,73 +1152,95 @@ void R_MoveParticles (void)
                                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)
                                {
                                case CONTENTS_LAVA:
                                case CONTENTS_SLIME:
-                                       p->texnum = smokeparticletexture[rand()&7];
+                                       p->tex = smokeparticletexture[rand()&7];
                                        p->type = pt_smokecloud;
-                                       p->alpha = 64;
+                                       p->alpha = 96;
+                                       p->scale = 5;
                                        p->vel[2] = 96;
                                        break;
                                case CONTENTS_WATER:
-                                       p->texnum = smokeparticletexture[rand()&7];
+                                       p->tex = smokeparticletexture[rand()&7];
                                        p->type = pt_splash;
                                        p->alpha = 96;
                                        p->scale = 5;
-                                       p->vel[0] = p->vel[1] = p->vel[2] = 0;
-//                                     p->texnum = bubbleparticletexture;
-//                                     p->type = pt_bubble;
-//                                     p->vel[2] *= 0.1;
                                        break;
                                default: // CONTENTS_SOLID and any others
                                        TraceLine(p->oldorg, p->org, v, normal);
                                        VectorCopy(v, p->org);
-                                       p->texnum = smokeparticletexture[rand()&7];
+                                       p->tex = smokeparticletexture[rand()&7];
                                        p->type = pt_splash;
                                        p->alpha = 96;
                                        p->scale = 5;
-                                       p->vel[0] = p->vel[1] = p->vel[2] = 0;
-                                       p->die = cl.time + 1000;
+                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1,  64, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
+                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 128, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
+                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 192, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
+                                       particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 255, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48);
                                        break;
                                }
                        }
                        break;
                case pt_flame:
                        p->alpha -= frametime * 512;
+                       p->vel[2] += gravity * 0.2;
+                       if (p->alpha < 1)
+                               p->die = -1;
                        break;
+                       /*
                case pt_flamingdebris:
                        if (cl.time >= p->time2)
                        {
                                p->time2 = cl.time + 0.01;
-                               particle2(pt_flame, p->color, particletexture, false, 4, p->alpha, 999, p->org, 0, 50);
+                               particle2(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 999, 0, p->org, 0, 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], false, 4, p->alpha, 999, p->org, 0, 50);
+                               particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 999, 0, p->org, 0, 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_flamefall:
                        p->alpha -= frametime * 512;
                        p->vel[2] -= gravity * 0.5f;
+                       if (p->alpha < 1)
+                               p->die = -1;
+                       break;
+                       */
+               case pt_glow:
+                       if (p->time2)
+                               p->die = -1;
+                       p->time2 = 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->die = -1;
                        break;
                }
 
-               // LordHavoc: most particles did this check anyway, consistency...
-               if (p->alpha < 1)
-                       p->die = -1;
-
                // LordHavoc: immediate removal of unnecessary particles (must be done to ensure compactor below operates properly in all cases)
                if (p->die < cl.time)
                        freeparticles[j++] = p;
@@ -1185,15 +1261,13 @@ void R_MoveParticles (void)
        numparticles = activeparticles;
 }
 
-void R_CompleteLightPoint (vec3_t color, vec3_t p);
-
 void R_DrawParticles (void)
 {
        particle_t              *p;
        int                             i, r,g,b,a, dynlight;
        float                   scale, scale2, minparticledist;
        byte                    *color24;
-       vec3_t                  up, right, uprightangles, forward2, up2, right2, tempcolor;
+       vec3_t                  up, right, uprightangles, up2, right2, tempcolor, corner, decalright, decalup, v;
 
        // LordHavoc: early out condition
        if ((!numparticles) || (!r_drawparticles.value))
@@ -1210,7 +1284,7 @@ void R_DrawParticles (void)
        uprightangles[0] = 0;
        uprightangles[1] = r_refdef.viewangles[1];
        uprightangles[2] = 0;
-       AngleVectors (uprightangles, forward2, right2, up2);
+       AngleVectors (uprightangles, NULL, right2, up2);
 
        minparticledist = DotProduct(r_refdef.vieworg, vpn) + 16.0f;
 
@@ -1220,6 +1294,13 @@ void R_DrawParticles (void)
 //             if (p->die < cl.time)
 //                     continue;
 
+               if (p->type == pt_decal)
+               {
+                       VectorSubtract(p->org, r_refdef.vieworg, v);
+                       if (DotProduct(p->direction, v) < 0)
+                               continue;
+               }
+
                // LordHavoc: only render if not too close
                if (DotProduct(p->org, vpn) < minparticledist)
                        continue;
@@ -1236,21 +1317,38 @@ void R_DrawParticles (void)
                        g = (g * (int) tempcolor[1]) >> 7;
                        b = (b * (int) tempcolor[2]) >> 7;
                }
-               transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA);
-               scale = p->scale * -0.5;scale2 = p->scale * 0.5;
-               if (p->texnum == rainparticletexture) // rain streak
+               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)
+               {
+                       VectorVectors(p->direction, decalright, decalup);
+                       corner[0] = p->org[0] + decalup[0]*scale + decalright[0]*scale;
+                       corner[1] = p->org[1] + decalup[1]*scale + decalright[1]*scale;
+                       corner[2] = p->org[2] + decalup[2]*scale + decalright[2]*scale;
+                       transpolyvert(corner[0]                                           , corner[1]                                           , corner[2]                                           , 0,1,r,g,b,a);
+                       transpolyvert(corner[0] + decalup[0]*scale2                       , corner[1] + decalup[1]*scale2                       , corner[2] + decalup[2]*scale2                       , 0,0,r,g,b,a);
+                       transpolyvert(corner[0] + decalup[0]*scale2 + decalright[0]*scale2, corner[1] + decalup[1]*scale2 + decalright[1]*scale2, corner[2] + decalup[2]*scale2 + decalright[2]*scale2, 1,0,r,g,b,a);
+                       transpolyvert(corner[0]                     + decalright[0]*scale2, corner[1]                     + decalright[1]*scale2, corner[2]                     + decalright[2]*scale2, 1,1,r,g,b,a);
+               }
+               else if (p->tex == rainparticletexture) // rain streak
                {
-                       transpolyvert(p->org[0] + up2[0]*scale  + right2[0]*scale , p->org[1] + up2[1]*scale  + right2[1]*scale , p->org[2] + up2[2]*scale  + right2[2]*scale , 0,1,r,g,b,a);
-                       transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale , p->org[1] + up2[1]*scale2 + right2[1]*scale , p->org[2] + up2[2]*scale2 + right2[2]*scale , 0,0,r,g,b,a);
-                       transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale2, p->org[1] + up2[1]*scale2 + right2[1]*scale2, p->org[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a);
-                       transpolyvert(p->org[0] + up2[0]*scale  + right2[0]*scale2, p->org[1] + up2[1]*scale  + right2[1]*scale2, p->org[2] + up2[2]*scale  + right2[2]*scale2, 1,1,r,g,b,a);
+                       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;
+                       transpolyvert(corner[0]                                   , corner[1]                                   , corner[2]                                   , 0,1,r,g,b,a);
+                       transpolyvert(corner[0] + up2[0]*scale2                   , corner[1] + up2[1]*scale2                   , corner[2] + up2[2]*scale2                   , 0,0,r,g,b,a);
+                       transpolyvert(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,r,g,b,a);
+                       transpolyvert(corner[0]                 + right2[0]*scale2, corner[1]                 + right2[1]*scale2, corner[2]                 + right2[2]*scale2, 1,1,r,g,b,a);
                }
                else
                {
-                       transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale , p->org[1] + up[1]*scale  + right[1]*scale , p->org[2] + up[2]*scale  + right[2]*scale , 0,1,r,g,b,a);
-                       transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 0,0,r,g,b,a);
-                       transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale2, p->org[1] + up[1]*scale2 + right[1]*scale2, p->org[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a);
-                       transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale2, p->org[1] + up[1]*scale  + right[1]*scale2, p->org[2] + up[2]*scale  + right[2]*scale2, 1,1,r,g,b,a);
+                       corner[0] = p->org[0] + up[0]*scale + right[0]*scale;
+                       corner[1] = p->org[1] + up[1]*scale + right[1]*scale;
+                       corner[2] = p->org[2] + up[2]*scale + right[2]*scale;
+                       transpolyvert(corner[0]                                 , corner[1]                                 , corner[2]                                 , 0,1,r,g,b,a);
+                       transpolyvert(corner[0] + up[0]*scale2                  , corner[1] + up[1]*scale2                  , corner[2] + up[2]*scale2                  , 0,0,r,g,b,a);
+                       transpolyvert(corner[0] + up[0]*scale2 + right[0]*scale2, corner[1] + up[1]*scale2 + right[1]*scale2, corner[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a);
+                       transpolyvert(corner[0]                + right[0]*scale2, corner[1]                + right[1]*scale2, corner[2]                + right[2]*scale2, 1,1,r,g,b,a);
                }
                transpolyend();
        }
index ef0549015ea915c85d880a5b464c51271ab98685..13db9a0071681ea0791fcdd5e62535587159f699 100644 (file)
@@ -1,87 +1,14 @@
 #include "quakedef.h"
 
-/*
-================
-R_GetSpriteFrame
-================
-*/
-void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp)
-{
-       msprite_t               *psprite;
-       mspritegroup_t  *pspritegroup;
-       int                             i, j, numframes, frame;
-       float                   *pintervals, fullinterval, targettime, time, jtime, jinterval;
-
-       psprite = currententity->model->cache.data;
-       frame = currententity->frame;
-
-       if ((frame >= psprite->numframes) || (frame < 0))
-       {
-               Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
-               frame = 0;
-       }
-
-       if (psprite->frames[frame].type == SPR_SINGLE)
-       {
-               if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time)
-               {
-                       if (frame != currententity->draw_pose)
-                       {
-                               currententity->draw_lastpose = currententity->draw_pose;
-                               currententity->draw_pose = frame;
-                               currententity->draw_lerpstart = cl.time;
-                               *framelerp = 0;
-                       }
-                       else
-                               *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0;
-               }
-               else // uninitialized
-               {
-                       currententity->draw_lastmodel = currententity->model;
-                       currententity->draw_lastpose = currententity->draw_pose = frame;
-                       currententity->draw_lerpstart = cl.time;
-                       *framelerp = 0;
-               }
-               *oldframe = psprite->frames[currententity->draw_lastpose].frameptr;
-               *newframe = psprite->frames[frame].frameptr;
-       }
-       else
-       {
-               pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
-               pintervals = pspritegroup->intervals;
-               numframes = pspritegroup->numframes;
-               fullinterval = pintervals[numframes-1];
-
-               time = cl.time + currententity->syncbase;
-
-       // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
-       // are positive, so we don't have to worry about division by 0
-               targettime = time - ((int)(time / fullinterval)) * fullinterval;
-
-               // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0,
-               //            I instead measure the time of the first frame, hoping it is consistent
-               j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0];
-               for (i=0 ; i<(numframes-1) ; i++)
-               {
-                       if (pintervals[i] > targettime)
-                               break;
-                       j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i];
-               }
-               *framelerp = (targettime - jtime) / jinterval;
-
-               *oldframe = pspritegroup->frames[j];
-               *newframe = pspritegroup->frames[i];
-       }
-}
-
-void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha)
+void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha)
 {
-       // LordHavoc: rewrote this to use the transparent poly system
-       transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
-       transpolyvert(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, alpha);
-       transpolyvert(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, alpha);
-       transpolyvert(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, alpha);
-       transpolyvert(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alpha);
+       byte alphaub;
+       alphaub = bound(0, alpha, 255);
+       transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+       transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub);
+       transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub);
+       transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
+       transpolyvertub(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alphaub);
        transpolyend();
 }
 
@@ -91,29 +18,23 @@ R_DrawSpriteModel
 
 =================
 */
-void R_DrawSpriteModel (entity_t *e)
+void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
 {
-       mspriteframe_t  *oldframe, *newframe;
-       float                   lerp, ilerp;
-       vec3_t                  forward, right, up, org, color;
+       vec3_t                  right, up, org, color;
+       byte                    colorub[4];
        msprite_t               *psprite;
 
        // don't even bother culling, because it's just a single
        // polygon without a surface cache
 
        c_sprites++;
-       
-       R_GetSpriteFrame (e, &oldframe, &newframe, &lerp);
-       if (lerp < 0) lerp = 0;
-       if (lerp > 1) lerp = 1;
-       if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK!
-               lerp = 1;
-       ilerp = 1.0 - lerp;
-       psprite = e->model->cache.data;
+
+       psprite = Mod_Extradata(e->model);
+       //psprite = e->model->cache.data;
 
        if (psprite->type == SPR_ORIENTED)
        {       // bullet marks on walls
-               AngleVectors (e->angles, forward, right, up);
+               AngleVectors (e->angles, NULL, right, up);
                VectorSubtract(e->origin, vpn, org);
        }
        else
@@ -135,15 +56,20 @@ void R_DrawSpriteModel (entity_t *e)
                color[2] = e->colormod[2] * 255;
        }
        else
-       {
-               R_LightPoint (color, e->origin);
-               R_DynamicLightPointNoMask(color, e->origin);
-       }
+               R_CompleteLightPoint(color, e->origin);
+
+       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 (ilerp != 0)
-               GL_DrawSpriteImage(oldframe, org, up, right, color[0],color[1],color[2],e->alpha*255*ilerp);
-       if (lerp != 0)
-               GL_DrawSpriteImage(newframe, org, up, right, color[0],color[1],color[2],e->alpha*255*lerp);
+       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->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->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->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->alpha*255*blend[3].lerp);
 }
 
diff --git a/r_textures.h b/r_textures.h
new file mode 100644 (file)
index 0000000..9657fad
--- /dev/null
@@ -0,0 +1,19 @@
+
+#define TEXF_ALPHA 1 // transparent
+#define TEXF_MIPMAP 2 // mipmapped
+#define TEXF_RGBA 4 // 32bit RGBA, as opposed to 8bit paletted
+#define TEXF_PRECACHE 8 // upload immediately, otherwise defer loading until it is used (r_textureprecache can override this)
+
+// contents of this structure are private to gl_textures.c
+typedef struct rtexture_s
+{
+       int useless;
+}
+rtexture_t;
+
+// uploads a texture
+extern rtexture_t *R_LoadTexture (char *identifier, int width, int height, byte *data, int flags);
+// returns the renderer dependent texture slot number (call this before each use, as a texture might not have been precached)
+extern int R_GetTexture (rtexture_t *rt);
+// returns a GL texture slot (only used for lightmaps)
+extern int R_GetTextureSlots(int count);
index 669b7b372463162c3a39806c16e5b35ce00a3e56..5cf362e6547b4f2e65c306d45f8677407700a982 100644 (file)
--- a/render.h
+++ b/render.h
@@ -55,10 +55,7 @@ typedef struct entity_s
        float                                   alpha;                  // opacity (alpha) of the model
        float                                   colormod[3];    // color tint for model
        float                                   scale;                  // size the model is shown
-       int                                             draw_lastpose, draw_pose; // for interpolation
-       float                                   draw_lerpstart; // for interpolation
-       struct model_s                  *draw_lastmodel; // for interpolation
-       float                                   trail_leftover;
+       float                                   trail_time;
        float                                   glowsize;               // how big the glow is
        byte                                    glowcolor;              // color of glow and particle trail (paletted)
        byte                                    glowtrail;              // leaves a trail of particles
@@ -66,10 +63,17 @@ typedef struct entity_s
 
        struct model_s                  *model;                 // NULL = no model
        struct efrag_s                  *efrag;                 // linked list of efrags
-       int                                             frame;
+       int                                             frame;                  // current desired frame (usually identical to frame2, but frame2 is not always used)
+       struct model_s                  *lerp_model;    // lerp resets when model changes
+       float                                   lerp_starttime; // start of this transition
+       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 lerp_starttime
+       double                                  frame1start;    // time frame1 began playing (for framegroup animations)
+       double                                  frame2start;    // time frame2 began playing (for framegroup animations)
        float                                   syncbase;               // for client-side animations
        int                                             colormap;
-       int                                             effects;                // light, particals, etc
+       int                                             effects;                // light, particles, etc
        int                                             skinnum;                // for Alias models
        int                                             visframe;               // last frame this entity was
                                                                                        //  found in an active leaf
@@ -89,6 +93,7 @@ typedef struct
 {
        vrect_t         vrect;                          // subwindow in video for refresh
                                                                        // FIXME: not need vrect next field here?
+       /*
        vrect_t         aliasvrect;                     // scaled Alias version
        int                     vrectright, vrectbottom;        // right & bottom screen coords
        int                     aliasvrectright, aliasvrectbottom;      // scaled Alias versions
@@ -104,15 +109,16 @@ typedef struct
        float           fvrectbottom;                   // bottommost edge, for Alias clamping
        float           horizontalFieldOfView;  // at Z = 1.0, this many X is visible 
                                                                                // 2.0 = 90 degrees
-       float           xOrigin;                        // should probably allways be 0.5
+       float           xOrigin;                        // should probably always be 0.5
        float           yOrigin;                        // between be around 0.3 to 0.5
+       */
 
        vec3_t          vieworg;
        vec3_t          viewangles;
        
        float           fov_x, fov_y;
 
-       int                     ambientlight;
+//     int                     ambientlight;
 } refdef_t;
 
 
@@ -126,46 +132,44 @@ extern vec3_t     r_origin, vpn, vright, vup;
 
 extern struct texture_s        *r_notexture_mip;
 
-extern void R_Init (void);
-extern void R_InitTextures (void);
-extern void R_InitEfrags (void);
-extern void R_RenderView (void);               // must set r_refdef first
-extern void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect);
+void R_Init (void);
+void R_InitTextures (void);
+void R_InitEfrags (void);
+void R_RenderView (void);              // must set r_refdef first
+void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect);
                                                                // called whenever r_refdef or vid change
 // LordHavoc: changed this for sake of GLQuake
-extern void R_InitSky (byte *src, int bytesperpixel);  // called at level load
-//extern void R_InitSky (struct texture_s *mt);        // called at level load
-
-extern void R_AddEfrags (entity_t *ent);
-extern void R_RemoveEfrags (entity_t *ent);
-
-extern void R_NewMap (void);
-
-
-extern void R_ParseParticleEffect (void);
-extern void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
-extern void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent);
-extern void R_RocketTrail2 (vec3_t start, vec3_t end, int type, entity_t *ent);
-extern void R_SparkShower (vec3_t org, vec3_t dir, int count);
-extern void R_BloodPuff (vec3_t org);
-
-extern void R_EntityParticles (entity_t *ent);
-extern void R_BlobExplosion (vec3_t org);
-extern void R_ParticleExplosion (vec3_t org, int smoke);
-extern void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength);
-extern void R_LavaSplash (vec3_t org);
-extern void R_TeleportSplash (vec3_t org);
-
-extern void R_NewExplosion(vec3_t org);
-
-extern void R_PushDlights (void);
-extern void R_DrawWorld (void);
-//extern void R_RenderDlights (void);
-extern void R_DrawParticles (void);
-extern void R_MoveParticles (void);
-extern void R_DrawExplosions (void);
-extern void R_MoveExplosions (void);
-
-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);
+void R_InitSky (byte *src, int bytesperpixel); // called at level load
+//void R_InitSky (struct texture_s *mt);       // called at level load
+
+void R_AddEfrags (entity_t *ent);
+void R_RemoveEfrags (entity_t *ent);
+
+void R_NewMap (void);
+
+
+void R_ParseParticleEffect (void);
+void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
+void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent);
+void R_RocketTrail2 (vec3_t start, vec3_t end, int type, entity_t *ent);
+void R_SparkShower (vec3_t org, vec3_t dir, int count);
+void R_BloodPuff (vec3_t org, vec3_t vel, int count);
+void R_FlameCube (vec3_t mins, vec3_t maxs, int count);
+void R_Flames (vec3_t org, vec3_t vel, int count);
+
+void R_EntityParticles (entity_t *ent);
+void R_BlobExplosion (vec3_t org);
+void R_ParticleExplosion (vec3_t org, int smoke);
+void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength);
+void R_LavaSplash (vec3_t org);
+void R_TeleportSplash (vec3_t org);
+
+void R_NewExplosion(vec3_t org);
+
+void R_PushDlights (void);
+void R_DrawWorld (void);
+//void R_RenderDlights (void);
+void R_DrawParticles (void);
+void R_MoveParticles (void);
+void R_DrawExplosions (void);
+void R_MoveExplosions (void);
index c377acdc0dcc5b5225911e7a7be953e515726f84..4eada814250c8f1f3d707934c83c5561eb6296f6 100644 (file)
--- a/server.h
+++ b/server.h
@@ -40,6 +40,8 @@ typedef struct
        qboolean        loadgame;                       // handle connections specially
 
        double          time;
+
+       double          frametime;
        
        int                     lastcheck;                      // used by PF_checkclient
        double          lastchecktime;
@@ -204,8 +206,8 @@ extern      edict_t         *sv_player;
 void SV_Init (void);
 
 void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count);
-void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
-    float attenuation);
+void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate);
+void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation);
 
 void SV_DropClient (qboolean crash);
 
index a66e329a15aa17dff155f923845a9a024c728913..4f760acc917c4083434abc34b49b37f96e1155e8 100644 (file)
--- a/snd_dma.c
+++ b/snd_dma.c
@@ -64,9 +64,6 @@ int                   num_sfx;
 
 sfx_t          *ambient_sfx[NUM_AMBIENTS];
 
-int            desired_speed = 44100; //11025; // LordHavoc: 44.1khz sound
-int            desired_bits = 16;
-
 int sound_started=0;
 
 cvar_t bgmvolume = {"bgmvolume", "1", true};
@@ -376,7 +373,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
                if (entchannel != 0             // channel 0 never overrides
                && channels[ch_idx].entnum == entnum
                && (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
-               {       // allways override sound from same entity
+               {       // always override sound from same entity
                        first_to_die = ch_idx;
                        break;
                }
@@ -414,7 +411,7 @@ void SND_Spatialize(channel_t *ch)
     vec3_t source_vec;
        sfx_t *snd;
 
-// anything coming from the view entity will allways be full volume
+// anything coming from the view entity will always be full volume
 // LordHavoc: make sounds with ATTN_NONE have no spatialization
        if (ch->entnum == cl.viewentity || ch->dist_mult == 0)
        {
@@ -517,9 +514,12 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
                        continue;
                if (check->sfx == sfx && !check->pos)
                {
-                       skip = rand () % (int)(0.1*shm->speed);
-                       if (skip >= target_chan->end)
-                               skip = target_chan->end - 1;
+                       // LordHavoc: fixed skip calculations
+                       skip = 0.1 * shm->speed;
+                       if (skip > sc->length)
+                               skip = sc->length;
+                       if (skip > 0)
+                               skip = rand() % skip;
                        target_chan->pos += skip;
                        target_chan->end -= skip;
                        break;
@@ -707,13 +707,13 @@ void S_UpdateAmbientSounds (void)
        // don't adjust volume too fast
                if (chan->master_vol < vol)
                {
-                       chan->master_vol += host_frametime * ambient_fade.value;
+                       chan->master_vol += host_realframetime * ambient_fade.value;
                        if (chan->master_vol > vol)
                                chan->master_vol = vol;
                }
                else if (chan->master_vol > vol)
                {
-                       chan->master_vol -= host_frametime * ambient_fade.value;
+                       chan->master_vol -= host_realframetime * ambient_fade.value;
                        if (chan->master_vol < vol)
                                chan->master_vol = vol;
                }
@@ -763,7 +763,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
        // try to combine static sounds with a previous channel of the same
        // sound effect so we don't mix five torches every frame
        
-               if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
+               if (i > MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS)
                {
                // see if it can just use the last one
                        if (combine && combine->sfx == ch->sfx)
index f573c370365e49061e35837322f9ab92175b2591..09758a63057b1887860157b2b2315218433e95d1 100644 (file)
--- a/snd_mem.c
+++ b/snd_mem.c
@@ -30,10 +30,10 @@ byte *S_Alloc (int size);
 ResampleSfx
 ================
 */
-void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
+void ResampleSfx (sfx_t *sfx, int inrate, byte *data, char *name)
 {
        int             outcount;
-       int             srcsample;
+       int             srcsample, srclength;
        float   stepscale;
        int             i;
        int             samplefrac, fracstep;
@@ -45,6 +45,8 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
 
        stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2
 
+       srclength = sc->length << sc->stereo;
+
        outcount = sc->length / stepscale;
        sc->length = outcount;
        if (sc->loopstart != -1)
@@ -62,6 +64,7 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
        if (stepscale == 1/* && inwidth == 1*/ && sc->width == 1)
        {
 // fast special case
+               /*
                // LordHavoc: I do not serve the readability gods...
                int *indata, *outdata;
                int count4, count1;
@@ -75,27 +78,18 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                        ((short*)outdata)[0] = ((short*)indata)[0] ^ 0x8080;
                if (count1 & 1)
                        ((char*)outdata)[2] = ((char*)indata)[2] ^ 0x80;
-               /*
-               if (sc->stereo) // LordHavoc: stereo sound support
-               {
-                       for (i=0 ; i<(outcount<<1) ; i++)
-                               ((signed char *)sc->data)[i] = (int)( (unsigned char)(data[i]) - 128);
-               }
-               else
-               {
-                       for (i=0 ; i<outcount ; i++)
-                               ((signed char *)sc->data)[i] = (int)( (unsigned char)(data[i]) - 128);
-               }
                */
+               if (sc->stereo) // LordHavoc: stereo sound support
+                       outcount *= 2;
+               for (i=0 ; i<outcount ; i++)
+                       ((signed char *)sc->data)[i] = ((unsigned char *)data)[i] - 128;
        }
        else if (stepscale == 1/* && inwidth == 2*/ && sc->width == 2) // LordHavoc: quick case for 16bit
        {
                if (sc->stereo) // LordHavoc: stereo sound support
-                       for (i=0 ; i<outcount*2 ;i++)
-                               ((short *)sc->data)[i] = LittleShort (((short *)data)[i]);
-               else
-                       for (i=0 ; i<outcount ;i++)
-                               ((short *)sc->data)[i] = LittleShort (((short *)data)[i]);
+                       outcount *= 2;
+               for (i=0 ; i<outcount ;i++)
+                       ((short *)sc->data)[i] = LittleShort (((short *)data)[i]);
        }
        else
        {
@@ -113,10 +107,10 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                                if (sc->stereo) // LordHavoc: stereo sound support
                                {
                                        fracstep <<= 1;
-                                       for (i=0 ; i<outcount ;)
+                                       for (i=0 ; i<outcount ; i++)
                                        {
-                                               *out++ = (short) LittleShort (in[srcsample  ]);
-                                               *out++ = (short) LittleShort (in[srcsample+1]);
+                                               *out++ = LittleShort (in[srcsample  ]);
+                                               *out++ = LittleShort (in[srcsample+1]);
                                                srcsample += fracstep;
                                        }
                                }
@@ -124,21 +118,22 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                                {
                                        for (i=0 ; i<outcount ; i++)
                                        {
-                                               *out++ = (short) LittleShort (in[srcsample  ]);
+                                               *out++ = LittleShort (in[srcsample  ]);
                                                srcsample += fracstep;
                                        }
                                }
                        }
                        else
                        {
-                               signed char *out = (void *)sc->data, *in = (void *)data;
+                               signed char *out = (void *)sc->data;
+                               unsigned char *in = (void *)data;
                                if (sc->stereo) // LordHavoc: stereo sound support
                                {
                                        fracstep <<= 1;
-                                       for (i=0 ; i<outcount ;)
+                                       for (i=0 ; i<outcount ; i++)
                                        {
-                                               *out++ = (signed char) in[srcsample  ] - 128;
-                                               *out++ = (signed char) in[srcsample+1] - 128;
+                                               *out++ = in[srcsample  ] - 128;
+                                               *out++ = in[srcsample+1] - 128;
                                                srcsample += fracstep;
                                        }
                                }
@@ -146,7 +141,7 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                                {
                                        for (i=0 ; i<outcount ; i++)
                                        {
-                                               *out++ = (signed char) in[srcsample  ] - 128;
+                                               *out++ = in[srcsample  ] - 128;
                                                srcsample += fracstep;
                                        }
                                }
@@ -155,19 +150,30 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                else
                {
                        int sample;
+                       int a, b;
                        if (sc->width == 2)
                        {
                                short *out = (void *)sc->data, *in = (void *)data;
                                if (sc->stereo) // LordHavoc: stereo sound support
                                {
-                                       for (i=0 ; i<outcount ;)
+                                       for (i=0 ; i<outcount ; i++)
                                        {
-                                               srcsample = (samplefrac >> 7) & ~1;
-                                               samplefrac += fracstep;
-                                               sample = (LittleShort (in[srcsample  ]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+2]) * (samplefrac & 255)) >> 8;
+                                               srcsample = (samplefrac >> 8) << 1;
+                                               a = in[srcsample  ];
+                                               if (srcsample+2 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = in[srcsample+2];
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (short) sample;
-                                               sample = (LittleShort (in[srcsample+1]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+3]) * (samplefrac & 255)) >> 8;
+                                               a = in[srcsample+1];
+                                               if (srcsample+2 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = in[srcsample+3];
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (short) sample;
+                                               samplefrac += fracstep;
                                        }
                                }
                                else
@@ -175,25 +181,41 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                                        for (i=0 ; i<outcount ; i++)
                                        {
                                                srcsample = samplefrac >> 8;
-                                               samplefrac += fracstep;
-                                               sample = (LittleShort (in[srcsample  ]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+1]) * (samplefrac & 255)) >> 8;
+                                               a = in[srcsample  ];
+                                               if (srcsample+1 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = in[srcsample+1];
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (short) sample;
+                                               samplefrac += fracstep;
                                        }
                                }
                        }
                        else
                        {
-                               signed char *out = (void *)sc->data, *in = (void *)data;
+                               signed char *out = (void *)sc->data;
+                               unsigned char *in = (void *)data;
                                if (sc->stereo) // LordHavoc: stereo sound support
                                {
-                                       for (i=0 ; i<outcount ;)
+                                       for (i=0 ; i<outcount ; i++)
                                        {
-                                               srcsample = (samplefrac >> 7) & ~1;
-                                               samplefrac += fracstep;
-                                               sample = ((((unsigned char) in[srcsample  ] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+2] - 128) * (samplefrac & 255))) >> 8;
+                                               srcsample = (samplefrac >> 8) << 1;
+                                               a = (int) in[srcsample  ] - 128;
+                                               if (srcsample+2 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = (int) in[srcsample+2] - 128;
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (signed char) sample;
-                                               sample = ((((unsigned char) in[srcsample+1] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+3] - 128) * (samplefrac & 255))) >> 8;
+                                               a = (int) in[srcsample+1] - 128;
+                                               if (srcsample+2 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = (int) in[srcsample+3] - 128;
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (signed char) sample;
+                                               samplefrac += fracstep;
                                        }
                                }
                                else
@@ -201,14 +223,24 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data)
                                        for (i=0 ; i<outcount ; i++)
                                        {
                                                srcsample = samplefrac >> 8;
-                                               samplefrac += fracstep;
-                                               sample = ((((unsigned char) in[srcsample  ] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+1] - 128) * (samplefrac & 255))) >> 8;
+                                               a = (int) in[srcsample  ] - 128;
+                                               if (srcsample+1 >= srclength)
+                                                       b = 0;
+                                               else
+                                                       b = (int) in[srcsample+1] - 128;
+                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
                                                *out++ = (signed char) sample;
+                                               samplefrac += fracstep;
                                        }
                                }
                        }
                }
        }
+
+       // LordHavoc: use this for testing if it ever becomes useful again
+#if 0
+       COM_WriteFile (va("sound/%s.pcm", name), sc->data, (sc->length << sc->stereo) * sc->width);
+#endif
 }
 
 //=============================================================================
@@ -281,7 +313,7 @@ sfxcache_t *S_LoadSound (sfx_t *s)
        sc->width = info.width;
        sc->stereo = info.channels == 2;
 
-       ResampleSfx (s, sc->speed, data + info.dataofs);
+       ResampleSfx (s, sc->speed, data + info.dataofs, s->name);
 
        qfree(data);
        return sc;
index 1da0fcf6f29bf8b9f08c697e9496213642fc6f10..7444857f7fa2229ac8c359a1891d6d7eca4a3842 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -27,7 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define DWORD  unsigned long
 #endif
 
-#define        PAINTBUFFER_SIZE        512
+// LordHavoc: was 512, expanded to 2048
+#define        PAINTBUFFER_SIZE        2048
 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
 int            snd_scaletable[32][256];
 int    *snd_p, snd_linear_count, snd_vol;
@@ -46,20 +47,9 @@ void Snd_WriteLinearBlastStereo16 (void)
                for (i=0 ; i<snd_linear_count ; i+=2)
                {
                        val = (snd_p[i+1]*snd_vol)>>8;
-                       if (val > 0x7fff)
-                               snd_out[i] = 0x7fff;
-                       else if (val < (short)0x8000)
-                               snd_out[i] = (short)0x8000;
-                       else
-                               snd_out[i] = val;
-
-                       val = (snd_p[i]*snd_vol)>>8;
-                       if (val > 0x7fff)
-                               snd_out[i+1] = 0x7fff;
-                       else if (val < (short)0x8000)
-                               snd_out[i+1] = (short)0x8000;
-                       else
-                               snd_out[i+1] = val;
+                       snd_out[i  ] = bound(-32768, val, 32767);
+                       val = (snd_p[i  ]*snd_vol)>>8;
+                       snd_out[i+1] = bound(-32768, val, 32767);
                }
        }
        else
@@ -67,20 +57,9 @@ void Snd_WriteLinearBlastStereo16 (void)
                for (i=0 ; i<snd_linear_count ; i+=2)
                {
                        val = (snd_p[i]*snd_vol)>>8;
-                       if (val > 0x7fff)
-                               snd_out[i] = 0x7fff;
-                       else if (val < (short)0x8000)
-                               snd_out[i] = (short)0x8000;
-                       else
-                               snd_out[i] = val;
-
+                       snd_out[i] = bound(-32768, val, 32767);
                        val = (snd_p[i+1]*snd_vol)>>8;
-                       if (val > 0x7fff)
-                               snd_out[i+1] = 0x7fff;
-                       else if (val < (short)0x8000)
-                               snd_out[i+1] = (short)0x8000;
-                       else
-                               snd_out[i+1] = val;
+                       snd_out[i+1] = bound(-32768, val, 32767);
                }
        }
 }
@@ -107,8 +86,7 @@ void S_TransferStereo16 (int endtime)
        {
                reps = 0;
 
-               while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
-                                                                          &pbuf2, &dwSize2, 0)) != DS_OK)
+               while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2, &dwSize2, 0)) != DS_OK)
                {
                        if (hresult != DSERR_BUFFERLOST)
                        {
@@ -194,8 +172,7 @@ void S_TransferPaintBuffer(int endtime)
        {
                reps = 0;
 
-               while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
-                                                                          &pbuf2,&dwSize2, 0)) != DS_OK)
+               while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2,&dwSize2, 0)) != DS_OK)
                {
                        if (hresult != DSERR_BUFFERLOST)
                        {
@@ -226,12 +203,8 @@ void S_TransferPaintBuffer(int endtime)
                while (count--)
                {
                        val = (*p * snd_vol) >> 8;
+                       out[out_idx] = bound(-32768, val, 32767);
                        p+= step;
-                       if (val > 0x7fff)
-                               val = 0x7fff;
-                       else if (val < (short)0x8000)
-                               val = (short)0x8000;
-                       out[out_idx] = val;
                        out_idx = (out_idx + 1) & out_mask;
                }
        }
@@ -240,19 +213,16 @@ void S_TransferPaintBuffer(int endtime)
                unsigned char *out = (unsigned char *) pbuf;
                while (count--)
                {
-                       val = (*p * snd_vol) >> 8;
+                       val = ((*p * snd_vol) >> 16) + 128;
+                       out[out_idx] = bound(0, val, 255);
                        p+= step;
-                       if (val > 0x7fff)
-                               val = 0x7fff;
-                       else if (val < (short)0x8000)
-                               val = (short)0x8000;
-                       out[out_idx] = (val>>8) + 128;
                        out_idx = (out_idx + 1) & out_mask;
                }
        }
 
 #ifdef _WIN32
-       if (pDSBuf) {
+       if (pDSBuf)
+       {
                DWORD dwNewpos, dwWrite;
                int il = paintedtime;
                int ir = endtime - paintedtime;
@@ -291,15 +261,15 @@ void S_PaintChannels(int endtime)
 
        while (paintedtime < endtime)
        {
-       // if paintbuffer is smaller than DMA buffer
+               // if paintbuffer is smaller than DMA buffer
                end = endtime;
                if (endtime - paintedtime > PAINTBUFFER_SIZE)
                        end = paintedtime + PAINTBUFFER_SIZE;
 
-       // clear the paint buffer
+               // clear the paint buffer
                memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
 
-       // paint in the channels.
+               // paint in the channels.
                ch = channels;
                for (i=0; i<total_channels ; i++, ch++)
                {
@@ -314,7 +284,8 @@ void S_PaintChannels(int endtime)
                        ltime = paintedtime;
 
                        while (ltime < end)
-                       {       // paint up to end
+                       {
+                               // paint up to end
                                if (ch->end < end)
                                        count = ch->end - ltime;
                                else
@@ -330,7 +301,7 @@ void S_PaintChannels(int endtime)
                                        ltime += count;
                                }
 
-                       // if at end of loop, restart
+                               // if at end of loop, restart
                                if (ltime >= ch->end)
                                {
                                        if (sc->loopstart >= 0)
@@ -339,7 +310,8 @@ void S_PaintChannels(int endtime)
                                                ch->end = ltime + sc->length - ch->pos;
                                        }
                                        else                            
-                                       {       // channel just stopped
+                                       {
+                                               // channel just stopped
                                                ch->sfx = NULL;
                                                break;
                                        }
@@ -348,7 +320,7 @@ void S_PaintChannels(int endtime)
                                                                                                                          
                }
 
-       // transfer out according to DMA format
+               // transfer out according to DMA format
                S_TransferPaintBuffer(end);
                paintedtime = end;
        }
@@ -375,11 +347,12 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
                ch->leftvol = 255;
        if (ch->rightvol > 255)
                ch->rightvol = 255;
-               
+
        lscale = snd_scaletable[ch->leftvol >> 3];
        rscale = snd_scaletable[ch->rightvol >> 3];
-       if (sc->stereo) // LordHavoc: stereo sound support, and optimizations
+       if (sc->stereo)
        {
+               // LordHavoc: stereo sound support, and optimizations
                sfx = (unsigned char *)sc->data + ch->pos * 2;
 
                for (i=0 ; i<count ; i++)
@@ -413,14 +386,15 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
 
        leftvol = ch->leftvol;
        rightvol = ch->rightvol;
-       if (sc->stereo) // LordHavoc: stereo sound support, and optimizations
+       if (sc->stereo)
        {
+               // LordHavoc: stereo sound support, and optimizations
                sfx = (signed short *)sc->data + ch->pos * 2;
 
                for (i=0 ; i<count ; i++)
                {
-                       paintbuffer[i].left += (short) ((int) (*sfx++ * leftvol) >> 8);
-                       paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8);
+                       paintbuffer[i].left += (*sfx++ * leftvol) >> 8;
+                       paintbuffer[i].right += (*sfx++ * rightvol) >> 8;
                }
        }
        else
@@ -429,8 +403,8 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
 
                for (i=0 ; i<count ; i++)
                {
-                       paintbuffer[i].left += (short) ((int) (*sfx * leftvol) >> 8);
-                       paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8);
+                       paintbuffer[i].left += (*sfx * leftvol) >> 8;
+                       paintbuffer[i].right += (*sfx++ * rightvol) >> 8;
                }
        }
 
index d24b6f2dd42a50870d3a831c832a645448b7d134..1a725ebbabf36f4852b7510beb153cf82e2760bd 100644 (file)
--- a/snd_win.c
+++ b/snd_win.c
@@ -364,7 +364,7 @@ sndinitstat SNDDMA_InitDirect (void)
        if (snd_firsttime)
                Con_SafePrintf("   %d channel(s)\n"
                               "   %d bits/sample\n"
-                                          "   %d bytes/sec\n",
+                                          "   %d samples/sec\n",
                                           shm->channels, shm->samplebits, shm->speed);
        
        gSndBufSize = dsbcaps.dwBufferBytes;
index 9a3c37ed3b6df8e4ec7c86c6d454839387768106..330a9ba712fdf731635c0060d49a65bd1c2ca164 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -102,6 +102,41 @@ void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
        MSG_WriteByte (&sv.datagram, color);
 }           
 
+/*  
+==================
+SV_StartEffect
+
+Make sure the event gets sent to all clients
+==================
+*/
+void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate)
+{
+       if (sv.datagram.cursize > MAX_DATAGRAM-18)
+               return; 
+       if (modelindex >= 256)
+       {
+               MSG_WriteByte (&sv.datagram, svc_effect2);
+               MSG_WriteFloatCoord (&sv.datagram, org[0]);
+               MSG_WriteFloatCoord (&sv.datagram, org[1]);
+               MSG_WriteFloatCoord (&sv.datagram, org[2]);
+               MSG_WriteShort (&sv.datagram, modelindex);
+               MSG_WriteByte (&sv.datagram, startframe);
+               MSG_WriteByte (&sv.datagram, framecount);
+               MSG_WriteByte (&sv.datagram, framerate);
+       }
+       else
+       {
+               MSG_WriteByte (&sv.datagram, svc_effect);
+               MSG_WriteFloatCoord (&sv.datagram, org[0]);
+               MSG_WriteFloatCoord (&sv.datagram, org[1]);
+               MSG_WriteFloatCoord (&sv.datagram, org[2]);
+               MSG_WriteByte (&sv.datagram, modelindex);
+               MSG_WriteByte (&sv.datagram, startframe);
+               MSG_WriteByte (&sv.datagram, framecount);
+               MSG_WriteByte (&sv.datagram, framerate);
+       }
+}           
+
 /*  
 ==================
 SV_StartSound
@@ -110,7 +145,7 @@ Each entity can have eight independant sound sources, like voice,
 weapon, feet, etc.
 
 Channel 0 is an auto-allocate channel, the others override anything
-allready running on that entity/channel pair.
+already running on that entity/channel pair.
 
 An attenuation of 0 will play full volume everywhere in the level.
 Larger attenuations will drop off.  (max 4 attenuation)
@@ -159,15 +194,21 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
        if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
                field_mask |= SND_ATTENUATION;
 
-// directed messages go only to the entity the are targeted on
-       MSG_WriteByte (&sv.datagram, svc_sound);
+// directed messages go only to the entity they are targeted on
+       if (sound_num >= 256)
+               MSG_WriteByte (&sv.datagram, svc_sound2);
+       else
+               MSG_WriteByte (&sv.datagram, svc_sound);
        MSG_WriteByte (&sv.datagram, field_mask);
        if (field_mask & SND_VOLUME)
                MSG_WriteByte (&sv.datagram, volume);
        if (field_mask & SND_ATTENUATION)
                MSG_WriteByte (&sv.datagram, attenuation*64);
        MSG_WriteShort (&sv.datagram, channel);
-       MSG_WriteByte (&sv.datagram, sound_num);
+       if (sound_num >= 256)
+               MSG_WriteShort (&sv.datagram, sound_num);
+       else
+               MSG_WriteByte (&sv.datagram, sound_num);
        for (i=0 ; i<3 ; i++)
                MSG_WriteFloatCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
 }           
@@ -547,7 +588,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
 
                dodelta = false;
                if ((int)ent->v.effects & EF_DELTA)
-                       dodelta = sv.time < client->nextfullupdate[e]; // every half second a full update is forced
+                       dodelta = realtime < client->nextfullupdate[e]; // every half second a full update is forced
 
                if (dodelta)
                {
@@ -556,7 +597,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                }
                else
                {
-                       client->nextfullupdate[e] = sv.time + 0.5;
+                       client->nextfullupdate[e] = realtime + 0.5;
                        baseline = &ent->baseline;
                }
 
@@ -619,17 +660,20 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                }
 
                // LordHavoc: old stuff, but rewritten to have more exact tolerances
-               if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0))                                             bits |= U_ORIGIN1;
-               if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0))                                             bits |= U_ORIGIN2;
-               if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0))                                             bits |= U_ORIGIN3;
+//             if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0))                                             bits |= U_ORIGIN1;
+//             if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0))                                             bits |= U_ORIGIN2;
+//             if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0))                                             bits |= U_ORIGIN3;
+               if (origin[0] != baseline->origin[0])                                                                                   bits |= U_ORIGIN1;
+               if (origin[1] != baseline->origin[1])                                                                                   bits |= U_ORIGIN2;
+               if (origin[2] != baseline->origin[2])                                                                                   bits |= U_ORIGIN3;
                if ((int)(angles[0]*(256.0/360.0)) != (int)(baseline->angles[0]*(256.0/360.0))) bits |= U_ANGLE1;
                if ((int)(angles[1]*(256.0/360.0)) != (int)(baseline->angles[1]*(256.0/360.0))) bits |= U_ANGLE2;
                if ((int)(angles[2]*(256.0/360.0)) != (int)(baseline->angles[2]*(256.0/360.0))) bits |= U_ANGLE3;
-               if (baseline->colormap != (int) ent->v.colormap)                                                                bits |= U_COLORMAP;
-               if (baseline->skin != (int) ent->v.skin)                                                                                bits |= U_SKIN;
+               if (baseline->colormap != (byte) ent->v.colormap)                                                               bits |= U_COLORMAP;
+               if (baseline->skin != (byte) ent->v.skin)                                                                               bits |= U_SKIN;
                if ((baseline->frame & 0x00FF) != ((int) ent->v.frame & 0x00FF))                                bits |= U_FRAME;
                if ((baseline->effects & 0x00FF) != ((int) ent->v.effects & 0x00FF))                    bits |= U_EFFECTS;
-               if (baseline->modelindex != (int) ent->v.modelindex)                                                    bits |= U_MODEL;
+               if (baseline->modelindex != (byte) ent->v.modelindex)                                                   bits |= U_MODEL;
 
                // LordHavoc: new stuff
                if (baseline->alpha != alpha)                                                                                                   bits |= U_ALPHA;
@@ -639,6 +683,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                if (baseline->glowcolor != glowcolor)                                                                                   bits |= U_GLOWCOLOR;
                if (baseline->colormod != colormod)                                                                                             bits |= U_COLORMOD;
                if (((int) baseline->frame & 0xFF00) != ((int) ent->v.frame & 0xFF00))                  bits |= U_FRAME2;
+               if (((int) baseline->frame & 0xFF00) != ((int) ent->v.modelindex & 0xFF00))             bits |= U_MODEL2;
 
                // update delta baseline
                VectorCopy(ent->v.origin, ent->deltabaseline.origin);
@@ -697,6 +742,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor);
                if (bits & U_COLORMOD)  MSG_WriteByte(msg, colormod);
                if (bits & U_FRAME2)    MSG_WriteByte(msg, (int)ent->v.frame >> 8);
+               if (bits & U_MODEL2)    MSG_WriteByte(msg, (int)ent->v.modelindex >> 8);
        }
 }
 
@@ -732,6 +778,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        edict_t *other;
        int             items;
        eval_t  *val;
+       vec3_t  punchvector;
 
 //
 // send a damage message
@@ -788,10 +835,17 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        if ( ent->v.waterlevel >= 2)
                bits |= SU_INWATER;
        
+       // dpprotocol
+       VectorClear(punchvector);
+       if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector)))
+               VectorCopy(val->vector, punchvector);
+
        for (i=0 ; i<3 ; i++)
        {
                if (ent->v.punchangle[i])
                        bits |= (SU_PUNCH1<<i);
+               if (punchvector[i]) // dpprotocol
+                       bits |= (SU_PUNCHVEC1<<i); // dpprotocol
                if (ent->v.velocity[i])
                        bits |= (SU_VELOCITY1<<i);
        }
@@ -805,10 +859,19 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
 //     if (ent->v.weapon)
                bits |= SU_WEAPON;
 
+       if (bits >= 65536)
+               bits |= SU_EXTEND1;
+       if (bits >= 16777216)
+               bits |= SU_EXTEND2;
+
 // send the data
 
        MSG_WriteByte (msg, svc_clientdata);
        MSG_WriteShort (msg, bits);
+       if (bits & SU_EXTEND1)
+               MSG_WriteByte(msg, bits >> 16);
+       if (bits & SU_EXTEND2)
+               MSG_WriteByte(msg, bits >> 24);
 
        if (bits & SU_VIEWHEIGHT)
                MSG_WriteChar (msg, ent->v.view_ofs[2]);
@@ -819,7 +882,9 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg)
        for (i=0 ; i<3 ; i++)
        {
                if (bits & (SU_PUNCH1<<i))
-                       MSG_WriteChar (msg, ent->v.punchangle[i]);
+                       MSG_WritePreciseAngle(msg, ent->v.punchangle[i]); // dpprotocol
+               if (bits & (SU_PUNCHVEC1<<i)) // dpprotocol
+                       MSG_WriteFloatCoord(msg, punchvector[i]); // dpprotocol
                if (bits & (SU_VELOCITY1<<i))
                        MSG_WriteChar (msg, ent->v.velocity[i]/16);
        }
@@ -1324,7 +1389,7 @@ void SV_SpawnServer (char *server)
        sv.state = ss_active;
        
 // run two frames to allow everything to settle
-       host_frametime = 0.1;
+       sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
        SV_Physics ();
        SV_Physics ();
 
index afe020c9a22037e655d88e07d74cdbea34b40160..7c41965a1a270343654804039ba749d6f9720fec 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -137,7 +137,7 @@ qboolean SV_RunThink (edict_t *ent)
        float   thinktime;
 
        thinktime = ent->v.nextthink;
-       if (thinktime <= 0 || thinktime > sv.time + host_frametime)
+       if (thinktime <= 0 || thinktime > sv.time + sv.frametime)
                return true;
                
        if (thinktime < sv.time)
@@ -392,7 +392,7 @@ void SV_AddGravity (edict_t *ent)
                ent_gravity = val->_float;
        else
                ent_gravity = 1.0;
-       ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
+       ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime;
 }
 
 
@@ -754,14 +754,14 @@ void SV_Physics_Pusher (edict_t *ent)
        oldltime = ent->v.ltime;
        
        thinktime = ent->v.nextthink;
-       if (thinktime < ent->v.ltime + host_frametime)
+       if (thinktime < ent->v.ltime + sv.frametime)
        {
                movetime = thinktime - ent->v.ltime;
                if (movetime < 0)
                        movetime = 0;
        }
        else
-               movetime = host_frametime;
+               movetime = sv.frametime;
 
        if (movetime)
        {
@@ -886,11 +886,11 @@ SV_WallFriction
 */
 void SV_WallFriction (edict_t *ent, trace_t *trace)
 {
-       vec3_t          forward, right, up;
+       vec3_t          forward;
        float           d, i;
        vec3_t          into, side;
        
-       AngleVectors (ent->v.v_angle, forward, right, up);
+       AngleVectors (ent->v.v_angle, forward, NULL, NULL);
        d = DotProduct (trace->plane.normal, forward);
        
        d += 0.5;
@@ -993,7 +993,7 @@ void SV_WalkMove (edict_t *ent)
        VectorCopy (ent->v.origin, oldorg);
        VectorCopy (ent->v.velocity, oldvel);
        
-       clip = SV_FlyMove (ent, host_frametime, &steptrace);
+       clip = SV_FlyMove (ent, sv.frametime, &steptrace);
 
        if ( !(clip & 2) )
                return;         // move didn't block on a step
@@ -1021,7 +1021,7 @@ void SV_WalkMove (edict_t *ent)
        VectorClear (upmove);
        VectorClear (downmove);
        upmove[2] = STEPSIZE;
-       downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
+       downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime;
 
 // move up
        SV_PushEntity (ent, upmove);    // FIXME: don't link?
@@ -1030,7 +1030,7 @@ void SV_WalkMove (edict_t *ent)
        ent->v.velocity[0] = oldvel[0];
        ent->v. velocity[1] = oldvel[1];
        ent->v. velocity[2] = 0;
-       clip = SV_FlyMove (ent, host_frametime, &steptrace);
+       clip = SV_FlyMove (ent, sv.frametime, &steptrace);
 
 // check for stuckness, possibly due to the limited precision of floats
 // in the clipping hulls
@@ -1121,14 +1121,14 @@ void SV_Physics_Client (edict_t *ent, int num)
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
-               SV_FlyMove (ent, host_frametime, NULL);
+               SV_FlyMove (ent, sv.frametime, NULL);
                break;
                
        case MOVETYPE_NOCLIP:
                if (!SV_RunThink (ent))
                        return;
                SV_CheckWater (ent);
-               VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+               VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
                break;
                
        default:
@@ -1221,8 +1221,8 @@ void SV_Physics_Noclip (edict_t *ent)
        if (!SV_RunThink (ent))
                return;
        
-       VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
-       VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
+       VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
+       VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin);
 
        SV_LinkEdict (ent, false);
 }
@@ -1301,10 +1301,10 @@ void SV_Physics_Toss (edict_t *ent)
                SV_AddGravity (ent);
 
 // move angles
-       VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
+       VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles);
 
 // move origin
-       VectorScale (ent->v.velocity, host_frametime, move);
+       VectorScale (ent->v.velocity, sv.frametime, move);
        trace = SV_PushEntity (ent, move);
        if (trace.fraction == 1)
                return;
@@ -1369,7 +1369,7 @@ void SV_Physics_Step (edict_t *ent)
 
                SV_AddGravity (ent);
                SV_CheckVelocity (ent);
-               SV_FlyMove (ent, host_frametime, NULL);
+               SV_FlyMove (ent, sv.frametime, NULL);
                SV_LinkEdict (ent, true);
 
                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
@@ -1477,7 +1477,7 @@ void SV_Physics (void)
                PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
        }
 
-       sv.time += host_frametime;
+       sv.time += sv.frametime;
 }
 
 
@@ -1488,10 +1488,6 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
        trace_t trace;
        vec3_t  move;
        vec3_t  end;
-       double  save_frametime;
-
-       save_frametime = host_frametime;
-       host_frametime = 0.05;
 
        memcpy(&tempent, ent, sizeof(edict_t));
        tent = &tempent;
@@ -1500,8 +1496,8 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
        {
                SV_CheckVelocity (tent);
                SV_AddGravity (tent);
-               VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
-               VectorScale (tent->v.velocity, host_frametime, move);
+               VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles);
+               VectorScale (tent->v.velocity, 0.05, move);
                VectorAdd (tent->v.origin, move, end);
                trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);   
                VectorCopy (trace.endpos, tent->v.origin);
@@ -1510,6 +1506,6 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
                        if (trace.ent != ignore)
                                break;
        }
-       host_frametime = save_frametime;
+       trace.fraction = 0; // not relevant
        return trace;
 }
index e76f78f944f74e6d8e1d3a76275520b7f0f308ee..496d0c02126ca6c65758f99423481002987e7bfe 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -149,7 +149,7 @@ void SV_UserFriction (void)
 
 // apply friction      
        control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
-       newspeed = speed - host_frametime*control*friction;
+       newspeed = speed - sv.frametime*control*friction;
        
        if (newspeed < 0)
                newspeed = 0;
@@ -181,7 +181,7 @@ void SV_Accelerate (vec3_t wishvel)
        VectorSubtract (wishvel, velocity, pushvec);
        addspeed = VectorNormalize (pushvec);
 
-       accelspeed = sv_accelerate.value*host_frametime*addspeed;
+       accelspeed = sv_accelerate.value*sv.frametime*addspeed;
        if (accelspeed > addspeed)
                accelspeed = addspeed;
        
@@ -198,7 +198,7 @@ void SV_Accelerate (void)
        addspeed = wishspeed - currentspeed;
        if (addspeed <= 0)
                return;
-       accelspeed = sv_accelerate.value*host_frametime*wishspeed;
+       accelspeed = sv_accelerate.value*sv.frametime*wishspeed;
        if (accelspeed > addspeed)
                accelspeed = addspeed;
        
@@ -218,8 +218,8 @@ void SV_AirAccelerate (vec3_t wishveloc)
        addspeed = wishspd - currentspeed;
        if (addspeed <= 0)
                return;
-//     accelspeed = sv_accelerate.value * host_frametime;
-       accelspeed = sv_accelerate.value*wishspeed * host_frametime;
+//     accelspeed = sv_accelerate.value * sv.frametime;
+       accelspeed = sv_accelerate.value*wishspeed * sv.frametime;
        if (accelspeed > addspeed)
                accelspeed = addspeed;
        
@@ -231,13 +231,24 @@ void SV_AirAccelerate (vec3_t wishveloc)
 void DropPunchAngle (void)
 {
        float   len;
+       eval_t  *val;
        
        len = VectorNormalizeLength (sv_player->v.punchangle);
        
-       len -= 10*host_frametime;
+       len -= 10*sv.frametime;
        if (len < 0)
                len = 0;
        VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle);
+       
+       if ((val = GETEDICTFIELDVALUE(sv_player, eval_punchvector)))
+       {
+               len = VectorNormalizeLength (val->vector);
+               
+               len -= 20*sv.frametime;
+               if (len < 0)
+                       len = 0;
+               VectorScale (val->vector, len, val->vector);
+       }
 }
 
 /*
@@ -279,7 +290,7 @@ void SV_WaterMove (void)
        speed = Length (velocity);
        if (speed)
        {
-               newspeed = speed - host_frametime * speed * sv_friction.value;
+               newspeed = speed - sv.frametime * speed * sv_friction.value;
                if (newspeed < 0)
                        newspeed = 0;   
                VectorScale (velocity, newspeed/speed, velocity);
@@ -298,7 +309,7 @@ void SV_WaterMove (void)
                return;
 
        VectorNormalize (wishvel);
-       accelspeed = sv_accelerate.value * wishspeed * host_frametime;
+       accelspeed = sv_accelerate.value * wishspeed * sv.frametime;
        if (accelspeed > addspeed)
                accelspeed = addspeed;
 
@@ -429,8 +440,7 @@ void SV_ClientThink (void)
 //
 // walk
 //
-       if ( (sv_player->v.waterlevel >= 2)
-       && (sv_player->v.movetype != MOVETYPE_NOCLIP) )
+       if ( (sv_player->v.waterlevel >= 2)     && (sv_player->v.movetype != MOVETYPE_NOCLIP) )
        {
                SV_WaterMove ();
                return;
index 8c8a595c9e57d7b6818ba073d7cac70496898117..90b04ed8ab97999fd7af88d72aeb48c55e3e9f6b 100644 (file)
--- a/sys_win.c
+++ b/sys_win.c
@@ -187,21 +187,15 @@ int Sys_FileWrite (int handle, void *data, int count)
 int    Sys_FileTime (char *path)
 {
        FILE    *f;
-       int             retval;
-
+       
        f = fopen(path, "rb");
-
        if (f)
        {
                fclose(f);
-               retval = 1;
-       }
-       else
-       {
-               retval = -1;
+               return 1;
        }
        
-       return retval;
+       return -1;
 }
 
 void Sys_mkdir (char *path)
diff --git a/vid.h b/vid.h
index b177ed8b33b7e2004e924cc8cfcb26966e343965..f0f49ab8e7116a6dcf2abe4ac2c822c32d0e6e77 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -45,15 +45,10 @@ extern      viddef_t        vid;                            // global video state
 extern void (*vid_menudrawfn)(void);
 extern void (*vid_menukeyfn)(int key);
 
-extern qboolean isG200;
-extern qboolean isRagePro;
-extern qboolean gl_mtexable;
-extern qboolean gl_arrays;
-
 void GL_Init (void);
 
 void VID_CheckMultitexture();
-void VID_CheckVertexArrays();
+void VID_CheckCVA();
 
 void   VID_Init ();
 // Called at startup
index f326228bb8647de4b940833c9d59149ef7daacc0..601387c1625991613ae96b094b9453ed708afcbf 100644 (file)
@@ -46,9 +46,6 @@
 #include <glide/sst1vid.h>
 
 
-unsigned               d_8to24table[256];
-unsigned char  d_15to8table[65536];
-
 cvar_t         vid_mode = {"vid_mode","0",false};
 
 viddef_t       vid;    // global video state
@@ -62,8 +59,6 @@ int   VID_options_items = 0;
 
 /*-----------------------------------------------------------------------*/
 
-int    texture_extension_number = 1;
-
 float          gldepthmin, gldepthmax;
 
 const char *gl_vendor;
@@ -71,17 +66,6 @@ const char *gl_renderer;
 const char *gl_version;
 const char *gl_extensions;
 
-void (*qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-void (*qglSelectTexture) (GLenum);
-
-int gl_mtex_enum = 0;
-
-// LordHavoc: in GLX these are never set, simply provided to make the rest of the code work
-qboolean isG200 = false;
-qboolean isRagePro = false;
-qboolean gl_mtexable = false;
-qboolean gl_arrays = false;
-
 /*-----------------------------------------------------------------------*/
 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
 {
@@ -122,11 +106,6 @@ void InitSig(void)
        signal(SIGTERM, signal_handler);
 }
 
-// LordHavoc: FIXME or something?
-void VID_CheckVertexArrays()
-{
-}
-
 /*
        VID_CheckMultitexture
 
@@ -165,7 +144,34 @@ void VID_CheckMultitexture()
        else
                Con_Printf ("none found\n");
        dlclose(dlhand);
-       dlhand = NULL;          
+       dlhand = NULL;
+}
+
+void VID_CheckCVA(void)
+{
+       qglLockArraysEXT = NULL;
+       qglUnlockArraysEXT = NULL;
+       gl_supportslockarrays = false;
+       if (COM_CheckParm("-nocva"))
+       {
+               Con_Printf("...compiled vertex arrays disabled\n");
+               return;
+       }
+       dlhand = dlopen (NULL, RTLD_LAZY);
+       if (dlhand == NULL)
+       {
+               Con_Printf("Unable to open symbol list for main program.\n");
+               return;
+       }
+       if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array"))
+       {
+               Con_Printf("...using compiled vertex arrays\n");
+               qglLockArraysEXT = (void *) dlsym(dlhand, "glLockArraysEXT");
+               qglUnlockArraysEXT = (void *) dlsym(dlhand, "glUnlockArraysEXT");
+               gl_supportslockarrays = true;
+       }
+       dlclose(dlhand);
+       dlhand = NULL;
 }
 
 
index c0af5028ea63bba8c7fedf1ab23f3f7063fd51b7..cb0b1be4effe2597797ce9a9ad4dc42462196a82 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -49,9 +49,6 @@ static GLXContext ctx = NULL;
 #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
 
 
-unsigned               d_8to24table[256];
-unsigned char  d_15to8table[65536];
-
 cvar_t vid_mode = {"vid_mode", "0", false};
 cvar_t vid_fullscreen = {"vid_fullscreen", "1"};
 
@@ -83,8 +80,6 @@ static qboolean vidmode_active = false;
 
 /*-----------------------------------------------------------------------*/
 
-int            texture_extension_number = 1;
-
 float          gldepthmin, gldepthmax;
 
 const char *gl_vendor;
@@ -92,20 +87,11 @@ const char *gl_renderer;
 const char *gl_version;
 const char *gl_extensions;
 
-void (*qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
-void (*qglSelectTexture) (GLenum);
-
 //static float vid_gamma = 1.0;
 
 // LordHavoc: ARB multitexture support
 int gl_mtex_enum = 0;
 
-// LordHavoc: in GLX these are never set, simply provided to make the rest of the code work
-qboolean isG200 = false;
-qboolean isRagePro = false;
-qboolean gl_mtexable = false;
-qboolean gl_arrays = false;
-
 /*-----------------------------------------------------------------------*/
 static int
 XLateKey(XKeyEvent *ev/*, qboolean modified*/)
@@ -453,55 +439,6 @@ void InitSig(void)
        signal(SIGTERM, signal_handler);
 }
 
-/*
-void (*qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (*qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (*qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (*qglArrayElement)(GLint i);
-void (*qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-void (*qglMTexCoord2f)(GLenum, GLfloat, GLfloat);
-void (*qglSelectTexture)(GLenum);
-
-void VID_CheckVertexArrays (void)
-{
-       void *prjobj;
-       if (COM_CheckParm("-novertex"))
-       {
-               Con_Printf("...vertex array support disabled\n");
-               return;
-       }
-       if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL)
-       {
-               Con_Printf("Unable to open symbol list for main program.\n");
-               return;
-       }
-       qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
-       if ((qglArrayElement = (void *) dlsym(prjobj, "glArrayElement"))
-        && (qglColorPointer = (void *) dlsym(prjobj, "glColorPointer"))
-//      && (qglDrawArrays = (void *) dlsym(prjobj, "glDrawArrays"))
-        && (qglDrawElements = (void *) dlsym(prjobj, "glDrawElements"))
-//      && (qglInterleavedArrays = (void *) dlsym(prjobj, "glInterleavedArrays"))
-        && (qglTexCoordPointer = (void *) dlsym(prjobj, "glTexCoordPointer"))
-        && (qglVertexPointer = (void *) dlsym(prjobj, "glVertexPointer"))
-               )
-       {
-               Con_Printf("...vertex array support detected\n");
-               gl_arrays = true;
-               dlclose(prjobj);
-               return;
-       }
-
-       Con_Printf("...vertex array support disabled (not detected - get a better driver)\n");
-       dlclose(prjobj);
-}
-*/
-
-// LordHavoc: require OpenGL 1.2.x
-void VID_CheckVertexArrays (void)
-{
-       gl_arrays = true;
-}
-
 void VID_CheckMultitexture(void) 
 {
        void *prjobj;
@@ -535,11 +472,37 @@ void VID_CheckMultitexture(void)
                gl_mtexable = true;
                gl_mtex_enum = TEXTURE0_SGIS;
        }
-       if (!gl_mtexable)
+       else
                Con_Printf("...multitexture disabled (not detected)\n");
        dlclose(prjobj);
 }
 
+void VID_CheckCVA(void)
+{
+       void *prjobj;
+       qglLockArraysEXT = NULL;
+       qglUnlockArraysEXT = NULL;
+       gl_supportslockarrays = false;
+       if (COM_CheckParm("-nocva"))
+       {
+               Con_Printf("...compiled vertex arrays disabled\n");
+               return;
+       }
+       if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL)
+       {
+               Con_Printf("Unable to open symbol list for main program.\n");
+               return;
+       }
+       if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array"))
+       {
+               Con_Printf("...using compiled vertex arrays\n");
+               qglLockArraysEXT = (void *) dlsym(prjobj, "glLockArraysEXT");
+               qglUnlockArraysEXT = (void *) dlsym(prjobj, "glUnlockArraysEXT");
+               gl_supportslockarrays = true;
+       }
+       dlclose(prjobj);
+}
+
 /*
 =================
 GL_BeginRendering
index 589c59dc4365d4751f98461be2e6bd1b0c889f95..47ac0546550a08c4d740456a3f86a7967d60cd20 100644 (file)
@@ -1,3 +1,17 @@
 
 #include "quakedef.h"
 
+// LordHavoc: these are only set in wgl
+qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh...
+qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200.
+
+// LordHavoc: compiled vertex array support
+qboolean gl_supportslockarrays = false;
+// LordHavoc: ARB multitexture support
+qboolean gl_mtexable = false;
+int gl_mtex_enum = 0;
+
+void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
+void (GLAPIENTRY *qglSelectTexture) (GLenum);
+void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count);
+void (GLAPIENTRY *qglUnlockArraysEXT) (void);
index 3ef91f208675be55c839b0ee065e9e70d5978c18..fe9ec2cbf0471adec62bad6aa2dd608c0e2651f9 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -113,14 +113,6 @@ char *VID_GetModeDescription (int mode);
 void ClearAllStates (void);
 void VID_UpdateWindowStatus (void);
 
-// LordHavoc: ARB multitexture support
-int gl_mtex_enum = 0;
-
-qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh...
-qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200.
-qboolean gl_mtexable = false;
-qboolean gl_arrays = false;
-
 //====================================
 
 cvar_t         vid_mode = {"vid_mode","0", false};
@@ -376,44 +368,11 @@ void VID_UpdateWindowStatus (void)
 
 //====================================
 
-void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
-void (GLAPIENTRY *qglArrayElement)(GLint i);
-void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-void (GLAPIENTRY *qglMTexCoord2f)(GLenum, GLfloat, GLfloat);
-void (GLAPIENTRY *qglSelectTexture)(GLenum);
-
-void VID_CheckVertexArrays (void)
-{
-       if (COM_CheckParm("-novertex"))
-       {
-               Con_Printf("...vertex array support disabled\n");
-               return;
-       }
-       if ((qglArrayElement = (void *) wglGetProcAddress("glArrayElement"))
-        && (qglColorPointer = (void *) wglGetProcAddress("glColorPointer"))
-//      && (qglDrawArrays = (void *) wglGetProcAddress("glDrawArrays"))
-        && (qglDrawElements = (void *) wglGetProcAddress("glDrawElements"))
-//      && (qglInterleavedArrays = (void *) wglGetProcAddress("glInterleavedArrays"))
-        && (qglTexCoordPointer = (void *) wglGetProcAddress("glTexCoordPointer"))
-        && (qglVertexPointer = (void *) wglGetProcAddress("glVertexPointer"))
-               )
-       {
-               Con_Printf("...vertex array support detected\n");
-               gl_arrays = true;
-               return;
-       }
-
-       Con_Printf("...vertex array support disabled (not detected - get a better driver)\n");
-}
-
-int            texture_extension_number = 1;
-
 void VID_CheckMultitexture(void) 
 {
        qglMTexCoord2f = NULL;
        qglSelectTexture = NULL;
+       gl_mtexable = false;
        // Check to see if multitexture is disabled
        if (COM_CheckParm("-nomtex"))
        {
@@ -437,10 +396,29 @@ void VID_CheckMultitexture(void)
                gl_mtexable = true;
                gl_mtex_enum = TEXTURE0_SGIS;
        }
-       if (!gl_mtexable)
+       else
                Con_Printf("...multitexture disabled (not detected)\n");
 }
 
+void VID_CheckCVA(void)
+{
+       qglLockArraysEXT = NULL;
+       qglUnlockArraysEXT = NULL;
+       gl_supportslockarrays = false;
+       if (COM_CheckParm("-nocva"))
+       {
+               Con_Printf("...compiled vertex arrays disabled\n");
+               return;
+       }
+       if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array"))
+       {
+               Con_Printf("...using compiled vertex arrays\n");
+               qglLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT");
+               qglUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT");
+               gl_supportslockarrays = true;
+       }
+}
+
 /*
 =================
 GL_BeginRendering
diff --git a/view.c b/view.c
index bcff7fff80468c62ad2399af0a1cf32506120f76..5eddbe637856bd74ee2eca45eafca7e5d7a6a8d5 100644 (file)
--- a/view.c
+++ b/view.c
@@ -41,6 +41,8 @@ cvar_t        v_kicktime = {"v_kicktime", "0.5", false};
 cvar_t v_kickroll = {"v_kickroll", "0.6", false};
 cvar_t v_kickpitch = {"v_kickpitch", "0.6", false};
 
+cvar_t v_punch = {"v_punch", "1", false};
+
 cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false};
 cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false};
 cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false};
@@ -69,15 +71,14 @@ V_CalcRoll
 Used by view and sv_user
 ===============
 */
-vec3_t forward, right, up;
-
 float V_CalcRoll (vec3_t angles, vec3_t velocity)
 {
+       vec3_t  right;
        float   sign;
        float   side;
        float   value;
        
-       AngleVectors (angles, forward, right, up);
+       AngleVectors (angles, NULL, right, NULL);
        side = DotProduct (velocity, right);
        sign = side < 0 ? -1 : 1;
        side = fabs(side);
@@ -189,7 +190,7 @@ void V_DriftPitch (void)
                if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value)
                        cl.driftmove = 0;
                else
-                       cl.driftmove += host_frametime;
+                       cl.driftmove += cl.frametime;
        
                if ( cl.driftmove > v_centermove.value)
                {
@@ -206,10 +207,10 @@ void V_DriftPitch (void)
                return;
        }
 
-       move = host_frametime * cl.pitchvel;
-       cl.pitchvel += host_frametime * v_centerspeed.value;
+       move = cl.frametime * cl.pitchvel;
+       cl.pitchvel += cl.frametime * v_centerspeed.value;
        
-//Con_Printf ("move: %f (%f)\n", move, host_frametime);
+//Con_Printf ("move: %f (%f)\n", move, cl.frametime);
 
        if (delta > 0)
        {
@@ -262,7 +263,7 @@ void V_ParseDamage (void)
        int             armor, blood;
        vec3_t  from;
        int             i;
-       vec3_t  forward, right, up;
+       vec3_t  forward, right;
        entity_t        *ent;
        float   side;
        float   count;
@@ -276,7 +277,7 @@ void V_ParseDamage (void)
        if (count < 10)
                count = 10;
 
-       cl.faceanimtime = cl.time + 0.2;                // but sbar face into pain frame
+       cl.faceanimtime = cl.time + 0.2;                // put sbar face into pain frame
 
        if (gl_polyblend.value)
        {
@@ -314,7 +315,7 @@ void V_ParseDamage (void)
        VectorSubtract (from, ent->origin, from);
        VectorNormalize (from);
        
-       AngleVectors (ent->angles, forward, right, up);
+       AngleVectors (ent->angles, forward, right, NULL);
 
        side = DotProduct (from, right);
        v_dmg_roll = count*side*v_kickroll.value;
@@ -567,6 +568,7 @@ CalcGunAngle
 */
 void CalcGunAngle (void)
 {      
+       /*
        float   yaw, pitch, move;
        static float oldyaw = 0;
        static float oldpitch = 0;
@@ -584,7 +586,7 @@ void CalcGunAngle (void)
                pitch = 10;
        if (pitch < -10)
                pitch = -10;
-       move = host_frametime*20;
+       move = cl.frametime*20;
        if (yaw > oldyaw)
        {
                if (oldyaw + move < yaw)
@@ -612,6 +614,9 @@ void CalcGunAngle (void)
 
        cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw;
        cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
+       */
+       cl.viewent.angles[YAW] = r_refdef.viewangles[YAW];
+       cl.viewent.angles[PITCH] = -r_refdef.viewangles[PITCH];
 
        cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;
        cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value;
@@ -679,7 +684,7 @@ void V_CalcViewRoll (void)
        {
                r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll;
                r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch;
-               v_dmg_time -= host_frametime;
+               v_dmg_time -= cl.frametime;
        }
 
        if (cl.stats[STAT_HEALTH] <= 0)
@@ -711,7 +716,7 @@ void V_CalcIntermissionRefdef (void)
        VectorCopy (ent->angles, r_refdef.viewangles);
        view->model = NULL;
 
-// allways idle in intermission
+// always idle in intermission
        old = v_idlescale.value;
        v_idlescale.value = 1;
        V_AddIdle ();
@@ -729,7 +734,7 @@ void V_CalcRefdef (void)
 {
        entity_t        *ent, *view;
        int                     i;
-       vec3_t          forward, right, up;
+       vec3_t          forward;
        vec3_t          angles;
        float           bob;
        static float oldz = 0;
@@ -777,7 +782,7 @@ void V_CalcRefdef (void)
        angles[YAW] = ent->angles[YAW];
        angles[ROLL] = ent->angles[ROLL];
 
-       AngleVectors (angles, forward, right, up);
+       AngleVectors (angles, forward, NULL, NULL);
 
        V_BoundOffsets ();
                
@@ -806,6 +811,7 @@ void V_CalcRefdef (void)
 
 // set up the refresh position
        if (!intimerefresh)
+       if (v_punch.value)
        {
                VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles);
        }
@@ -831,6 +837,9 @@ if (cl.onground && ent->origin[2] - oldz > 0)
 else
        oldz = ent->origin[2];
 
+// LordHavoc: origin view kick
+       VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg);
+
        if (chase_active.value)
                Chase_Update ();
 }
@@ -900,6 +909,8 @@ void V_Init (void)
        Cvar_RegisterVariable (&v_kicktime);
        Cvar_RegisterVariable (&v_kickroll);
        Cvar_RegisterVariable (&v_kickpitch);   
+
+       Cvar_RegisterVariable (&v_punch);
 }
 
 
diff --git a/world.c b/world.c
index eea796c7c0453539584d31f03ab6b608bd675858..1c4b74bb1164f292f2dd6cde6cf598f3fa1f2a78 100644 (file)
--- a/world.c
+++ b/world.c
@@ -538,7 +538,19 @@ POINT TESTING IN HULLS
 ===============================================================================
 */
 
-// SV_HullPointContents moved to cpu_noasm.c
+/*
+==================
+SV_HullPointContents
+
+==================
+*/
+int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
+{
+       while (num >= 0)
+               num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist];
+       
+       return num;
+}
 
 /*
 ============
diff --git a/zone.c b/zone.c
index e48844673e1fb7708086ad89122faac14cf5acf6..556c709496ec24813ad2bad6045fb78988186821 100644 (file)
--- a/zone.c
+++ b/zone.c
@@ -825,7 +825,7 @@ void *Cache_Alloc (cache_user_t *c, int size, char *name)
        cache_system_t  *cs;
 
        if (c->data)
-               Sys_Error ("Cache_Alloc: allready allocated");
+               Sys_Error ("Cache_Alloc: already allocated");
        
        if (size <= 0)
                Sys_Error ("Cache_Alloc: size %i", size);