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 2189396..9bab547 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 13fbed5..85873db 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 f3432d2..21f084f 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 1abbfd2..7a6623a 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 0d776ab..368bf3d 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 518b1ef..1046cbc 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 44fbedf..9abe25e 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 6bb726f..85cd55c 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 f9eab24..da1daa6 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 1430e05..cc4bfd8 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 a9dad19..502f4cd 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 db48c0c..bb68015 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 009b747..4a961b2 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 322c9b8..267b9e9 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 e9899a4..93622b1 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 5a1e715..f2c9465 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 42b68fc..99e7114 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 2f53d5c..4eb8baf 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 429b97b..24ece5f 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 11a1c48..c4a257d 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 7276632..bde929e 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 23b7047..026861d 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 e7c19f3..a5644a3 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 5b37779..c3ccd0d 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 b6d2d32..c9e0e03 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 e179da6..3d687b6 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 4783279..f9f3225 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 622ff52..7b05a23 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 ebaafd5..60a9759 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 524d0d0..ea8460d 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 9b9f4fc..fb055bb 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 6d54c3f..ea8fb19 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 ba4f3d4..9d847ad 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&