]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
updated to version 1.50, build 75.
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 17 Nov 2000 08:35:39 +0000 (08:35 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 17 Nov 2000 08:35:39 +0000 (08:35 +0000)
change log as best I can remember:
rewrote model loading and rendering
multi-pass colormapping on any model (NO UPLOADS!)
fullbrights on models (feature of new multi-pass model renderer)
rewrote texture management
rewrote texture uploading
heavily optimized static light sampling
fancy new crosshair
fixed network angle rounding (shots are fired where you're pointing, not down and to the right)
HL map hull sizes are supported (still sink into grates though)
removal of some commented out junk
other minor stuff I can't remember now

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

43 files changed:
buildnumber.c
cl_main.c
cl_parse.c
cl_tent.c
client.h
common.c
draw.h
gl_draw.c
gl_models.c [new file with mode: 0644]
gl_poly.c
gl_rmain.c
gl_rmisc.c
gl_rsurf.c
gl_screen.c
gl_textures.c [new file with mode: 0644]
gl_warp.c
glquake.h
host.c
host_cmd.c
image.c
image.h [new file with mode: 0644]
model_alias.c
model_alias.h
model_brush.c
model_shared.c
model_shared.h
modelgen.h
net_wins.c
pr_exec.c
quakedef.h
r_crosshairs.c [new file with mode: 0644]
r_light.c
r_light.h [new file with mode: 0644]
r_modules.c [new file with mode: 0644]
r_modules.h [new file with mode: 0644]
r_part.c
render.h
sv_main.c
vid_glx.c
vid_shared.c
vid_wgl.c
view.c
world.c

index f2fa7865810506a43f284c53ed557b7532759ece..cd041315d4410c8fd20ef4651eb5820187dca09c 100644 (file)
@@ -1,4 +1,4 @@
 
-#define BUILDNUMBER 73
+#define BUILDNUMBER 75
 
 int buildnumber = BUILDNUMBER;
index 34a0b42f3e8aed6b24bd192d1b3cb618ed713b50..538b19c511ab797ce5acefd7c1e74db7d527d530 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -466,9 +466,31 @@ void CL_RelinkEntities (void)
                if (ent->msgtime != cl.mtime[0])
                {
                        ent->model = NULL;
+                       // LordHavoc: free on the same frame, not the next
+                       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)
index 75d53fe7dec5bfa883829778a57c4b86b0ce2afb..028dda200500bbcde5659ca024179f697ebab831 100644 (file)
@@ -105,7 +105,7 @@ entity_t    *CL_EntityNum (int num)
                        Host_Error ("CL_EntityNum: %i is an invalid number",num);
                while (cl.num_entities<=num)
                {
-                       cl_entities[cl.num_entities].colormap = 0; //vid.colormap;
+                       cl_entities[cl.num_entities].colormap = -1; // no special coloring
                        cl.num_entities++;
                }
        }
@@ -516,8 +516,6 @@ void CL_ParseUpdate (int bits)
                        ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
                else
                        forcelink = true;       // hack to make null model players work
-               if (num > 0 && num <= cl.maxclients)
-                       R_TranslatePlayerSkin(num - 1);
        }
 
        ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
@@ -525,20 +523,18 @@ void CL_ParseUpdate (int bits)
        i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
        ent->deltabaseline.colormap = i;
        if (!i)
-               ent->colormap = 0; //vid.colormap;
+               ent->colormap = -1; // no special coloring
        else
        {
                if (i > cl.maxclients)
                        Host_Error ("i >= cl.maxclients");
-               ent->colormap = i; //vid.colormap; // cl.scores[i-1].translations;
+               ent->colormap = cl.scores[i-1].colors; // color it
        }
 
        skin = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
        if (skin != ent->skinnum)
        {
                ent->skinnum = skin;
-               if (num > 0 && num <= cl.maxclients)
-                       R_TranslatePlayerSkin(num - 1);
        }
        ent->deltabaseline.skin = skin;
 
@@ -769,7 +765,7 @@ void CL_ParseStatic (void)
 // copy it to the current state
        ent->model = cl.model_precache[ent->baseline.modelindex];
        ent->frame = ent->baseline.frame;
-       ent->colormap = 0; //vid.colormap;
+       ent->colormap = -1; // no special coloring
        ent->skinnum = ent->baseline.skin;
        ent->effects = ent->baseline.effects;
        ent->alpha = 1;
@@ -963,7 +959,6 @@ void CL_ParseServerMessage (void)
                        if (i >= cl.maxclients)
                                Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
                        cl.scores[i].colors = MSG_ReadByte ();
-                       R_TranslatePlayerSkin(i);
                        break;
                        
                case svc_particle:
index d60ed56e189e9e38c6b950943f6c892e5e780c96..d6d424757680cff6308836b318dc01037c1b2e70 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -104,6 +104,21 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count);
 void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel);
 void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type);
 
+// attempts to find the nearest non-solid location, used for explosions mainly
+void FindNonSolidLocation(vec3_t pos)
+{
+       if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[0]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[0]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[0]-=1;
+       pos[1]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[1]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[1]-=1;
+       pos[2]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[2]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+       pos[2]-=1;
+}
+
 /*
 =================
 CL_ParseTEnt
@@ -345,6 +360,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_ParticleExplosion (pos, false);
 //             R_BlastParticles (pos, 120, 120);
                dl = CL_AllocDlight (0);
@@ -360,6 +376,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_ParticleExplosion (pos, false);
 //             R_BlastParticles (pos, 120, 480);
                dl = CL_AllocDlight (0);
@@ -376,6 +393,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_ParticleExplosion (pos, true);
                dl = CL_AllocDlight (0);
                VectorCopy (pos, dl->origin);
@@ -391,6 +409,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_ParticleExplosion (pos, false);
 //             R_BlastParticles (pos, 120, 120);
                dl = CL_AllocDlight (0);
@@ -406,6 +425,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_ParticleExplosion (pos, false);
 //             R_BlastParticles (pos, 120, 120);
                dl = CL_AllocDlight (0);
@@ -421,6 +441,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                R_BlobExplosion (pos);
 //             R_BlastParticles (pos, 120, 120);
 
@@ -475,6 +496,7 @@ void CL_ParseTEnt (void)
                pos[0] = MSG_ReadCoord ();
                pos[1] = MSG_ReadCoord ();
                pos[2] = MSG_ReadCoord ();
+               FindNonSolidLocation(pos);
                colorStart = MSG_ReadByte ();
                colorLength = MSG_ReadByte ();
                R_ParticleExplosion2 (pos, colorStart, colorLength);
@@ -514,8 +536,7 @@ entity_t *CL_NewTempEntity (void)
        cl_visedicts[cl_numvisedicts] = ent;
        cl_numvisedicts++;
 
-//     ent->colormap = vid.colormap;
-       ent->colormap = 0;
+       ent->colormap = -1; // no special coloring
        ent->scale = 1;
        ent->alpha = 1;
        ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
index 45ae787e485afbac37440f36ff602054d85f9866..563f3cd07b262d740a41ead32e83d5cfff5a1dd4 100644 (file)
--- a/client.h
+++ b/client.h
@@ -41,7 +41,7 @@ typedef struct
        float   entertime;
        int             frags;
        int             colors;                 // two 4 bit fields
-       byte    translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
+//     byte    translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
 } scoreboard_t;
 
 typedef struct
@@ -65,20 +65,7 @@ typedef struct
 
 #define        SIGNONS         4                       // signon messages to receive before connected
 
-// LordHavoc: 256 dynamic lights
-#define        MAX_DLIGHTS             256
-typedef struct
-{
-       vec3_t  origin;
-       float   radius;
-       float   die;                            // stop lighting after this time
-       float   decay;                          // drop this each second
-       float   minlight;                       // don't add when contributing less
-       int             key;
-       vec3_t  color;                          // LordHavoc: colored lighting
-       qboolean        dark;                   // subtracts light instead of adding
-} dlight_t;
-
+#include "r_light.h"
 
 #define        MAX_BEAMS       24
 typedef struct
index 2c9c8cc11c07c6d42eba517bb339d6b651abeaca..e31b48d7605b8d089bd2c87dc3d472e9806ce31f 100644 (file)
--- a/common.c
+++ b/common.c
@@ -588,17 +588,18 @@ void MSG_WriteCoord (sizebuf_t *sb, float f)
        if (dpprotocol)
                MSG_WriteFloat(sb, f);
        else
-               MSG_WriteShort (sb, (int)(f*8));
+               MSG_WriteShort (sb, (int)(f*8.0f + 0.5f));
 }
 
 void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
 {
-       MSG_WriteShort (sb, (int) (f*65536.0f/360) & 65535);
+       MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
 }
 
+// LordHavoc: round to nearest value, rather than rounding down, fixes crosshair problem
 void MSG_WriteAngle (sizebuf_t *sb, float f)
 {
-       MSG_WriteByte (sb, ((int)f*256/360) & 255);
+       MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
 }
 
 //
diff --git a/draw.h b/draw.h
index db8a8601876301fc2d5540afd2ef3f8bec5c4399..ddb8e35b05b5f18e21bee7ba553dad77bb25323d 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -25,6 +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, float x, float y, float width, float height);
 void Draw_Pic (int x, int y, qpic_t *pic);
 void Draw_TransPic (int x, int y, qpic_t *pic);
 void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
index 7777801f6431fe88361e152ddd579dd34821177d..69c8d7b83f727edd77a7d7f1b73bfada507f5e7c 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -28,15 +28,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 extern unsigned char d_15to8table[65536];
 
 cvar_t         qsg_version = {"qsg_version", "1"};
-cvar_t         gl_max_size = {"gl_max_size", "1024"};
-cvar_t         gl_picmip = {"gl_picmip", "0"};
 cvar_t         gl_conalpha = {"gl_conalpha", "1"};
-cvar_t         gl_lerpimages = {"gl_lerpimages", "1"};
 
 byte           *draw_chars;                            // 8*8 graphic characters
 qpic_t         *draw_disc;
 
-int                    translate_texture;
+//int                  translate_texture;
 int                    char_texture;
 
 typedef struct
@@ -48,29 +45,6 @@ typedef struct
 byte           conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
 qpic_t         *conback = (qpic_t *)&conback_buffer;
 
-int            gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
-int            gl_filter_max = GL_LINEAR;
-
-
-int            texels;
-
-typedef struct
-{
-       int             texnum;
-       char    identifier[64];
-       int             width, height;
-       qboolean        mipmap;
-// LordHavoc: 32bit textures
-       int             bytesperpixel;
-// LordHavoc: CRC to identify cache mismatchs
-       int             crc;
-       int             lerped; // whether this texture was uploaded with or without interpolation
-} gltexture_t;
-
-#define        MAX_GLTEXTURES  4096
-gltexture_t    gltextures[MAX_GLTEXTURES];
-int                    numgltextures;
-
 /*
 =============================================================================
 
@@ -89,7 +63,6 @@ int                   numgltextures;
 int                    scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
 byte           scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
 qboolean       scrap_dirty;
-int                    scrap_texnum;
 
 // returns a texture number and the position inside it
 int Scrap_AllocBlock (int w, int h, int *x, int *y)
@@ -134,6 +107,7 @@ int Scrap_AllocBlock (int w, int h, int *x, int *y)
 }
 
 int    scrap_uploads;
+int scraptexnum[MAX_SCRAPS];
 
 void Scrap_Upload (void)
 {
@@ -142,10 +116,7 @@ void Scrap_Upload (void)
        scrap_uploads++;
 
        for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
-       {
-               glBindTexture(GL_TEXTURE_2D, scrap_texnum + texnum);
-               GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
-       }
+               scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
        scrap_dirty = false;
 }
 
@@ -191,8 +162,9 @@ qpic_t *Draw_PicFromWad (char *name)
                for (i=0 ; i<p->height ; i++)
                        for (j=0 ; j<p->width ; j++, k++)
                                scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
-               texnum += scrap_texnum;
-               gl->texnum = texnum;
+               if (!scraptexnum[texnum])
+                       scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
+               gl->texnum = scraptexnum[texnum];
                gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
                gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
                gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
@@ -200,9 +172,6 @@ qpic_t *Draw_PicFromWad (char *name)
 
                pic_count++;
                pic_texels += p->width*p->height;
-               // LordHavoc: LINEAR interpolation
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
        else
        {
@@ -211,9 +180,6 @@ qpic_t *Draw_PicFromWad (char *name)
                gl->sh = 1;
                gl->tl = 0;
                gl->th = 1;
-               // LordHavoc: LINEAR interpolation
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //NEAREST);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //NEAREST);
        }
        return p;
 }
@@ -267,7 +233,7 @@ qpic_t      *Draw_CachePic (char *path)
        return &pic->pic;
 }
 
-
+/*
 void Draw_CharToConback (int num, byte *dest)
 {
        int             row, col;
@@ -291,69 +257,7 @@ void Draw_CharToConback (int num, byte *dest)
        }
 
 }
-
-typedef struct
-{
-       char *name;
-       int     minimize, maximize;
-} glmode_t;
-
-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},
-       {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
-       {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
-       {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
-};
-
-/*
-===============
-Draw_TextureMode_f
-===============
 */
-void Draw_TextureMode_f (void)
-{
-       int             i;
-       gltexture_t     *glt;
-
-       if (Cmd_Argc() == 1)
-       {
-               for (i=0 ; i< 6 ; i++)
-                       if (gl_filter_min == modes[i].minimize)
-                       {
-                               Con_Printf ("%s\n", modes[i].name);
-                               return;
-                       }
-               Con_Printf ("current filter is unknown???\n");
-               return;
-       }
-
-       for (i=0 ; i< 6 ; i++)
-       {
-               if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
-                       break;
-       }
-       if (i == 6)
-       {
-               Con_Printf ("bad filter name\n");
-               return;
-       }
-
-       gl_filter_min = modes[i].minimize;
-       gl_filter_max = modes[i].maximize;
-
-       // change all the existing mipmap texture objects
-       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
-       {
-               if (glt->mipmap)
-               {
-                       glBindTexture(GL_TEXTURE_2D, glt->texnum);
-                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
-               }
-       }
-}
 
 extern void LoadSky_f(void);
 
@@ -366,101 +270,85 @@ Draw_Init
 */
 void rmain_registercvars();
 extern int buildnumber;
-void Draw_Init (void)
+
+void gl_draw_start()
 {
        int             i;
-       qpic_t  *cb;
-       byte    *dest;
-       int             x, y;
-       char    ver[40];
        glpic_t *gl;
-       int             start;
-
-       Cvar_RegisterVariable (&qsg_version);
-       Cvar_RegisterVariable (&gl_max_size);
-       Cvar_RegisterVariable (&gl_picmip);
-       Cvar_RegisterVariable (&gl_conalpha);
-       Cvar_RegisterVariable (&gl_lerpimages);
-
-       // 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");
-
-       Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
-
-       Cmd_AddCommand ("loadsky", &LoadSky_f);
 
        // load the console background and the charset
        // by hand, because we need to write the version
        // string into the background before turning
        // it into a texture
-       draw_chars = W_GetLumpName ("conchars");
-       for (i=0 ; i<256*64 ; i++)
-               if (draw_chars[i] == 0)
-                       draw_chars[i] = 255;    // proper transparent color
+       char_texture = loadtextureimage ("conchars", 0, 0, false, false);
+       if (!char_texture)
+       {
+               draw_chars = W_GetLumpName ("conchars");
+               for (i=0 ; i<256*64 ; i++)
+                       if (draw_chars[i] == 0)
+                               draw_chars[i] = 255;    // proper transparent color
 
-       // now turn them into textures
-       char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
+               // now turn them into textures
+               char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
+       }
 
-       start = Hunk_LowMark();
+       gl = (glpic_t *)conback->data;
+       gl->texnum = loadtextureimage("gfx/conback", 0, 0, false, false);
+       gl->sl = 0;
+       gl->sh = 1;
+       gl->tl = 0;
+       gl->th = 1;
+       conback->width = vid.width;
+       conback->height = vid.height;
+
+       memset(scraptexnum, 0, sizeof(scraptexnum));
+
+       // get the other pics we need
+       draw_disc = Draw_PicFromWad ("disc");
+}
 
-       cb = (qpic_t *)COM_LoadMallocFile ("gfx/conback.lmp", false);
-       if (!cb)
-               Sys_Error ("Couldn't load gfx/conback.lmp");
-       SwapPic (cb);
+void gl_draw_shutdown()
+{
+}
+
+char engineversion[40];
+int engineversionx, engineversiony;
+
+extern void GL_Textures_Init();
+void GL_Draw_Init (void)
+{
+       int i;
+       Cvar_RegisterVariable (&qsg_version);
+       Cvar_RegisterVariable (&gl_conalpha);
+
+       Cmd_AddCommand ("loadsky", &LoadSky_f);
 
-       // hack the version number directly into the pic
 #ifdef NEHAHRA
 #if defined(__linux__)
-       sprintf (ver, "DPNehahra Linux GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DPNehahra Linux   GL %.2f build %3i", (float) VERSION, buildnumber);
 #elif defined(WIN32)
-       sprintf (ver, "DPNehahra Windows GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DPNehahra Windows GL %.2f build %3i", (float) VERSION, buildnumber);
 #else
-       sprintf (ver, "DPNehahra Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DPNehahra Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
 #endif
 #else
 #if defined(__linux__)
-       sprintf (ver, "DarkPlaces Linux GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DarkPlaces Linux   GL %.2f build %3i", (float) VERSION, buildnumber);
 #elif defined(WIN32)
-       sprintf (ver, "DarkPlaces Windows GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
 #else
-       sprintf (ver, "DarkPlaces Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
+       sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
 #endif
 #endif
-       dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
-       y = strlen(ver);
-       for (x=0 ; x<y ; x++)
-               Draw_CharToConback (ver[x], dest+(x<<3));
-
-       gl = (glpic_t *)conback->data;
-       gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1);
-       gl->sl = 0;
-       gl->sh = 1;
-       gl->tl = 0;
-       gl->th = 1;
-       conback->width = vid.width;
-       conback->height = vid.height;
-
-       // free loaded console
-       free(cb);
-
-       // save a texture slot for translated picture
-       translate_texture = texture_extension_number++;
+       for (i = 0;i < 40 && engineversion[i];i++)
+               engineversion[i] += 0x80; // shift to orange
+       engineversionx = vid.width - strlen(engineversion) * 8 - 8;
+       engineversiony = vid.height - 8;
 
-       // save slots for scraps
-       scrap_texnum = texture_extension_number;
-       texture_extension_number += MAX_SCRAPS;
-
-       //
-       // get the other pics we need
-       //
-       draw_disc = Draw_PicFromWad ("disc");
-
-       rmain_registercvars();
+       GL_Textures_Init();
+       R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown);
 }
 
-
 /*
 ================
 Draw_Character
@@ -566,6 +454,30 @@ void Draw_String (int x, int y, char *str, int maxlen)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 }
 
+void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, float x, float y, float width, float height)
+{
+       glDisable(GL_ALPHA_TEST);
+//     glEnable (GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+//     glCullFace(GL_FRONT);
+       glColor4f(red,green,blue,alpha);
+       glBindTexture(GL_TEXTURE_2D, texnum);
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+       glBegin (GL_QUADS);
+       glTexCoord2f (0, 0);
+       glVertex2f (x, y);
+       glTexCoord2f (1, 0);
+       glVertex2f (x+width, y);
+       glTexCoord2f (1, 1);
+       glVertex2f (x+width, y+height);
+       glTexCoord2f (0, 1);
+       glVertex2f (x, y+height);
+       glEnd ();
+       glColor3f(1,1,1);
+//     glEnable(GL_ALPHA_TEST);
+//     glDisable (GL_BLEND);
+}
+
 /*
 =============
 Draw_AlphaPic
@@ -660,8 +572,6 @@ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
        byte                    *src;
        int                             p;
 
-       glBindTexture(GL_TEXTURE_2D, translate_texture);
-
        c = pic->width * pic->height;
 
        dest = trans;
@@ -678,10 +588,7 @@ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
                }
        }
 
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
-
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glBindTexture(GL_TEXTURE_2D, GL_LoadTexture ("translatedplayerpic", 64, 64, (void *) trans, false, true, 1));
 
        glColor3f(0.8,0.8,0.8);
        glBegin (GL_QUADS);
@@ -713,6 +620,8 @@ void Draw_ConsoleBackground (int lines)
        else
                Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
        //      Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
+       // LordHavoc: draw version
+       Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
 }
 
 /*
@@ -845,587 +754,3 @@ void SHOWLMP_clear()
        for (i = 0;i < SHOWLMP_MAXLABELS;i++)
                showlmp[i].isactive = false;
 }
-
-//====================================================================
-
-/*
-================
-GL_FindTexture
-================
-*/
-int GL_FindTexture (char *identifier)
-{
-       int             i;
-       gltexture_t     *glt;
-
-       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
-       {
-               if (!strcmp (identifier, glt->identifier))
-                       return gltextures[i].texnum;
-       }
-
-       return -1;
-}
-
-extern byte qgamma[];
-
-// LordHavoc: gamma correction and improved resampling
-void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
-{
-       int             j, xi, oldx = 0;
-       float   f, fstep, l1, l2;
-       fstep = (float) inwidth/outwidth;
-       for (j = 0,f = 0;j < outwidth;j++, f += fstep)
-       {
-               xi = (int) f;
-               if (xi != oldx)
-               {
-                       in += (xi - oldx) * 4;
-                       oldx = xi;
-               }
-               if (xi < (inwidth-1))
-               {
-                       l2 = f - xi;
-                       l1 = 1 - l2;
-                       *out++ = qgamma[(byte) (in[0] * l1 + in[4] * l2)];
-                       *out++ = qgamma[(byte) (in[1] * l1 + in[5] * l2)];
-                       *out++ = qgamma[(byte) (in[2] * l1 + in[6] * l2)];
-                       *out++ =        (byte) (in[3] * l1 + in[7] * l2) ;
-               }
-               else // last pixel of the line has no pixel to lerp to
-               {
-                       *out++ = qgamma[in[0]];
-                       *out++ = qgamma[in[1]];
-                       *out++ = qgamma[in[2]];
-                       *out++ =        in[3] ;
-               }
-       }
-}
-
-/*
-================
-GL_ResampleTexture
-================
-*/
-void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight)
-{
-       // LordHavoc: gamma correction and greatly improved resampling
-       if (gl_lerpimages.value)
-       {
-               int             i, j, yi, oldy;
-               byte    *inrow, *out, *row1, *row2;
-               float   f, fstep, l1, l2;
-               out = outdata;
-               fstep = (float) inheight/outheight;
-
-               row1 = malloc(outwidth*4);
-               row2 = malloc(outwidth*4);
-               inrow = indata;
-               oldy = 0;
-               GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
-               GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
-               for (i = 0, f = 0;i < outheight;i++,f += fstep)
-               {
-                       yi = (int) f;
-                       if (yi != oldy)
-                       {
-                               inrow = (byte *)((int)indata + inwidth*4*yi);
-                               if (yi == oldy+1)
-                                       memcpy(row1, row2, outwidth*4);
-                               else
-                                       GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
-                               if (yi < (inheight-1))
-                                       GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
-                               else
-                                       memcpy(row2, row1, outwidth*4);
-                               oldy = yi;
-                       }
-                       if (yi < (inheight-1))
-                       {
-                               l2 = f - yi;
-                               l1 = 1 - l2;
-                               for (j = 0;j < outwidth;j++)
-                               {
-                                       *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
-                                       *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
-                                       *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
-                                       *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
-                               }
-                               row1 -= outwidth*4;
-                               row2 -= outwidth*4;
-                       }
-                       else // last line has no pixels to lerp to
-                       {
-                               for (j = 0;j < outwidth;j++)
-                               {
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
-                                       *out++ = *row1++;
-                               }
-                               row1 -= outwidth*4;
-                       }
-               }
-               free(row1);
-               free(row2);
-       }
-       else
-       {
-               int             i, j;
-               unsigned        frac, fracstep;
-               byte    *inrow, *out, *inpix;
-               out = outdata;
-
-               fracstep = inwidth*0x10000/outwidth;
-               for (i=0 ; i<outheight ; i++)
-               {
-                       inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
-                       frac = fracstep >> 1;
-                       for (j=0 ; j<outwidth ; j+=4)
-                       {
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
-                       }
-               }
-       }
-}
-
-/*
-================
-GL_Resample8BitTexture -- JACK
-================
-*/
-void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
-{
-       int             i, j;
-       unsigned        char *inrow;
-       unsigned        frac, fracstep;
-
-       fracstep = inwidth*0x10000/outwidth;
-       for (i=0 ; i<outheight ; i++, out += outwidth)
-       {
-               inrow = in + inwidth*(i*inheight/outheight);
-               frac = fracstep >> 1;
-               for (j=0 ; j<outwidth ; j+=4)
-               {
-                       out[j] = inrow[frac>>16];
-                       frac += fracstep;
-                       out[j+1] = inrow[frac>>16];
-                       frac += fracstep;
-                       out[j+2] = inrow[frac>>16];
-                       frac += fracstep;
-                       out[j+3] = inrow[frac>>16];
-                       frac += fracstep;
-               }
-       }
-}
-
-
-/*
-================
-GL_MipMap
-
-Operates in place, quartering the size of the texture
-================
-*/
-void GL_MipMap (byte *in, int width, int height)
-{
-       int             i, j;
-       byte    *out;
-
-       width <<=2;
-       height >>= 1;
-       out = in;
-       for (i=0 ; i<height ; i++, in+=width)
-       {
-               for (j=0 ; j<width ; j+=8, out+=4, in+=8)
-               {
-                       out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
-                       out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
-                       out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
-                       out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
-               }
-       }
-}
-
-/*
-================
-GL_MipMap8Bit
-
-Mipping for 8 bit textures
-================
-*/
-void GL_MipMap8Bit (byte *in, int width, int height)
-{
-       int             i, j;
-       unsigned short     r,g,b;
-       byte    *out, *at1, *at2, *at3, *at4;
-
-       height >>= 1;
-       out = in;
-       for (i=0 ; i<height ; i++, in+=width)
-       {
-               for (j=0 ; j<width ; j+=2, out+=1, in+=2)
-               {
-                       at1 = (byte *) (d_8to24table + in[0]);
-                       at2 = (byte *) (d_8to24table + in[1]);
-                       at3 = (byte *) (d_8to24table + in[width+0]);
-                       at4 = (byte *) (d_8to24table + in[width+1]);
-
-                       r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
-                       g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
-                       b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
-
-                       out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
-               }
-       }
-}
-
-/*
-===============
-GL_Upload32
-===============
-*/
-void GL_Upload32 (void *data, int width, int height,  qboolean mipmap, qboolean alpha)
-{
-       int samples, scaled_width, scaled_height, i;
-       byte *in, *out, *scaled;
-
-       for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
-               ;
-       for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
-               ;
-
-       scaled_width >>= (int)gl_picmip.value;
-       scaled_height >>= (int)gl_picmip.value;
-
-       if (scaled_width > gl_max_size.value)
-               scaled_width = gl_max_size.value;
-       if (scaled_height > gl_max_size.value)
-               scaled_height = gl_max_size.value;
-
-       if (alpha)
-       {
-               alpha = false;
-               in = data;
-               for (i = 3;i < width*height*4;i += 4)
-                       if (in[i] != 255)
-                       {
-                               alpha = true;
-                               break;
-                       }
-       }
-
-       samples = alpha ? gl_alpha_format : gl_solid_format;
-
-#if 0
-       if (mipmap)
-               gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
-       else if (scaled_width == width && scaled_height == height)
-               glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
-       else
-       {
-               gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
-               glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
-       }
-#else
-texels += scaled_width * scaled_height;
-
-       scaled = malloc(scaled_width*scaled_height*4);
-       if (scaled_width == width && scaled_height == height)
-       {
-               // LordHavoc: gamma correct while copying
-               in = (byte *)data;
-               out = (byte *)scaled;
-               for (i = 0;i < width*height;i++)
-               {
-                       *out++ = qgamma[*in++];
-                       *out++ = qgamma[*in++];
-                       *out++ = qgamma[*in++];
-                       *out++ = *in++;
-               }
-       }
-       else
-               GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
-
-       glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
-       if (mipmap)
-       {
-               int             miplevel;
-
-               miplevel = 0;
-               while (scaled_width > 1 || scaled_height > 1)
-               {
-                       GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
-                       scaled_width >>= 1;
-                       scaled_height >>= 1;
-                       if (scaled_width < 1)
-                               scaled_width = 1;
-                       if (scaled_height < 1)
-                               scaled_height = 1;
-                       miplevel++;
-                       glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
-               }
-       }
-#endif
-
-
-       if (mipmap)
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
-       }
-       else
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
-       }
-       free(scaled);
-}
-
-void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap)
-{
-       int             scaled_width, scaled_height;
-       byte    *scaled = NULL;
-
-       for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
-               ;
-       for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
-               ;
-
-       scaled_width >>= (int)gl_picmip.value;
-       scaled_height >>= (int)gl_picmip.value;
-
-       if (scaled_width > gl_max_size.value)
-               scaled_width = gl_max_size.value;
-       if (scaled_height > gl_max_size.value)
-               scaled_height = gl_max_size.value;
-
-       texels += scaled_width * scaled_height;
-
-       if (scaled_width == width && scaled_height == height)
-       {
-               if (!mipmap)
-               {
-                       glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
-                       goto done;
-               }
-               scaled = malloc(scaled_width*scaled_height*4);
-               memcpy (scaled, data, width*height);
-       }
-       else
-       {
-               scaled = malloc(scaled_width*scaled_height*4);
-               GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
-       }
-
-       glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
-       if (mipmap)
-       {
-               int             miplevel;
-
-               miplevel = 0;
-               while (scaled_width > 1 || scaled_height > 1)
-               {
-                       GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
-                       scaled_width >>= 1;
-                       scaled_height >>= 1;
-                       if (scaled_width < 1)
-                               scaled_width = 1;
-                       if (scaled_height < 1)
-                               scaled_height = 1;
-                       miplevel++;
-                       glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
-               }
-       }
-done: ;
-
-
-       if (mipmap)
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
-       }
-       else
-       {
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
-       }
-       free(scaled);
-}
-
-qboolean VID_Is8bit();
-
-/*
-===============
-GL_Upload8
-===============
-*/
-void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
-{
-       static  unsigned *trans;
-       int                     i, s;
-       qboolean        noalpha;
-       int                     p;
-       byte    *indata;
-       int             *outdata;
-
-       s = width*height;
-       trans = malloc(s*4);
-       // if there are no transparent pixels, make it a 3 component
-       // texture even if it was specified as otherwise
-       if (alpha)
-       {
-               noalpha = true;
-               for (i=0 ; i<s ; i++)
-               {
-                       p = data[i];
-                       if (p != 255)
-                               trans[i] = d_8to24table[p];
-                       else
-                       {
-                               trans[i] = 0; // force to black
-                               noalpha = false;
-                       }
-               }
-
-               if (noalpha)
-               {
-                       if (VID_Is8bit() && (data!=scrap_texels[0]))
-                       {
-                               GL_Upload8_EXT (data, width, height, mipmap);
-                               free(trans);
-                               return;
-                       }
-                       alpha = false;
-               }
-       }
-       else
-       {
-               // LordHavoc: dodge the copy if it will be uploaded as 8bit
-               if (VID_Is8bit() && (data!=scrap_texels[0]))
-               {
-                       GL_Upload8_EXT (data, width, height, mipmap);
-                       free(trans);
-                       return;
-               }
-               //if (s&3)
-               //      Sys_Error ("GL_Upload8: s&3");
-               indata = data;
-               outdata = trans;
-               if (s&1)
-                       *outdata++ = d_8to24table[*indata++];
-               if (s&2)
-               {
-                       *outdata++ = d_8to24table[*indata++];
-                       *outdata++ = d_8to24table[*indata++];
-               }
-               for (i = 0;i < s;i+=4)
-               {
-                       *outdata++ = d_8to24table[*indata++];
-                       *outdata++ = d_8to24table[*indata++];
-                       *outdata++ = d_8to24table[*indata++];
-                       *outdata++ = d_8to24table[*indata++];
-               }
-       }
-
-       GL_Upload32 (trans, width, height, mipmap, alpha);
-       free(trans);
-}
-
-/*
-================
-GL_LoadTexture
-================
-*/
-int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
-{
-       unsigned short  crc;
-       int                             i;
-       gltexture_t             *glt;
-
-       if (isDedicated)
-               return 1;
-
-       // 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])
-       {
-               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)
-                               {
-                                       Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
-                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
-                                       //Sys_Error ("GL_LoadTexture: cache mismatch");
-                               }
-                               if ((gl_lerpimages.value != 0) != glt->lerped)
-                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
-                               return glt->texnum;
-                       }
-               }
-       }
-       // LordHavoc: although this could be an else condition as it was in the original id code,
-       //            it is more clear this way
-       // 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++];
-
-       strcpy (glt->identifier, identifier);
-       glt->texnum = texture_extension_number;
-       texture_extension_number++;
-// LordHavoc: label to drop out of the loop into the setup code
-GL_LoadTexture_setup:
-       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;
-
-       glBindTexture(GL_TEXTURE_2D, glt->texnum);
-
-       if (bytesperpixel == 1) // 8bit
-               GL_Upload8 (data, width, height, mipmap, alpha);
-       else // 32bit
-               GL_Upload32 (data, width, height, mipmap, true);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       return glt->texnum;
-}
-
-/*
-================
-GL_LoadPicTexture
-================
-*/
-int GL_LoadPicTexture (qpic_t *pic)
-{
-       return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
-}
-
-int GL_GetTextureSlots (int count)
-{
-       gltexture_t             *glt, *first;
-
-       first = glt = &gltextures[numgltextures];
-       while (count--)
-       {
-               glt->identifier[0] = 0;
-               glt->texnum = texture_extension_number++;
-               glt->crc = 0;
-               glt->width = 0;
-               glt->height = 0;
-               glt->bytesperpixel = 0;
-               glt++;
-               numgltextures++;
-       }
-       return first->texnum;
-}
diff --git a/gl_models.c b/gl_models.c
new file mode 100644 (file)
index 0000000..636018d
--- /dev/null
@@ -0,0 +1,802 @@
+
+#include "quakedef.h"
+
+// LordHavoc: vertex array
+float *aliasvert;
+float *aliasvertnorm;
+byte *aliasvertcolor;
+byte *aliasvertcolor2;
+
+int chrometexture;
+
+void makechrometexture()
+{
+       int i;
+       byte noise[64*64];
+       byte data[64*64][4];
+
+       fractalnoise(noise, 64);
+
+       // convert to RGBA data
+       for (i = 0;i < 64*64;i++)
+       {
+               data[i][0] = data[i][1] = data[i][2] = noise[i];
+               data[i][3] = 255;
+       }
+
+       chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4);
+}
+
+void gl_models_start()
+{
+       // allocate vertex processing arrays
+       aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
+       aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
+       aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
+       aliasvertcolor2 = malloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
+       makechrometexture();
+}
+
+void gl_models_shutdown()
+{
+       free(aliasvert);
+       free(aliasvertnorm);
+       free(aliasvertcolor);
+       free(aliasvertcolor2);
+}
+
+void GL_Models_Init()
+{
+       R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
+}
+
+extern vec3_t softwaretransform_x;
+extern vec3_t softwaretransform_y;
+extern vec3_t softwaretransform_z;
+extern vec_t softwaretransform_scale;
+extern vec3_t softwaretransform_offset;
+void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
+{
+       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)
+       {
+               float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
+               if (lerp < 0) lerp = 0;
+               if (lerp > 1) lerp = 1;
+               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
+               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++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                       *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                       *av++ = 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++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+                       *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+                       *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                       verts1++;verts2++;
+               }
+       }
+       else
+       {
+               // generate vertices
+               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++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                       *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                       *av++ = 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++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+                       *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+                       *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                       verts1++;
+               }
+       }
+}
+
+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;
+       }
+}
+
+extern cvar_t gl_vertexarrays;
+extern qboolean lighthalf;
+void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
+{
+       int i;
+       glBindTexture(GL_TEXTURE_2D, skin);
+       if (!colors)
+       {
+               if (lighthalf)
+                       glColor3f(0.5f, 0.5f, 0.5f);
+               else
+                       glColor3f(1.0f, 1.0f, 1.0f);
+       }
+       if (gl_vertexarrays.value)
+       {
+//             qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+//             glEnableClientState(GL_VERTEX_ARRAY);
+               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));
+
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+               /*
+               // draw the front faces
+               qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr));
+               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+               qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+               // draw the back faces
+               qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr));
+               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+               qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr));
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+               */
+
+               if (colors)
+                       glDisableClientState(GL_COLOR_ARRAY);
+//             glDisableClientState(GL_VERTEX_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();
+               /*
+               in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
+               glBegin(GL_TRIANGLES);
+               // draw the front faces
+               tex = (void *)((int) paliashdr->texcoords + (int) paliashdr);
+               //if (isG200)
+               //{
+                       for (i = 0;i < paliashdr->frontfaces * 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]);
+                       }
+               */
+               /*
+               }
+               else
+               {
+                       for (i = 0;i < paliashdr->frontfaces * 3;i++)
+                       {
+                               index = *in++;
+                               glTexCoord2f(tex[index*2], tex[index*2+1]);
+                               glColor4ub(colors[index*4], colors[index*4+1], colors[index*4+2], colors[index*4+3]);
+                               glVertex3fv(&aliasvert[index*3]);
+                       }
+               }
+               */
+               /*
+               // draw the back faces
+               tex += 2 * paliashdr->numverts;
+               //if (isG200)
+               //{
+                       for (i = 0;i < paliashdr->backfaces * 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]);
+                       }
+               */
+               /*
+               }
+               else
+               {
+                       for (i = 0;i < paliashdr->backfaces * 3;i++)
+                       {
+                               index = *in++;
+                               glTexCoord2f(tex[index*2], tex[index*2+1]);
+                               glColor4ub(colors[index*4], colors[index*4+1], colors[index*4+2], colors[index*4+3]);
+                               glVertex3fv(&aliasvert[index*3]);
+                       }
+               }
+               */
+               /*
+               glEnd();
+               */
+       }
+       // leave it in a state for additional passes
+       glDepthMask(0);
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive
+}
+
+void R_TintModel(byte *in, byte *out, int verts, byte *color)
+{
+       int i;
+       byte r = color[0];
+       byte g = color[1];
+       byte b = color[2];
+       for (i = 0;i < verts;i++)
+       {
+               out[0] = (byte) ((in[0] * r) >> 8);
+               out[1] = (byte) ((in[1] * g) >> 8);
+               out[2] = (byte) ((in[2] * b) >> 8);
+               out[3] =          in[3];
+               in += 4;
+               out += 4;
+       }
+}
+
+/*
+=================
+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, int frame, int *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)
+       {
+               lerpscale = frameinfo->rate;
+               pose += (int)(cl.time * frameinfo->rate) % frameinfo->length;
+       }
+       else
+               lerpscale = 10.0f;
+
+       lerp = R_CalcAnimLerp(ent, pose, lerpscale);
+
+       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);
+
+       // prep the vertex array as early as possible
+       if (gl_vertexarrays.value)
+       {
+               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+               glEnableClientState(GL_VERTEX_ARRAY);
+       }
+
+       R_LightModel(maliashdr->numverts, org, color);
+
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+       glShadeModel(GL_SMOOTH);
+       if (effects & EF_ADDITIVE)
+       {
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
+               glEnable(GL_BLEND);
+               glDepthMask(0);
+       }
+       else if (alpha != 1.0)
+       {
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable(GL_BLEND);
+               glDepthMask(0);
+       }
+       else
+       {
+               glDisable(GL_BLEND);
+               glDepthMask(1);
+       }
+
+       if (colormap >= 0)
+       {
+               if (!skin[0] && !skin[1] && !skin[2] && !skin[3])
+                       GL_DrawModelMesh(0, NULL, maliashdr);
+               else
+               {
+                       int c;
+                       if (skin[0])
+                               GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
+                       if (skin[1])
+                       {
+                               c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+                               R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
+                               GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
+                       }
+                       if (skin[2])
+                       {
+                               c = colormap & 0xF0      ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+                               R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
+                               GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
+                       }
+                       if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+               }
+       }
+       else
+       {
+               if (!skin[3] && !skin[4])
+                       GL_DrawModelMesh(0, NULL, maliashdr);
+               else
+               {
+                       if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
+                       if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+               }
+       }
+
+       if (fogenabled)
+       {
+               vec3_t diff;
+               glDisable (GL_TEXTURE_2D);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable (GL_BLEND);
+               glDepthMask(0); // disable zbuffer updates
+
+               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);
+                       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();
+               }
+
+               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();
+               }
+
+               glEnable (GL_TEXTURE_2D);
+               glColor3f (1,1,1);
+       }
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(1);
+}
+
+/*
+=================
+R_DrawQ2AliasFrame
+
+=================
+*/
+void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, int frame, int skin, int effects, int flags)
+{
+       int *order, count;
+       float lerp;
+       md2memframe_t *frame1, *frame2;
+
+       glBindTexture(GL_TEXTURE_2D, skin);
+
+       softwaretransformforentity(ent);
+
+       if ((frame >= pheader->num_frames) || (frame < 0))
+       {
+               Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
+               frame = 0;
+       }
+
+       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);
+
+       R_LightModel(pheader->num_xyz, org, color);
+
+       if (gl_vertexarrays.value)
+       {
+               // LordHavoc: big mess...
+               // using 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);
+               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]);
+                               qglArrayElement(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;
+                       }
+                       //if (isG200)
+                       //{
+                               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--);
+                       /*
+                       }
+                       else
+                       {
+                               do
+                               {
+                                       glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
+                                       glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]);
+                                       glVertex3fv(&aliasvert[order[2] * 3]);
+                                       order += 3;
+                               }
+                               while (count--);
+                       }
+                       */
+               }
+       }
+
+       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)));
+               }
+
+               if (gl_vertexarrays.value)
+               {
+                       // 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)
+                       {
+                               if (!(count = *order++))
+                                       break;
+                               if (count > 0)
+                                       glBegin(GL_TRIANGLE_STRIP);
+                               else
+                               {
+                                       glBegin(GL_TRIANGLE_FAN);
+                                       count = -count;
+                               }
+                               do
+                               {
+                                       qglArrayElement(order[2]);
+                                       order += 3;
+                               }
+                               while (count--);
+                       }
+
+                       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
+                               {
+                                       glVertex3fv(&aliasvert[order[2] * 3]);
+                                       order += 3;
+                               }
+                               while (count--);
+                       }
+               }
+
+               glEnable (GL_TEXTURE_2D);
+               glColor3f (1,1,1);
+       }
+
+       if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
+       {
+               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)
+               {
+                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+                       glEnableClientState(GL_VERTEX_ARRAY);
+                                               
+                       while(1)
+                       {
+                               if (!(count = *order++))
+                                       break;
+                               if (count > 0)
+                                       glBegin(GL_TRIANGLE_STRIP);
+                               else
+                               {
+                                       glBegin(GL_TRIANGLE_FAN);
+                                       count = -count;
+                               }
+                               do
+                               {
+                                       qglArrayElement(order[2]);
+                                       order += 3;
+                               }
+                               while (count--);
+                       }
+
+                       glDisableClientState(GL_VERTEX_ARRAY);
+               }
+               else
+               {
+                       while(1)
+                       {
+                               if (!(count = *order++))
+                                       break;
+                               if (count > 0)
+                                       glBegin(GL_TRIANGLE_STRIP);
+                               else
+                               {
+                                       glBegin(GL_TRIANGLE_FAN);
+                                       count = -count;
+                               }
+                               do
+                               {
+                                       glVertex3fv(&aliasvert[order[2] * 3]);
+                                       order += 3;
+                               }
+                               while (count--);
+                       }
+               }
+
+               glEnable (GL_TEXTURE_2D);
+               glColor3f (1,1,1);
+       }
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(1);
+}
+
+int modeldlightbits[8];
+extern int r_dlightframecount;
+extern void R_LightPoint (vec3_t color, vec3_t p);
+
+/*
+=================
+R_DrawAliasModel
+
+=================
+*/
+void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap)
+{
+       int                     i;
+       vec3_t          mins, maxs, color;
+//     aliashdr_t      *paliashdr = NULL;
+//     md2mem_t        *pheader = NULL;
+       mleaf_t         *leaf;
+       void            *modelheader;
+       int                     *skinset;
+
+       if (alpha < (1.0 / 64.0))
+               return; // basically completely transparent
+
+       VectorAdd (org, clmodel->mins, mins);
+       VectorAdd (org, clmodel->maxs, maxs);
+
+       if (cull && R_CullBox (mins, maxs))
+               return;
+
+       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
+       {
+               // HACK HACK HACK -- no fullbright colors, so make torches full light
+               if (!strcmp (clmodel->name, "progs/flame2.mdl") || !strcmp (clmodel->name, "progs/flame.mdl") )
+                       color[0] = color[1] = color[2] = 128;
+               else
+                       R_LightPoint (color, org);
+       }
+
+       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;
+               Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
+       }
+
+       modelheader = Mod_Extradata (clmodel);
+
+       {
+//             int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
+//             int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
+               int *skinanimrange = clmodel->skinanimrange + skin * 2;
+               int *skinanim = clmodel->skinanim;
+               i = skinanimrange[0];
+               if (skinanimrange[1] > 1) // animated
+                       i += ((int) (cl.time * 10) % skinanimrange[1]);
+               skinset = skinanim + i*5;
+       }
+
+//     glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[skin][(int)(cl.time*10) & 3]);
+//     glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[skin]);
+
+       glEnable (GL_TEXTURE_2D);
+
+       c_alias_polys += clmodel->numtris;
+       if (clmodel->aliastype == ALIASTYPE_MD2)
+               R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset[0], effects, flags);
+       else
+               R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset, colormap, effects, flags);
+}
index 3947bbd80fabb9dfc3e6c48b6fed04b987beddd5..9750a3466f7484dd8b3fdd658d66e965244fe86e 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -34,11 +34,9 @@ float transviewdist; // distance of view origin along the view normal
 
 float transreciptable[256];
 
-void glpoly_init()
+void gl_poly_start()
 {
        int i;
-       Cvar_RegisterVariable (&gl_multitexture);
-       Cvar_RegisterVariable (&gl_vertexarrays);
        transvert = malloc(MAX_TRANSVERTS * sizeof(transvert_t));
        transpoly = malloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
        transpolyindex = malloc(MAX_TRANSPOLYS * sizeof(unsigned short));
@@ -50,6 +48,23 @@ void glpoly_init()
        for (i = 1;i < 256;i++)
                transreciptable[i] = 1.0f / i;
 }
+void gl_poly_shutdown()
+{
+       free(transvert);
+       free(transpoly);
+       free(transpolyindex);
+       free(wallvert);
+       free(wallpoly);
+       free(skyvert);
+       free(skypoly);
+}
+
+void GL_Poly_Init()
+{
+       Cvar_RegisterVariable (&gl_multitexture);
+       Cvar_RegisterVariable (&gl_vertexarrays);
+       R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown);
+}
 
 void transpolyclear()
 {
index 753f34e798945f2013c83e5384646dc5d78ca2a4..e880dbd5dfcef5e92b96301a7d0c340540a39778 100644 (file)
@@ -39,7 +39,7 @@ qboolean      envmap;                         // true during envmap command capture
 
 // LordHavoc: moved all code related to particles into r_part.c
 //int                  particletexture;        // little dot for particles
-int                    playertextures;         // up to 16 color translated skins
+//int                  playertextures;         // up to 16 color translated skins
 
 extern qboolean isG200, isRagePro; // LordHavoc: special card hacks
 
@@ -82,17 +82,9 @@ cvar_t       r_novis = {"r_novis","0"};
 cvar_t r_waterripple = {"r_waterripple","0"};
 cvar_t r_fullbrights = {"r_fullbrights", "1"};
 
-//cvar_t       gl_cull = {"gl_cull","1"};
-//cvar_t       gl_affinemodels = {"gl_affinemodels","0"};
-//cvar_t       gl_polyblend = {"gl_polyblend","1"};
-cvar_t gl_playermip = {"gl_playermip","0"};
-//cvar_t       gl_nocolors = {"gl_nocolors","0"};
-//cvar_t       gl_keeptjunctions = {"gl_keeptjunctions","1"};
-//cvar_t       gl_reporttjunctions = {"gl_reporttjunctions","0"};
 cvar_t contrast = {"contrast", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
 cvar_t brightness = {"brightness", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
 cvar_t gl_lightmode = {"gl_lightmode", "1", TRUE}; // LordHavoc: overbright lighting
-//cvar_t       r_dynamicwater = {"r_dynamicwater", "1"};
 //cvar_t       r_dynamicbothsides = {"r_dynamicbothsides", "1"}; // LordHavoc: can disable dynamic lighting of backfaces, but quake maps are weird so it doesn't always work right...
 cvar_t r_farclip = {"r_farclip", "6144"};
 
@@ -105,74 +97,6 @@ cvar_t      gl_fogstart = {"gl_fogstart", "0"};
 cvar_t gl_fogend = {"gl_fogend","0"};
 cvar_t glfog = {"glfog", "0"};
 
-int chrometexture;
-
-void makechrometextures()
-{
-       int x, y, g, g2, amplitude, noise[64][64], min, max;
-       byte data[64][64][4];
-       //
-       // particle texture
-       //
-       chrometexture = texture_extension_number++;
-    glBindTexture(GL_TEXTURE_2D, chrometexture);
-
-#define n(x,y) noise[(y)&63][(x)&63]
-
-       amplitude = 16777215;
-       g2 = 64;
-       noise[0][0] = 0;
-       for (;(g = g2 >> 1) >= 1;g2 >>= 1)
-       {
-               // subdivide, diamond-square algorythm (really this has little to do with squares)
-               // diamond
-               for (y = 0;y < 64;y += g2)
-                       for (x = 0;x < 64;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 < 64;y += g2)
-                       for (x = 0;x < 64;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 < 64;y += g)
-                       for (x = 0;x < 64;x += g)
-                               noise[y][x] += rand()&amplitude;
-       }
-       // normalize the noise range
-       min = max = 0;
-       for (y = 0;y < 64;y++)
-               for (x = 0;x < 64;x++)
-               {
-                       if (n(x,y) < min) min = n(x,y);
-                       if (n(x,y) > max) max = n(x,y);
-               }
-       max -= min;
-       for (y = 0;y < 64;y++)
-               for (x = 0;x < 64;x++)
-                       n(x,y) = (n(x,y) - min) * 255 / max;
-
-#undef n
-
-       // convert to RGBA data
-       for (y = 0;y < 64;y++)
-               for (x = 0;x < 64;x++)
-               {
-                       data[y][x][0] = data[y][x][1] = data[y][x][2] = (byte) noise[y][x];
-                       data[y][x][3] = 255;
-               }
-
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-}
-
 extern qboolean isRagePro;
 
 qboolean lighthalf;
@@ -286,22 +210,16 @@ void FOG_registercvars()
        }
 }
 
-void glpoly_init();
-void glrsurf_init();
-void rlight_init();
-
-// LordHavoc: vertex array
-float *aliasvert;
-float *aliasvertnorm;
-byte *aliasvertcolor;
+void glmain_start()
+{
+}
 
-void rmain_registercvars()
+void glmain_shutdown()
 {
-       // allocate vertex processing arrays
-       aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
-       aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
-       aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
+}
 
+void GL_Main_Init()
+{
        FOG_registercvars();
        Cvar_RegisterVariable (&r_speeds2);
        Cvar_RegisterVariable (&contrast);
@@ -315,10 +233,34 @@ void rmain_registercvars()
 //     if (gl_vendor && strstr(gl_vendor, "3Dfx"))
 //             gl_lightmode.value = 0;
        Cvar_RegisterVariable (&r_fullbright);
-       makechrometextures();
-       glpoly_init();
-       glrsurf_init();
-       rlight_init();
+       R_RegisterModule("GL_Main", glmain_start, glmain_shutdown);
+}
+
+extern void GL_Draw_Init();
+extern void GL_Main_Init();
+extern void GL_Models_Init();
+extern void GL_Poly_Init();
+extern void GL_Surf_Init();
+extern void GL_Screen_Init();
+extern void GL_Misc_Init();
+extern void R_Crosshairs_Init();
+extern void R_Light_Init();
+extern void R_Particles_Init();
+
+void Render_Init()
+{
+       R_ShutdownModules();
+       GL_Draw_Init();
+       GL_Main_Init();
+       GL_Models_Init();
+       GL_Poly_Init();
+       GL_Surf_Init();
+       GL_Screen_Init();
+       GL_Misc_Init();
+       R_Crosshairs_Init();
+       R_Light_Init();
+       R_Particles_Init();
+       R_StartModules();
 }
 
 /*
@@ -347,32 +289,9 @@ vec3_t     shadecolor;
 
 float  modelalpha;
 
-void R_LightPoint (vec3_t color, vec3_t p);
-void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
-
-float R_CalcAnimLerp(int pose, float lerpscale)
-{
-       if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart <= cl.time)
-       {
-               if (pose != currententity->draw_pose)
-               {
-                       currententity->draw_lastpose = currententity->draw_pose;
-                       currententity->draw_pose = pose;
-                       currententity->draw_lerpstart = cl.time;
-                       return 0;
-               }
-               else
-                       return ((cl.time - currententity->draw_lerpstart) * lerpscale);
-       }
-       else // uninitialized
-       {
-               currententity->draw_lastmodel = currententity->model;
-               currententity->draw_lastpose = currententity->draw_pose = pose;
-               currententity->draw_lerpstart = cl.time;
-               return 0;
-       }
-}
+extern void R_LightPoint (vec3_t color, vec3_t p);
+extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
+extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
 
 /*
 =============================================================
@@ -530,668 +449,6 @@ void R_DrawSpriteModel (entity_t *e)
                GL_DrawSpriteImage(newframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*lerp);
 }
 
-/*
-=============================================================
-
-  ALIAS MODELS
-
-=============================================================
-*/
-
-extern vec3_t softwaretransform_x;
-extern vec3_t softwaretransform_y;
-extern vec3_t softwaretransform_z;
-extern vec_t softwaretransform_scale;
-extern vec3_t softwaretransform_offset;
-void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
-{
-       int i;
-       vec3_t point, matrix_x, matrix_y, matrix_z;
-       float *av, *avn;
-       av = aliasvert;
-       avn = aliasvertnorm;
-       if (lerp < 0) lerp = 0;
-       if (lerp > 1) lerp = 1;
-       if (lerp != 0)
-       {
-               float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
-               if (lerp < 0) lerp = 0;
-               if (lerp > 1) lerp = 1;
-               ilerp = 1 - lerp;
-               ilerp127 = ilerp * (1.0 / 127.0);
-               lerp127 = lerp * (1.0 / 127.0);
-               VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
-               VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
-               VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
-               // 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
-               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++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                       *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                       *av++ = 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++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
-                       *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
-                       *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
-                       verts1++;verts2++;
-               }
-       }
-       else
-       {
-               float i127;
-               i127 = 1.0f / 127.0f;
-               VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
-               VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
-               VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
-               // generate vertices
-               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++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
-                       *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
-                       *av++ = 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] * i127;
-                       point[1] = verts1->n[1] * i127;
-                       point[2] = verts1->n[2] * i127;
-                       *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
-                       *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
-                       *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
-                       verts1++;
-               }
-       }
-}
-
-/*
-=================
-R_DrawAliasFrame
-
-=================
-*/
-extern vec3_t lightspot;
-void R_LightModel(int numverts, vec3_t center);
-extern cvar_t gl_vertexarrays;
-void R_DrawAliasFrame (aliashdr_t *paliashdr)
-{
-       int                             i, pose, frame = currententity->frame;
-       float                   lerpscale, lerp;
-
-       softwaretransformforentity(currententity);
-
-       if ((frame >= paliashdr->numframes) || (frame < 0))
-       {
-               Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
-               frame = 0;
-       }
-
-       pose = paliashdr->frames[frame].firstpose;
-
-       if (paliashdr->frames[frame].numposes > 1)
-       {
-               lerpscale = 1.0 / paliashdr->frames[frame].interval;
-               pose += (int)(cl.time * lerpscale) % paliashdr->frames[frame].numposes;
-       }
-       else
-               lerpscale = 10.0;
-
-       lerp = R_CalcAnimLerp(pose, lerpscale);
-
-       R_AliasLerpVerts(paliashdr->numverts, lerp, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_lastpose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_pose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin);
-
-       R_LightModel(paliashdr->numverts, currententity->origin);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glShadeModel(GL_SMOOTH);
-       if (currententity->effects & EF_ADDITIVE)
-       {
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
-               glEnable(GL_BLEND);
-               glDepthMask(0);
-       }
-       else if (modelalpha != 1.0)
-       {
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable(GL_BLEND);
-               glDepthMask(0);
-       }
-       else
-       {
-               glDisable(GL_BLEND);
-               glDepthMask(1);
-       }
-
-       if (gl_vertexarrays.value)
-       {
-               // LordHavoc: I would use InterleavedArrays here,
-               // but the texture coordinates are a seperate array,
-               // and it would be wasteful to copy them into the main array...
-       //      glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
-               glEnableClientState(GL_VERTEX_ARRAY);
-               glEnableClientState(GL_COLOR_ARRAY);
-
-               // draw the front faces
-               qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr));
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-               qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
-               // draw the back faces
-               qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr));
-               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-               qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr));
-               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
-               glDisableClientState(GL_COLOR_ARRAY);
-               glDisableClientState(GL_VERTEX_ARRAY);
-       }
-       else
-       {
-               unsigned short *in, index;
-               float *tex;
-               in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
-               glBegin(GL_TRIANGLES);
-               // draw the front faces
-               tex = (void *)((int) paliashdr->texcoords + (int) paliashdr);
-               //if (isG200)
-               //{
-                       for (i = 0;i < paliashdr->frontfaces * 3;i++)
-                       {
-                               index = *in++;
-                               glTexCoord2f(tex[index*2], tex[index*2+1]);
-                               glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
-                               glVertex3fv(&aliasvert[index*3]);
-                       }
-               /*
-               }
-               else
-               {
-                       for (i = 0;i < paliashdr->frontfaces * 3;i++)
-                       {
-                               index = *in++;
-                               glTexCoord2f(tex[index*2], tex[index*2+1]);
-                               glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
-                               glVertex3fv(&aliasvert[index*3]);
-                       }
-               }
-               */
-               // draw the back faces
-               tex += 2 * paliashdr->numverts;
-               //if (isG200)
-               //{
-                       for (i = 0;i < paliashdr->backfaces * 3;i++)
-                       {
-                               index = *in++;
-                               glTexCoord2f(tex[index*2], tex[index*2+1]);
-                               glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
-                               glVertex3fv(&aliasvert[index*3]);
-                       }
-               /*
-               }
-               else
-               {
-                       for (i = 0;i < paliashdr->backfaces * 3;i++)
-                       {
-                               index = *in++;
-                               glTexCoord2f(tex[index*2], tex[index*2+1]);
-                               glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
-                               glVertex3fv(&aliasvert[index*3]);
-                       }
-               }
-               */
-               glEnd();
-       }
-
-       if (fogenabled)
-       {
-               vec3_t diff;
-               glDisable (GL_TEXTURE_2D);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable (GL_BLEND);
-               glDepthMask(0); // disable zbuffer updates
-
-               VectorSubtract(currententity->origin, 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);
-                       qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
-                       glDisableClientState(GL_VERTEX_ARRAY);
-               }
-               else
-               {
-                       unsigned short *in;
-                       in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
-                       glBegin(GL_TRIANGLES);
-                       for (i = 0;i < paliashdr->numtris * 3;i++)
-                               glVertex3fv(&aliasvert[*in++ * 3]);
-                       glEnd();
-               }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-
-       if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
-       {
-               // flatten it to make a shadow
-               float *av = aliasvert + 2, l = lightspot[2] + 0.125;
-               av = aliasvert + 2;
-               for (i = 0;i < paliashdr->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 * modelalpha);
-
-               if (gl_vertexarrays.value)
-               {
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                       qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
-                       glDisableClientState(GL_VERTEX_ARRAY);
-               }
-               else
-               {
-                       unsigned short *in;
-                       in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
-                       glBegin(GL_TRIANGLES);
-                       for (i = 0;i < paliashdr->numtris * 3;i++)
-                               glVertex3fv(&aliasvert[*in++ * 3]);
-                       glEnd();
-               }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glEnable (GL_BLEND);
-       glDepthMask(1);
-}
-
-/*
-=================
-R_DrawQ2AliasFrame
-
-=================
-*/
-void R_DrawQ2AliasFrame (md2mem_t *pheader)
-{
-       int *order, count, frame = currententity->frame;
-       float lerp;
-       md2memframe_t *frame1, *frame2;
-
-       softwaretransformforentity(currententity);
-
-       if ((frame >= pheader->num_frames) || (frame < 0))
-       {
-               Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
-               frame = 0;
-       }
-
-       lerp = R_CalcAnimLerp(frame, 10);
-
-       frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_lastpose));
-       frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_pose));
-       R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
-
-       R_LightModel(pheader->num_xyz, currententity->origin);
-
-       if (gl_vertexarrays.value)
-       {
-               // LordHavoc: big mess...
-               // using arrays only slightly, although it is enough to prevent duplicates
-               // (saving half the transforms)
-               //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
-               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-               qglColorPointer(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]);
-                               qglArrayElement(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;
-                       }
-                       //if (isG200)
-                       //{
-                               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--);
-                       /*
-                       }
-                       else
-                       {
-                               do
-                               {
-                                       glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
-                                       glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]);
-                                       glVertex3fv(&aliasvert[order[2] * 3]);
-                                       order += 3;
-                               }
-                               while (count--);
-                       }
-                       */
-               }
-       }
-
-       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(currententity->origin, r_refdef.vieworg, diff);
-                       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
-               }
-
-               if (gl_vertexarrays.value)
-               {
-                       // LordHavoc: big mess...
-                       // using arrays only slightly, although it is enough to prevent duplicates
-                       // (saving half the transforms)
-                       //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_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
-                               {
-                                       qglArrayElement(order[2]);
-                                       order += 3;
-                               }
-                               while (count--);
-                       }
-
-                       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
-                               {
-                                       glVertex3fv(&aliasvert[order[2] * 3]);
-                                       order += 3;
-                               }
-                               while (count--);
-                       }
-               }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-
-       if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
-       {
-               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 * modelalpha);
-
-               if (gl_vertexarrays.value)
-               {
-                       qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
-                       glEnableClientState(GL_VERTEX_ARRAY);
-                                               
-                       while(1)
-                       {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
-                               else
-                               {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
-                               }
-                               do
-                               {
-                                       qglArrayElement(order[2]);
-                                       order += 3;
-                               }
-                               while (count--);
-                       }
-
-                       glDisableClientState(GL_VERTEX_ARRAY);
-               }
-               else
-               {
-                       while(1)
-                       {
-                               if (!(count = *order++))
-                                       break;
-                               if (count > 0)
-                                       glBegin(GL_TRIANGLE_STRIP);
-                               else
-                               {
-                                       glBegin(GL_TRIANGLE_FAN);
-                                       count = -count;
-                               }
-                               do
-                               {
-                                       glVertex3fv(&aliasvert[order[2] * 3]);
-                                       order += 3;
-                               }
-                               while (count--);
-                       }
-               }
-
-               glEnable (GL_TEXTURE_2D);
-               glColor3f (1,1,1);
-       }
-
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glEnable (GL_BLEND);
-       glDepthMask(1);
-}
-
-int modeldlightbits[8];
-extern int r_dlightframecount;
-
-/*
-=================
-R_DrawAliasModel
-
-=================
-*/
-void R_DrawAliasModel (entity_t *e, int cull)
-{
-       int                     i;
-       model_t         *clmodel;
-       vec3_t          mins, maxs;
-       aliashdr_t      *paliashdr = NULL;
-       md2mem_t                *pheader = NULL;
-       int                     anim;
-
-       if (modelalpha < (1.0 / 64.0))
-               return; // basically completely transparent
-
-       clmodel = currententity->model;
-
-       VectorAdd (currententity->origin, clmodel->mins, mins);
-       VectorAdd (currententity->origin, clmodel->maxs, maxs);
-
-       if (cull && R_CullBox (mins, maxs))
-               return;
-
-       VectorCopy (currententity->origin, r_entorigin);
-       VectorSubtract (r_origin, r_entorigin, modelorg);
-
-       {
-               mleaf_t *leaf = Mod_PointInLeaf (currententity->origin, 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 (currententity->model->flags & EF_FULLBRIGHT || currententity->effects & EF_FULLBRIGHT)
-       {
-               shadecolor[0] = currententity->colormod[0] * 256;
-               shadecolor[1] = currententity->colormod[1] * 256;
-               shadecolor[2] = currententity->colormod[2] * 256;
-       }
-       else
-       {
-               R_LightPoint (shadecolor, currententity->origin);
-
-               // HACK HACK HACK -- no fullbright colors, so make torches full light
-               if (!strcmp (currententity->model->name, "progs/flame2.mdl") || !strcmp (currententity->model->name, "progs/flame.mdl") )
-                       shadecolor[0] = shadecolor[1] = shadecolor[2] = 128;
-
-               shadecolor[0] *= currententity->colormod[0];
-               shadecolor[1] *= currententity->colormod[1];
-               shadecolor[2] *= currententity->colormod[2];
-       }
-
-       // locate the proper data
-       if (clmodel->aliastype == ALIASTYPE_MD2)
-       {
-               pheader = (void *)Mod_Extradata (currententity->model);
-               c_alias_polys += pheader->num_tris;
-       }
-       else
-       {
-               paliashdr = (void *)Mod_Extradata (currententity->model);
-               c_alias_polys += paliashdr->numtris;
-       }
-
-       // draw all the triangles
-
-       if (clmodel->aliastype == ALIASTYPE_MD2)
-       {
-               if (currententity->skinnum < 0 || currententity->skinnum >= pheader->num_skins)
-               {
-                       currententity->skinnum = 0;
-                       Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
-               }
-               glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[currententity->skinnum]);
-       }
-       else
-       {
-               if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
-               {
-                       currententity->skinnum = 0;
-                       Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
-               }
-               anim = (int)(cl.time*10) & 3;
-           glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[currententity->skinnum][anim]);
-       }
-       glDisable(GL_ALPHA_TEST);
-       glEnable (GL_TEXTURE_2D);
-
-       // we can't dynamically colormap textures, so they are cached
-       // seperately for the players.  Heads are just uncolored.
-       if (currententity->colormap != 0 /*vid.colormap*/ /* && !gl_nocolors.value*/)
-       {
-               i = currententity - cl_entities;
-               if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
-                       glBindTexture(GL_TEXTURE_2D, playertextures - 1 + i);
-       }
-
-//     if (gl_affinemodels.value)
-//             glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
-       if (clmodel->aliastype == ALIASTYPE_MD2)
-               R_DrawQ2AliasFrame (pheader);
-       else
-               R_DrawAliasFrame (paliashdr);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-}
-
 //==================================================================================
 
 void R_DrawBrushModel (entity_t *e);
@@ -1235,7 +492,7 @@ void R_DrawEntitiesOnList2 (void)
                switch (currententity->model->type)
                {
                case mod_alias:
-                       R_DrawAliasModel (currententity, true);
+                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
                        break;
 
                case mod_sprite:
@@ -1266,7 +523,7 @@ void R_DrawViewModel (void)
 
        // hack the depth range to prevent view model from poking into walls
        glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
-       R_DrawAliasModel (currententity, FALSE);
+       R_DrawAliasModel (currententity, FALSE, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
        glDepthRange (gldepthmin, gldepthmax);
 }
 
index ab7573c17986e55e634674b25aaa8071598aaaa4..99ff6ecb7fe2fde8b2feebc72c4ffe350e489397 100644 (file)
@@ -125,21 +125,25 @@ void R_Envmap_f (void)
 
 void R_InitParticles (void);
 
+void gl_misc_start()
+{
+}
+
+void gl_misc_shutdown()
+{
+}
+
 /*
 ===============
 R_Init
 ===============
 */
-void R_Init (void)
+void GL_Misc_Init (void)
 {      
-//     extern cvar_t gl_finish;
-
        Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);        
        Cmd_AddCommand ("envmap", R_Envmap_f);  
        Cmd_AddCommand ("pointfile", R_ReadPointFile_f);        
 
-//     Cvar_RegisterVariable (&r_norefresh);
-//     Cvar_RegisterVariable (&r_lightmap);
        Cvar_RegisterVariable (&r_drawentities);
        Cvar_RegisterVariable (&r_drawviewmodel);
        Cvar_RegisterVariable (&r_shadows);
@@ -149,175 +153,11 @@ void R_Init (void)
        Cvar_RegisterVariable (&r_speeds);
        Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple
 
-//     Cvar_RegisterVariable (&gl_cull);
-//     Cvar_RegisterVariable (&gl_affinemodels);
-//     Cvar_RegisterVariable (&gl_polyblend);
-       Cvar_RegisterVariable (&gl_playermip);
-//     Cvar_RegisterVariable (&gl_nocolors);
-
-//     Cvar_RegisterVariable (&gl_keeptjunctions);
-//     Cvar_RegisterVariable (&gl_reporttjunctions);
-
-       R_InitParticles ();
-
-       playertextures = texture_extension_number;
-       texture_extension_number += 64; // LordHavoc: increased number of players from 16 to 64
+       R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown);
 }
 
-qboolean VID_Is8bit(void);
-void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
-
-/*
-===============
-R_TranslatePlayerSkin
-
-Translates a skin texture by the per-player color lookup
-===============
-*/
-void R_TranslatePlayerSkin (int playernum)
-{
-       int             top, bottom;
-       byte    translate[256];
-       unsigned        translate32[256];
-       int             i, j, s;
-       model_t *model;
-       aliashdr_t *paliashdr;
-       byte    *original;
-       unsigned        pixels[512*256], *out;
-       unsigned        scaled_width, scaled_height;
-       int                     inwidth, inheight;
-       byte            *inrow;
-       unsigned        frac, fracstep;
-
-       top = cl.scores[playernum].colors & 0xf0;
-       bottom = (cl.scores[playernum].colors &15)<<4;
-
-       for (i=0 ; i<256 ; i++)
-               translate[i] = i;
-
-       for (i=0 ; i<16 ; i++)
-       {
-               // LordHavoc: corrected color ranges
-               if (top < 128 || (top >= 224 && top < 240))     // the artists made some backwards ranges.  sigh.
-                       translate[TOP_RANGE+i] = top+i;
-               else
-                       translate[TOP_RANGE+i] = top+15-i;
-
-               // LordHavoc: corrected color ranges
-               if (bottom < 128 || (bottom >= 224 && bottom < 240))
-                       translate[BOTTOM_RANGE+i] = bottom+i;
-               else
-                       translate[BOTTOM_RANGE+i] = bottom+15-i;
-       }
-
-       //
-       // locate the original skin pixels
-       //
-       currententity = &cl_entities[1+playernum];
-       model = currententity->model;
-       if (!model)
-               return;         // player doesn't have a model yet
-       if (model->type != mod_alias)
-               return; // only translate skins on alias models
-
-       paliashdr = (aliashdr_t *)Mod_Extradata (model);
-       s = paliashdr->skinwidth * paliashdr->skinheight;
-       if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
-       {
-               Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum);
-               original = (byte *)paliashdr + paliashdr->texels[0];
-       }
-       else
-               original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
-       if (s & 3)
-               Sys_Error ("R_TranslateSkin: s&3");
-
-       inwidth = paliashdr->skinwidth;
-       inheight = paliashdr->skinheight;
-
-       // because this happens during gameplay, do it fast
-       // instead of sending it through gl_upload 8
-    glBindTexture(GL_TEXTURE_2D, playertextures + playernum);
-
-#if 0
-       byte    translated[320*200];
-
-       for (i=0 ; i<s ; i+=4)
-       {
-               translated[i] = translate[original[i]];
-               translated[i+1] = translate[original[i+1]];
-               translated[i+2] = translate[original[i+2]];
-               translated[i+3] = translate[original[i+3]];
-       }
-
-
-       // don't mipmap these, because it takes too long
-       GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true);
-#else
-       scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
-       scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
-
-       // allow users to crunch sizes down even more if they want
-       scaled_width >>= (int)gl_playermip.value;
-       scaled_height >>= (int)gl_playermip.value;
-
-       if (VID_Is8bit())
-       { // 8bit texture upload
-               byte *out2;
-
-               out2 = (byte *)pixels;
-               memset(pixels, 0, sizeof(pixels));
-               fracstep = inwidth*0x10000/scaled_width;
-               for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
-               {
-                       inrow = original + inwidth*(i*inheight/scaled_height);
-                       frac = fracstep >> 1;
-                       for (j=0 ; j<scaled_width ; j+=4)
-                       {
-                               out2[j] = translate[inrow[frac>>16]];
-                               frac += fracstep;
-                               out2[j+1] = translate[inrow[frac>>16]];
-                               frac += fracstep;
-                               out2[j+2] = translate[inrow[frac>>16]];
-                               frac += fracstep;
-                               out2[j+3] = translate[inrow[frac>>16]];
-                               frac += fracstep;
-                       }
-               }
-
-               GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
-               return;
-       }
-
-       for (i=0 ; i<256 ; i++)
-               translate32[i] = d_8to24table[translate[i]];
-
-       out = pixels;
-       fracstep = inwidth*0x10000/scaled_width;
-       for (i=0 ; i<scaled_height ; i++, out += scaled_width)
-       {
-               inrow = original + inwidth*(i*inheight/scaled_height);
-               frac = fracstep >> 1;
-               for (j=0 ; j<scaled_width ; j+=4)
-               {
-                       out[j] = translate32[inrow[frac>>16]];
-                       frac += fracstep;
-                       out[j+1] = translate32[inrow[frac>>16]];
-                       frac += fracstep;
-                       out[j+2] = translate32[inrow[frac>>16]];
-                       frac += fracstep;
-                       out[j+3] = translate32[inrow[frac>>16]];
-                       frac += fracstep;
-               }
-       }
-       glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#endif
-
-}
+//qboolean VID_Is8bit(void);
+//void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
 
 void R_ClearParticles (void);
 void GL_BuildLightmaps (void);
index fe5bb6ca9f6127fa2a02f3fabbf080803c911b05..be07117ce096a3366b1ecc6e6ee739c88983d029 100644 (file)
@@ -51,15 +51,22 @@ cvar_t gl_vertex = {"gl_vertex", "0"};
 cvar_t gl_texsort = {"gl_texsort", "1"};
 //cvar_t gl_funnywalls = {"gl_funnywalls", "0"}; // LordHavoc: see BuildSurfaceDisplayList
 
-qboolean lightmaprgba, nosubimagefragments, nosubimage;
+qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible;
 int lightmapbytes;
 
-qboolean skyisvisible;
 extern qboolean gl_arrays;
 
 extern int r_dlightframecount;
 
-void glrsurf_init()
+void gl_surf_start()
+{
+}
+
+void gl_surf_shutdown()
+{
+}
+
+void GL_Surf_Init()
 {
        int i;
        for (i = 0;i < MAX_LIGHTMAPS;i++)
@@ -80,6 +87,8 @@ void glrsurf_init()
 //             Cvar_SetValue("gl_nosubimage", 1);
                Cvar_SetValue("gl_lightmode", 0);
        }
+
+       R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown);
 }
 
 extern qboolean lighthalf;
@@ -303,12 +312,9 @@ extern     int             solidskytexture;
 extern int             alphaskytexture;
 extern float   speedscale;             // for top sky and bottom sky
 
-qboolean mtexenabled = false;
-
 extern char skyname[];
 
 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-//extern cvar_t r_dynamicwater;
 float  turbsin[256] =
 {
        #include "gl_warp_sin.h"
@@ -347,7 +353,9 @@ void UploadLightmaps()
        }
 }
 
-void R_SkySurf(msurface_t *s, qboolean transform)
+float  wvert[1024*6]; // used by the following functions
+
+void RSurf_DrawSky(msurface_t *s, int transform)
 {
        glpoly_t *p;
        int i;
@@ -379,11 +387,11 @@ void R_SkySurf(msurface_t *s, qboolean transform)
        }
 }
 
-void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert)
+int RSurf_Light(int *dlightbits, glpoly_t *polys)
 {
        float           cr, cg, cb, radius, radius2, f, *v, *wv;
-       int                     i, a, b;
-       unsigned int c;
+       int                     i, a, b, lit = false;
+       unsigned int c, d;
        dlight_t        *light;
        vec_t           *lightorigin;
        glpoly_t        *p;
@@ -391,18 +399,18 @@ void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert)
        {
                if ((c = dlightbits[a]))
                {
-                       for (b = 0;c && b < 32;b++)
+                       for (b = 0, d = 1;c;b++, d <<= 1)
                        {
-                               if (c & (1 << b))
+                               if (c & d)
                                {
-                                       c -= (1 << b);
+                                       c -= d;
                                        light = &cl_dlights[a * 32 + b];
                                        lightorigin = light->origin;
                                        cr = light->color[0];
                                        cg = light->color[1];
                                        cb = light->color[2];
-                                       radius = light->radius*light->radius*16.0f;
-                                       radius2 = radius * 16.0f;
+                                       radius = light->radius*light->radius*LIGHTSCALE;
+                                       radius2 = radius * (256.0f / LIGHTSCALE);
                                        wv = wvert;
                                        for (p = polys;p;p = p->next)
                                        {
@@ -411,28 +419,28 @@ void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert)
                                                        f = VectorDistance2(wv, lightorigin);
                                                        if (f < radius)
                                                        {
-                                                               f = radius2 / (f + 65536.0f);
+                                                               f = radius2 / (f + LIGHTOFFSET);
                                                                wv[3] += cr * f;
                                                                wv[4] += cg * f;
                                                                wv[5] += cb * f;
+                                                               lit = true;
                                                        }
                                                        wv += 6;
                                                }
                                        }
                                }
-                               c >>= 1;
-                               b++;
                        }
                }
        }
+       return lit;
 }
 
-void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha)
+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)(realtime * TURBSCALE + 96.0) & 255];
        glpoly_t *p;
-       float   wvert[1024*6], *wv, *v;
+       float   *wv, *v;
        wv = wvert;
        for (p = s->polys;p;p = p->next)
        {
@@ -449,7 +457,7 @@ void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha)
                }
        }
        if (s->dlightframe == r_dlightframecount && r_dynamic.value)
-               R_LightSurface(s->dlightbits, s->polys, wvert);
+               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)
@@ -461,12 +469,8 @@ void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha)
        }
 }
 
-void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform)
+void RSurf_CheckLightmap(msurface_t *s)
 {
-       int                     i;
-       glpoly_t        *p;
-       float           wvert[64*6], *wv, *v;
-       // check for lightmap modification
        if (r_dynamic.value)
        {
                if (r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf
@@ -476,8 +480,13 @@ void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform)
                || (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)
+}
+
+void RSurf_Transform(glpoly_t *p, int transform)
+{
+       int             i;
+       float   *v, *wv = wvert;
+       for (;p;p = p->next)
        {
                for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
                {
@@ -489,77 +498,112 @@ void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform)
                        wv += 6;
                }
        }
-       if (s->dlightframe == r_dlightframecount && r_dynamic.value)
-               R_LightSurface(s->dlightbits, s->polys, wvert);
-       wv = wvert;
-       for (p = s->polys;p;p = p->next)
+}
+
+void RSurf_EmitWallpolys(int lightmap, glpoly_t *p, texture_t *t, int lit)
+{
+       int             i;
+       float   *v, *wv = wvert;
+       wallpoly_t *wp = &wallpoly[currentwallpoly];
+       wallvert_t *out = &wallvert[currentwallvert];
+       for (;p;p = p->next)
        {
                if (currentwallpoly >= MAX_WALLPOLYS)
                        break;
+               if (currentwallvert+p->numverts > MAX_WALLVERTS)
+                       break;
                v = p->verts[0];
-               wallpoly[currentwallpoly].texnum = (unsigned short) t->gl_texturenum;
-               wallpoly[currentwallpoly].lighttexnum = (unsigned short) lightmap_textures + s->lightmaptexturenum;
-               wallpoly[currentwallpoly].glowtexnum = (unsigned short) t->gl_glowtexturenum;
-               wallpoly[currentwallpoly].firstvert = currentwallvert;
-               wallpoly[currentwallpoly].numverts = p->numverts;
-               wallpoly[currentwallpoly++].lit = true;
-               for (i = 0;i<p->numverts;i++, v += VERTEXSIZE)
+               wp->texnum = (unsigned short) t->gl_texturenum;
+               wp->lighttexnum = (unsigned short) lightmap;
+               wp->glowtexnum = (unsigned short) t->gl_glowtexturenum;
+               wp->firstvert = currentwallvert;
+               wp->numverts = p->numverts;
+               wp->lit = lit;
+               wp++;
+               currentwallpoly++;
+               currentwallvert += p->numverts;
+               for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++)
                {
-                       if (lighthalf)
-                       {
-                               wallvert[currentwallvert].r = (byte) (bound(0, (int) wv[3] >> 1, 255));
-                               wallvert[currentwallvert].g = (byte) (bound(0, (int) wv[4] >> 1, 255));
-                               wallvert[currentwallvert].b = (byte) (bound(0, (int) wv[5] >> 1, 255));
-                               wallvert[currentwallvert].a = 255;
-                       }
-                       else
+                       if (lit)
                        {
-                               wallvert[currentwallvert].r = (byte) (bound(0, (int) wv[3], 255));
-                               wallvert[currentwallvert].g = (byte) (bound(0, (int) wv[4], 255));
-                               wallvert[currentwallvert].b = (byte) (bound(0, (int) wv[5], 255));
-                               wallvert[currentwallvert].a = 255;
+                               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;
+                               }
+                               else
+                               {
+                                       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;
+                               }
                        }
-                       wallvert[currentwallvert].vert[0] = wv[0];
-                       wallvert[currentwallvert].vert[1] = wv[1];
-                       wallvert[currentwallvert].vert[2] = wv[2];
-                       wallvert[currentwallvert].s = v[3];
-                       wallvert[currentwallvert].t = v[4];
-                       wallvert[currentwallvert].u = v[5];
-                       wallvert[currentwallvert++].v = v[6];
-                       wv += 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];
                }
        }
 }
 
+void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
+{
+       int                     lit = false;
+       // check for lightmap modification
+       RSurf_CheckLightmap(s);
+       RSurf_Transform(s->polys, transform);
+       if (s->dlightframe == r_dlightframecount && r_dynamic.value)
+               lit = RSurf_Light(s->dlightbits, s->polys);
+       RSurf_EmitWallpolys(lightmap_textures + s->lightmaptexturenum, s->polys, t, lit);
+}
+
 // LordHavoc: transparent brush models
 extern int r_dlightframecount;
 extern float modelalpha;
-//extern vec3_t shadecolor;
-//qboolean R_CullBox (vec3_t mins, vec3_t maxs);
-//void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-//void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
-//void EmitWaterPolys (msurface_t *fa);
 
-void R_WallSurfVertex(msurface_t *s, texture_t *t, qboolean transform, qboolean isbmodel)
+void RSurf_EmitWallVertex(glpoly_t *p, texture_t *t, int modulate, int alpha)
 {
-       int                     i, alpha;
+       int i;
+       float *v, *wv = wvert;
+       if (modulate)
+       {
+               for (;p;p = p->next)
+               {
+                       v = p->verts[0];
+                       transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 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();
+               }
+       }
+       else
+       {
+               for (;p;p = p->next)
+               {
+                       v = p->verts[0];
+                       transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 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();
+               }
+       }
+}
+
+void RSurf_WallVertexTransform(msurface_t *s, texture_t *t, int transform)
+{
+       int                     i;
        glpoly_t        *p;
-       float           wvert[64*6], *wv, *v;
+       float           *wv, *v;
        int                     size3;
        float           scale;
        byte            *lm;
        size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3; // *3 for colored lighting
-       alpha = (int) (modelalpha * 255.0f);
-       // check for lightmap modification
-       if (r_dynamic.value)
-       {
-               if (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)
        {
@@ -590,31 +634,14 @@ void R_WallSurfVertex(msurface_t *s, texture_t *t, qboolean transform, qboolean
                        wv += 6;
                }
        }
+}
+
+void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmodel)
+{
+       RSurf_WallVertexTransform(s, t, transform);
        if (s->dlightframe == r_dlightframecount && r_dynamic.value)
-               R_LightSurface(s->dlightbits, s->polys, wvert);
-       wv = wvert;
-       if (isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1))
-       {
-               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);
-                       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();
-               }
-       }
-       else
-       {
-               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);
-                       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();
-               }
-       }
+               RSurf_Light(s->dlightbits, s->polys);
+       RSurf_EmitWallVertex(s->polys, t, isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1), (int) (modelalpha * 255.0f));
 }
 
 /*
@@ -624,27 +651,26 @@ DrawTextureChains
 */
 extern qboolean hlbsp;
 extern char skyname[];
-//extern qboolean SV_TestLine (hull_t *hull, int num, vec3_t p1, vec3_t p2);
-void R_DrawSurf(msurface_t *s, qboolean isbmodel, qboolean vertexlit)
+void R_DrawSurf(msurface_t *s, int isbmodel, int vertexlit)
 {
        texture_t *t;
        if (s->flags & SURF_DRAWSKY)
        {
                skyisvisible = true;
                if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
-                       R_SkySurf(s, false);
+                       RSurf_DrawSky(s, false);
                return;
        }
        t = R_TextureAnimation (s->texinfo->texture);
        if (s->flags & SURF_DRAWTURB)
        {
-               R_WaterSurf(s, t, false, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
+               RSurf_DrawWater(s, t, false, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
                return;
        }
        if (vertexlit)
-               R_WallSurfVertex(s, t, false, false);
+               RSurf_DrawWallVertex(s, t, false, false);
        else
-               R_WallSurf(s, t, false);
+               RSurf_DrawWall(s, t, false);
 }
 
 void DrawTextureChains (void)
@@ -667,7 +693,7 @@ void DrawTextureChains (void)
                        skyisvisible = true;
                        if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
                                for (;s;s = s->texturechain)
-                                       R_SkySurf(s, false);
+                                       RSurf_DrawSky(s, false);
                        continue;
                }
                t = R_TextureAnimation (cl.worldmodel->textures[n]);
@@ -676,15 +702,15 @@ void DrawTextureChains (void)
                {
                        int alpha = s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f;
                        for (;s;s = s->texturechain)
-                               R_WaterSurf(s, t, false, alpha);
+                               RSurf_DrawWater(s, t, false, alpha);
                        continue;
                }
                if (gl_vertex.value)
                        for (;s;s = s->texturechain)
-                               R_WallSurfVertex(s, t, false, false);
+                               RSurf_DrawWallVertex(s, t, false, false);
                else
                        for (;s;s = s->texturechain)
-                               R_WallSurf(s, t, false);
+                               RSurf_DrawWall(s, t, false);
        }
 }
 
@@ -701,7 +727,7 @@ void R_DrawBrushModel (entity_t *e)
        vec3_t          mins, maxs;
        msurface_t      *s;
        model_t         *clmodel;
-       qboolean        rotated, vertexlit = false;
+       int     rotated, vertexlit = false;
        texture_t       *t;
        vec3_t          org;
 
@@ -767,19 +793,19 @@ e->angles[0] = -e->angles[0];     // stupid quake bug
 //                     R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent);
                        if (s->flags & SURF_DRAWSKY)
                        {
-                               R_SkySurf(s, true);
+                               RSurf_DrawSky(s, true);
                                continue;
                        }
                        t = R_TextureAnimation (s->texinfo->texture);
                        if (s->flags & SURF_DRAWTURB)
                        {
-                               R_WaterSurf(s, t, true, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
+                               RSurf_DrawWater(s, t, true, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
                                continue;
                        }
                        if (vertexlit || s->texinfo->texture->transparent)
-                               R_WallSurfVertex(s, t, true, true);
+                               RSurf_DrawWallVertex(s, t, true, true);
                        else
-                               R_WallSurf(s, t, true);
+                               RSurf_DrawWall(s, t, true);
                }
        }
        UploadLightmaps();
index 43923c65ebd5e8a5338601505cfdb3506bf3816a..e2a35ffacace7d13ef0b2f5260fc7b8354e1f65c 100644 (file)
@@ -369,12 +369,23 @@ void SCR_SizeDown_f (void)
 
 //============================================================================
 
+void gl_screen_start()
+{
+       scr_ram = Draw_PicFromWad ("ram");
+       scr_net = Draw_PicFromWad ("net");
+       scr_turtle = Draw_PicFromWad ("turtle");
+}
+
+void gl_screen_shutdown()
+{
+}
+
 /*
 ==================
 SCR_Init
 ==================
 */
-void SCR_Init (void)
+void GL_Screen_Init (void)
 {
 
        Cvar_RegisterVariable (&scr_fov);
@@ -394,11 +405,9 @@ void SCR_Init (void)
        Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
        Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
 
-       scr_ram = Draw_PicFromWad ("ram");
-       scr_net = Draw_PicFromWad ("net");
-       scr_turtle = Draw_PicFromWad ("turtle");
-
        scr_initialized = true;
+
+       R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown);
 }
 
 
@@ -780,9 +789,9 @@ void SCR_BringDownConsole (void)
                SCR_UpdateScreen ();
 
        cl.cshifts[0].percent = 0;              // no area contents palette on next frame
-       VID_SetPalette (host_basepal);
 }
 
+void DrawCrosshair(int num);
 void GL_Set2D (void);
 
 extern void SHOWLMP_drawall();
@@ -892,7 +901,7 @@ void SCR_UpdateScreen (void)
        if (vid.recalc_refdef)
                SCR_CalcRefdef ();
 
-       glClearColor(1,0,0,0);
+       glClearColor(0,0,0,0);
        glClear (GL_COLOR_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
 
 //
@@ -928,7 +937,7 @@ void SCR_UpdateScreen (void)
        else
        {
                if (crosshair.value)
-                       Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
+                       DrawCrosshair(crosshair.value);
                
                SCR_DrawRam ();
                SCR_DrawNet ();
diff --git a/gl_textures.c b/gl_textures.c
new file mode 100644 (file)
index 0000000..7534ab4
--- /dev/null
@@ -0,0 +1,924 @@
+#include "quakedef.h"
+
+cvar_t         gl_max_size = {"gl_max_size", "1024"};
+cvar_t         gl_picmip = {"gl_picmip", "0"};
+cvar_t         gl_lerpimages = {"gl_lerpimages", "1"};
+
+int            gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
+int            gl_filter_max = GL_LINEAR;
+
+
+int            texels;
+
+// 4096x4096
+#define MAXMIPS 12
+
+typedef struct
+{
+       int             texnum;
+       byte    *texels[MAXMIPS];
+       unsigned short texelsize[MAXMIPS][2];
+       char    identifier[64];
+       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
+} gltexture_t;
+
+#define        MAX_GLTEXTURES  4096
+gltexture_t    gltextures[MAX_GLTEXTURES];
+int                    numgltextures;
+
+typedef struct
+{
+       char *name;
+       int     minimize, maximize;
+} glmode_t;
+
+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},
+       {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
+       {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
+       {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
+};
+
+/*
+===============
+Draw_TextureMode_f
+===============
+*/
+void Draw_TextureMode_f (void)
+{
+       int             i;
+       gltexture_t     *glt;
+
+       if (Cmd_Argc() == 1)
+       {
+               for (i=0 ; i< 6 ; i++)
+                       if (gl_filter_min == modes[i].minimize)
+                       {
+                               Con_Printf ("%s\n", modes[i].name);
+                               return;
+                       }
+               Con_Printf ("current filter is unknown???\n");
+               return;
+       }
+
+       for (i=0 ; i< 6 ; i++)
+       {
+               if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
+                       break;
+       }
+       if (i == 6)
+       {
+               Con_Printf ("bad filter name\n");
+               return;
+       }
+
+       gl_filter_min = modes[i].minimize;
+       gl_filter_max = modes[i].maximize;
+
+       // change all the existing mipmap texture objects
+       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+       {
+               if (glt->mipmap)
+               {
+                       glBindTexture(GL_TEXTURE_2D, glt->texnum);
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+               }
+       }
+}
+
+extern int buildnumber;
+
+char engineversion[40];
+
+void GL_UploadTexture (gltexture_t *glt);
+void gl_textures_start()
+{
+       int i;
+       gltexture_t *glt;
+       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+               GL_UploadTexture(glt);
+}
+
+void gl_textures_shutdown()
+{
+}
+
+void GL_Textures_Init (void)
+{
+       Cvar_RegisterVariable (&gl_max_size);
+       Cvar_RegisterVariable (&gl_picmip);
+       Cvar_RegisterVariable (&gl_lerpimages);
+
+       // 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");
+
+       Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
+
+       R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
+}
+
+/*
+================
+GL_FindTexture
+================
+*/
+int GL_FindTexture (char *identifier)
+{
+       int             i;
+       gltexture_t     *glt;
+
+       for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+       {
+               if (!strcmp (identifier, glt->identifier))
+                       return gltextures[i].texnum;
+       }
+
+       return -1;
+}
+
+extern byte qgamma[];
+
+// LordHavoc: gamma correction and improved resampling
+void GL_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);
+       endx = (inwidth-1);
+       for (j = 0,f = 0;j < outwidth;j++, f += fstep)
+       {
+               xi = (int) f >> 16;
+               if (xi != oldx)
+               {
+                       in += (xi - oldx) * 4;
+                       oldx = xi;
+               }
+               if (xi < endx)
+               {
+                       l2 = f & 0xFFFF;
+                       l1 = 0x10000 - l2;
+                       *out++ = qgamma[(byte) ((in[0] * l1 + in[4] * l2) >> 16)];
+                       *out++ = qgamma[(byte) ((in[1] * l1 + in[5] * l2) >> 16)];
+                       *out++ = qgamma[(byte) ((in[2] * l1 + in[6] * l2) >> 16)];
+                       *out++ =        (byte) ((in[3] * l1 + in[7] * l2) >> 16) ;
+               }
+               else // last pixel of the line has no pixel to lerp to
+               {
+                       *out++ = qgamma[in[0]];
+                       *out++ = qgamma[in[1]];
+                       *out++ = qgamma[in[2]];
+                       *out++ =        in[3] ;
+               }
+       }
+}
+
+/*
+================
+GL_ResampleTexture
+================
+*/
+void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight)
+{
+       // LordHavoc: gamma correction and greatly improved resampling
+       if (gl_lerpimages.value)
+       {
+               int             i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
+               byte    *inrow, *out, *row1, *row2;
+               out = outdata;
+               fstep = (int) (inheight*65536.0f/outheight);
+
+               row1 = malloc(outwidth*4);
+               row2 = malloc(outwidth*4);
+               inrow = indata;
+               oldy = 0;
+               GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+               GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+               for (i = 0, f = 0;i < outheight;i++,f += fstep)
+               {
+                       yi = f >> 16;
+                       if (yi != oldy)
+                       {
+                               inrow = (byte *)indata + inwidth*4*yi;
+                               if (yi == oldy+1)
+                                       memcpy(row1, row2, outwidth*4);
+                               else
+                                       GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+                               if (yi < endy)
+                                       GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+                               else
+                                       memcpy(row2, row1, outwidth*4);
+                               oldy = yi;
+                       }
+                       if (yi < endy)
+                       {
+                               l2 = f & 0xFFFF;
+                               l1 = 0x10000 - l2;
+                               for (j = 0;j < outwidth;j++)
+                               {
+                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+                                       *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+                               }
+                               row1 -= outwidth*4;
+                               row2 -= outwidth*4;
+                       }
+                       else // last line has no pixels to lerp to
+                       {
+                               for (j = 0;j < outwidth;j++)
+                               {
+                                       *out++ = *row1++;
+                                       *out++ = *row1++;
+                                       *out++ = *row1++;
+                                       *out++ = *row1++;
+                               }
+                               row1 -= outwidth*4;
+                       }
+               }
+               free(row1);
+               free(row2);
+       }
+       else
+       {
+               int             i, j;
+               unsigned        frac, fracstep;
+               byte    *inrow, *out, *inpix;
+               out = outdata;
+
+               fracstep = inwidth*0x10000/outwidth;
+               for (i=0 ; i<outheight ; i++)
+               {
+                       inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
+                       frac = fracstep >> 1;
+                       for (j=0 ; j<outwidth ; j+=4)
+                       {
+                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
+                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
+                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
+                               inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ =       *inpix++ ;frac += fracstep;
+                       }
+               }
+       }
+}
+
+/*
+================
+GL_Resample8BitTexture -- JACK
+================
+*/
+/*
+void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out,  int outwidth, int outheight)
+{
+       int             i, j;
+       unsigned        char *inrow;
+       unsigned        frac, fracstep;
+
+       fracstep = inwidth*0x10000/outwidth;
+       for (i=0 ; i<outheight ; i++, out += outwidth)
+       {
+               inrow = in + inwidth*(i*inheight/outheight);
+               frac = fracstep >> 1;
+               for (j=0 ; j<outwidth ; j+=4)
+               {
+                       out[j  ] = inrow[frac>>16];frac += fracstep;
+                       out[j+1] = inrow[frac>>16];frac += fracstep;
+                       out[j+2] = inrow[frac>>16];frac += fracstep;
+                       out[j+3] = inrow[frac>>16];frac += fracstep;
+               }
+       }
+}
+*/
+
+
+/*
+================
+GL_MipMap
+
+Operates in place, quartering the size of the texture
+================
+*/
+/*
+void GL_MipMap (byte *in, int width, int height)
+{
+       int             i, j;
+       byte    *out;
+
+       width <<=2;
+       height >>= 1;
+       out = in;
+       for (i=0 ; i<height ; i++, in+=width)
+       {
+               for (j=0 ; j<width ; j+=8, out+=4, in+=8)
+               {
+                       out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
+                       out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
+                       out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
+                       out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
+               }
+       }
+}
+*/
+
+/*
+================
+GL_MipMap8Bit
+
+Mipping for 8 bit textures
+================
+*/
+/*
+void GL_MipMap8Bit (byte *in, int width, int height)
+{
+       int             i, j;
+       unsigned short     r,g,b;
+       byte    *out, *at1, *at2, *at3, *at4;
+
+       height >>= 1;
+       out = in;
+       for (i=0 ; i<height ; i++, in+=width)
+       {
+               for (j=0 ; j<width ; j+=2, out+=1, in+=2)
+               {
+                       at1 = (byte *) (d_8to24table + in[0]);
+                       at2 = (byte *) (d_8to24table + in[1]);
+                       at3 = (byte *) (d_8to24table + in[width+0]);
+                       at4 = (byte *) (d_8to24table + in[width+1]);
+
+                       r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
+                       g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
+                       b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
+
+                       out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
+               }
+       }
+}
+*/
+
+/*
+===============
+GL_Upload32
+===============
+*/
+/*
+void GL_Upload32 (void *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+       int samples, scaled_width, scaled_height, i;
+       byte *in, *out, *scaled;
+
+       for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+               ;
+       for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+               ;
+
+       scaled_width >>= (int)gl_picmip.value;
+       scaled_height >>= (int)gl_picmip.value;
+
+       if (scaled_width > gl_max_size.value)
+               scaled_width = gl_max_size.value;
+       if (scaled_height > gl_max_size.value)
+               scaled_height = gl_max_size.value;
+
+       if (alpha)
+       {
+               alpha = false;
+               in = data;
+               for (i = 3;i < width*height*4;i += 4)
+                       if (in[i] != 255)
+                       {
+                               alpha = true;
+                               break;
+                       }
+       }
+
+       samples = alpha ? gl_alpha_format : gl_solid_format;
+
+       texels += scaled_width * scaled_height;
+
+       scaled = malloc(scaled_width*scaled_height*4);
+       if (scaled_width == width && scaled_height == height)
+       {
+               // LordHavoc: gamma correct while copying
+               in = (byte *)data;
+               out = (byte *)scaled;
+               for (i = 0;i < width*height;i++)
+               {
+                       *out++ = qgamma[*in++];
+                       *out++ = qgamma[*in++];
+                       *out++ = qgamma[*in++];
+                       *out++ = *in++;
+               }
+       }
+       else
+               GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+       glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+       if (mipmap)
+       {
+               int             miplevel;
+
+               miplevel = 0;
+               while (scaled_width > 1 || scaled_height > 1)
+               {
+                       GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
+                       scaled_width >>= 1;
+                       scaled_height >>= 1;
+                       if (scaled_width < 1)
+                               scaled_width = 1;
+                       if (scaled_height < 1)
+                               scaled_height = 1;
+                       miplevel++;
+                       glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+               }
+       }
+
+       if (mipmap)
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       else
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       free(scaled);
+}
+
+void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap)
+{
+       int             scaled_width, scaled_height;
+       byte    *scaled = NULL;
+
+       for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+               ;
+       for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+               ;
+
+       scaled_width >>= (int)gl_picmip.value;
+       scaled_height >>= (int)gl_picmip.value;
+
+       if (scaled_width > gl_max_size.value)
+               scaled_width = gl_max_size.value;
+       if (scaled_height > gl_max_size.value)
+               scaled_height = gl_max_size.value;
+
+       texels += scaled_width * scaled_height;
+
+       if (scaled_width == width && scaled_height == height)
+       {
+               if (!mipmap)
+               {
+                       glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
+                       goto done;
+               }
+               scaled = malloc(scaled_width*scaled_height*4);
+               memcpy (scaled, data, width*height);
+       }
+       else
+       {
+               scaled = malloc(scaled_width*scaled_height*4);
+               GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
+       }
+
+       glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+       if (mipmap)
+       {
+               int             miplevel;
+
+               miplevel = 0;
+               while (scaled_width > 1 || scaled_height > 1)
+               {
+                       GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
+                       scaled_width >>= 1;
+                       scaled_height >>= 1;
+                       if (scaled_width < 1)
+                               scaled_width = 1;
+                       if (scaled_height < 1)
+                               scaled_height = 1;
+                       miplevel++;
+                       glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+               }
+       }
+done: ;
+
+
+       if (mipmap)
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       else
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       free(scaled);
+}
+*/
+
+extern qboolean VID_Is8bit();
+
+/*
+===============
+GL_Upload8
+===============
+*/
+/*
+void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha)
+{
+       static  unsigned *trans;
+       int                     i, s;
+       qboolean        noalpha;
+       int                     p;
+       byte    *indata;
+       int             *outdata;
+
+       s = width*height;
+       trans = malloc(s*4);
+       // if there are no transparent pixels, make it a 3 component
+       // texture even if it was specified as otherwise
+       if (alpha)
+       {
+               noalpha = true;
+               for (i=0 ; i<s ; i++)
+               {
+                       p = data[i];
+                       if (p != 255)
+                               trans[i] = d_8to24table[p];
+                       else
+                       {
+                               trans[i] = 0; // force to black
+                               noalpha = false;
+                       }
+               }
+
+               if (noalpha)
+               {
+                       if (VID_Is8bit() && (data!=scrap_texels[0]))
+                       {
+                               GL_Upload8_EXT (data, width, height, mipmap);
+                               free(trans);
+                               return;
+                       }
+                       alpha = false;
+               }
+       }
+       else
+       {
+               // LordHavoc: dodge the copy if it will be uploaded as 8bit
+               if (VID_Is8bit() && (data!=scrap_texels[0]))
+               {
+                       GL_Upload8_EXT (data, width, height, mipmap);
+                       free(trans);
+                       return;
+               }
+               //if (s&3)
+               //      Sys_Error ("GL_Upload8: s&3");
+               indata = data;
+               outdata = trans;
+               if (s&1)
+                       *outdata++ = d_8to24table[*indata++];
+               if (s&2)
+               {
+                       *outdata++ = d_8to24table[*indata++];
+                       *outdata++ = d_8to24table[*indata++];
+               }
+               for (i = 0;i < s;i+=4)
+               {
+                       *outdata++ = d_8to24table[*indata++];
+                       *outdata++ = d_8to24table[*indata++];
+                       *outdata++ = d_8to24table[*indata++];
+                       *outdata++ = d_8to24table[*indata++];
+               }
+       }
+
+       GL_Upload32 (trans, width, height, mipmap, alpha);
+       free(trans);
+}
+*/
+
+void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped)
+{
+       int i, w, h, size, done;
+       if (glt->texels[0])
+               free(glt->texels[0]);
+       glt->texelsize[0][0] = width;
+       glt->texelsize[0][1] = height;
+       if (mipmapped)
+       {
+               size = 0;
+               w = width;h = height;
+               i = 0;
+               done = false;
+               for (i = 0;i < MAXMIPS;i++)
+               {
+                       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
+                       {
+                               i++;
+                               break;
+                       }
+               }
+               while (i < MAXMIPS)
+                       glt->texels[i++] = NULL;
+               glt->texels[0] = malloc(size);
+               for (i = 1;i < MAXMIPS && glt->texels[i];i++)
+                       glt->texels[i] += (int) glt->texels[0];
+       }
+       else
+       {
+               glt->texels[0] = malloc(width*height*4);
+               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)
+{
+       int x, y, width2, height2, nextrow;
+       if (width > destwidth)
+       {
+               if (height > destheight)
+               {
+                       // reduce both
+                       width2 = width >> 1;
+                       height2 = height >> 1;
+                       nextrow = width << 2;
+                       for (y = 0;y < height2;y++)
+                       {
+                               for (x = 0;x < width2;x++)
+                               {
+                                       out[0] = (byte) ((in[0] + in[4] + in[nextrow  ] + in[nextrow+4]) >> 2);
+                                       out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
+                                       out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
+                                       out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
+                                       out += 4;
+                                       in += 8;
+                               }
+                               in += nextrow; // skip a line
+                       }
+               }
+               else
+               {
+                       // reduce width
+                       width2 = width >> 1;
+                       for (y = 0;y < height;y++)
+                       {
+                               for (x = 0;x < width2;x++)
+                               {
+                                       out[0] = (byte) ((in[0] + in[4]) >> 1);
+                                       out[1] = (byte) ((in[1] + in[5]) >> 1);
+                                       out[2] = (byte) ((in[2] + in[6]) >> 1);
+                                       out[3] = (byte) ((in[3] + in[7]) >> 1);
+                                       out += 4;
+                                       in += 8;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               if (height > destheight)
+               {
+                       // reduce height
+                       height2 = height >> 1;
+                       nextrow = width << 2;
+                       for (y = 0;y < height2;y++)
+                       {
+                               for (x = 0;x < width;x++)
+                               {
+                                       out[0] = (byte) ((in[0] + in[nextrow  ]) >> 1);
+                                       out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
+                                       out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
+                                       out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
+                                       out += 4;
+                                       in += 4;
+                               }
+                               in += nextrow; // skip a line
+                       }
+               }
+               else
+                       Sys_Error("GL_MipReduce: desired size already achieved\n");
+       }
+}
+
+void GL_UploadTexture (gltexture_t *glt)
+{
+       int mip, width, height;
+       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)
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       else
+       {
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+       }
+       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+/*
+================
+GL_LoadTexture
+================
+*/
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
+{
+       unsigned short  crc;
+       int                             i, width2, height2, width3, height3, w, h, mip;
+       gltexture_t             *glt;
+
+       if (isDedicated)
+               return 1;
+
+       // 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])
+       {
+               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)
+                               {
+                                       Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
+                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                                       //Sys_Error ("GL_LoadTexture: cache mismatch");
+                               }
+                               if ((gl_lerpimages.value != 0) != glt->lerped)
+                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                               return glt->texnum;
+                       }
+               }
+       }
+       // LordHavoc: although this could be an else condition as it was in the original id code,
+       //            it is more clear this way
+       // 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++];
+
+       strcpy (glt->identifier, identifier);
+       glt->texnum = texture_extension_number;
+       texture_extension_number++;
+// 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
+       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 = malloc(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);
+               }
+               free(temptexels2);
+       }
+       else // scaling...
+       {
+               byte *temptexels;
+               // pre-scaleup buffer
+               temptexels = malloc(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 = malloc(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);
+                       }
+                       free(temptexels2);
+               }
+               else // copy directly
+                       GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
+               free(temptexels);
+       }
+       if (alpha)
+       {
+               byte    *in = glt->texels[0] + 3;
+               for (i = 0;i < width*height;i++, in += 4)
+                       if (*in < 255)
+                       {
+                               glt->alpha = true;
+                               break;
+                       }
+       }
+       // 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);
+
+//     if (bytesperpixel == 1) // 8bit
+//             GL_Upload8 (data, width, height, mipmap, alpha);
+//     else // 32bit
+//             GL_Upload32 (data, width, height, mipmap, true);
+
+       return glt->texnum;
+}
+
+/*
+================
+GL_LoadPicTexture
+================
+*/
+int GL_LoadPicTexture (qpic_t *pic)
+{
+       return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
+}
+
+int GL_GetTextureSlots (int count)
+{
+       gltexture_t             *glt, *first;
+
+       first = glt = &gltextures[numgltextures];
+       while (count--)
+       {
+               glt->identifier[0] = 0;
+               glt->texnum = texture_extension_number++;
+               glt->crc = 0;
+               glt->width = 0;
+               glt->height = 0;
+               glt->bytesperpixel = 0;
+               glt++;
+               numgltextures++;
+       }
+       return first->texnum;
+}
index 5bf52b35ac45df99c86a04f3cc4a61219c2c9be5..812b82a6bbfe9a01e3df1c9f53e6b1461f015403 100644 (file)
--- a/gl_warp.c
+++ b/gl_warp.c
@@ -178,7 +178,7 @@ void GL_SubdivideSurface (msurface_t *fa)
 
 extern qboolean lighthalf;
 
-#define        SKY_TEX         4000
+int skyboxside[6];
 
 char skyname[256];
 
@@ -201,7 +201,6 @@ void R_LoadSkyBox (void)
 
        for (i=0 ; i<6 ; i++)
        {
-               glBindTexture(GL_TEXTURE_2D, SKY_TEX + i);
                sprintf (name, "env/%s%s", skyname, suf[i]);
                if (!(image_rgba = loadimagepixels(name, FALSE, 0, 0)))
                {
@@ -212,10 +211,8 @@ void R_LoadSkyBox (void)
                                continue;
                        }
                }
-               glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_rgba);
+               skyboxside[i] = GL_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, false, false, 4);
                free (image_rgba);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
 }
 
@@ -260,42 +257,42 @@ void R_SkyBox()
                glColor3f(0.5,0.5,0.5);
        else
                glColor3f(1,1,1);
-       glBindTexture(GL_TEXTURE_2D, SKY_TEX + 3); // front
+       glBindTexture(GL_TEXTURE_2D, 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, SKY_TEX + 1); // back
+       glBindTexture(GL_TEXTURE_2D, 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, SKY_TEX + 0); // right
+       glBindTexture(GL_TEXTURE_2D, 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, SKY_TEX + 2); // left
+       glBindTexture(GL_TEXTURE_2D, 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, SKY_TEX + 4); // up
+       glBindTexture(GL_TEXTURE_2D, 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, SKY_TEX + 5); // down
+       glBindTexture(GL_TEXTURE_2D, skyboxside[5]); // down
        glBegin(GL_QUADS);
        R_SkyBoxPolyVec(1, 0,  1,  1, -1);
        R_SkyBoxPolyVec(1, 1,  1, -1, -1);
@@ -430,18 +427,14 @@ R_InitSky
 A sky texture is 256*128, with the right side being a masked overlay
 ==============
 */
-// LordHavoc: changed this for GLQuake
-void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt)
+void R_InitSky (byte *src, int bytesperpixel)
 {
        int                     i, j, p;
-//     byte            *src;
        unsigned        trans[128*128];
        unsigned        transpix;
        int                     r, g, b;
        unsigned        *rgba;
 
-//     src = (byte *)mt + mt->offsets[0];
-
        if (bytesperpixel == 4)
        {
                for (i = 0;i < 128;i++)
@@ -470,16 +463,7 @@ void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt)
                ((byte *)&transpix)[3] = 0;
        }
 
-       if (!solidskytexture)
-               solidskytexture = texture_extension_number++;
-       if (!isDedicated)
-       {
-               glBindTexture(GL_TEXTURE_2D, solidskytexture );
-               glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       }
-
+       solidskytexture = GL_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, false, false, 4);
 
        if (bytesperpixel == 4)
        {
@@ -500,14 +484,6 @@ void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt)
                        }
        }
 
-       if (!alphaskytexture)
-               alphaskytexture = texture_extension_number++;
-       if (!isDedicated)
-       {
-               glBindTexture(GL_TEXTURE_2D, alphaskytexture);
-               glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       }
+       alphaskytexture = GL_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, false, true, 4);
 }
 
index bed1e189136a4b48226e98768a1b9a5c730efc8d..bab055b6509632a3b976c0aee5b4c548682a1c16 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -37,17 +37,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <GL/gl.h>
 //#include <GL/glu.h>
 
-void GL_BeginRendering (int *x, int *y, int *width, int *height);
-void GL_EndRendering (void);
+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;
 
-void GL_Upload32 (void *data, int width, int height,  qboolean mipmap, qboolean alpha);
-void GL_Upload8 (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
-int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel);
-int GL_FindTexture (char *identifier);
+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
 {
@@ -70,8 +70,8 @@ extern        int glx, gly, glwidth, glheight;
 #define BACKFACE_EPSILON       0.01
 
 
-void R_TimeRefresh_f (void);
-void R_ReadPointFile_f (void);
+extern void R_TimeRefresh_f (void);
+extern void R_ReadPointFile_f (void);
 
 //====================================================
 
@@ -103,39 +103,20 @@ extern    texture_t       *r_notexture_mip;
 extern int             d_lightstylevalue[256]; // 8.8 fraction of base light value
 
 extern qboolean        envmap;
-extern int     cnttextures[2];
-// LordHavoc: moved all code relating to particles into r_part.c
-//extern       int     particletexture;
-extern int     playertextures;
 
 extern int     skytexturenum;          // index in cl.loadmodel, not gl texture object
 
-//extern       cvar_t  r_norefresh;
 extern cvar_t  r_drawentities;
-//extern       cvar_t  r_drawworld;
 extern cvar_t  r_drawviewmodel;
 extern cvar_t  r_speeds;
-//extern       cvar_t  r_waterwarp;
 extern cvar_t  r_fullbright;
-//extern       cvar_t  r_lightmap;
 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_cull;
-//extern       cvar_t  gl_poly;
-//extern       cvar_t  gl_smoothmodels;
-//extern       cvar_t  gl_affinemodels;
-//extern       cvar_t  gl_polyblend;
-//extern       cvar_t  gl_keeptjunctions;
-//extern       cvar_t  gl_reporttjunctions;
-//extern       cvar_t  gl_nocolors;
-//extern       cvar_t  gl_doubleeyes;
-
 extern cvar_t  gl_max_size;
-extern cvar_t  gl_playermip;
 
 extern float   r_world_matrix[16];
 
@@ -144,8 +125,6 @@ extern      const char *gl_renderer;
 extern const char *gl_version;
 extern const char *gl_extensions;
 
-void R_TranslatePlayerSkin (int playernum);
-
 // Multitexture
 #define    TEXTURE0_SGIS                               0x835E
 #define    TEXTURE1_SGIS                               0x835F
@@ -259,3 +238,7 @@ extern vec_t fogdensity;
 //#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_refdef.vieworg[0]) * vpn[0] + ((v)[1] - r_refdef.vieworg[1]) * vpn[1] + ((v)[2] - r_refdef.vieworg[2]) * vpn[2])*(((v)[0] - r_refdef.vieworg[0]) * vpn[0] + ((v)[1] - r_refdef.vieworg[1]) * vpn[1] + ((v)[2] - r_refdef.vieworg[2]) * vpn[2]))))
 #define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_refdef.vieworg[0])*((v)[0] - r_refdef.vieworg[0])+((v)[1] - r_refdef.vieworg[1])*((v)[1] - r_refdef.vieworg[1])+((v)[2] - r_refdef.vieworg[2])*((v)[2] - r_refdef.vieworg[2])))))
 #define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255)))
+
+#include "r_modules.h"
+
+extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap);
diff --git a/host.c b/host.c
index e9c697eac09bbb36e00e0ff4ad271a96c783dc28..15ee313810dc9cb220bf2aecca3709d19621b88f 100644 (file)
--- a/host.c
+++ b/host.c
@@ -53,7 +53,6 @@ client_t      *host_client;                   // current client
 jmp_buf        host_abortserver;
 
 byte           *host_basepal;
-//byte         *host_colormap;
 
 cvar_t host_framerate = {"host_framerate","0"};        // set for slow motion
 cvar_t host_speeds = {"host_speeds","0"};                      // set for running times
@@ -557,74 +556,6 @@ Host_ServerFrame
 
 ==================
 */
-#ifdef FPS_20
-
-void _Host_ServerFrame (void)
-{
-// run the world state 
-       pr_global_struct->frametime = host_frametime;
-
-// read client messages
-       SV_RunClients ();
-       
-// move things around and think
-// always pause in single player if in console or menus
-       if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
-               SV_Physics ();
-}
-
-void Host_ServerFrame (void)
-{
-       float   save_host_frametime;
-       float   temp_host_frametime;
-       static float    host_serverframe_timevalue;
-
-// run the world state 
-       pr_global_struct->frametime = host_frametime;
-
-// set the time and clear the general datagram
-       SV_ClearDatagram ();
-               
-// check for new clients
-       SV_CheckForNewClients ();
-
-       temp_host_frametime = save_host_frametime = host_frametime;
-       // LordHavoc: the results of my attempts to mangle this code to process no more than sys_ticrate, 
-       // when I found that was too choppy, I changed it back to processing at least 20fps,
-       // I consider it a bit of a failure...  because I felt a little out of control in singleplayer
-       // (sliding around)
-       //if (host_serverframe_timevalue < -0.2) // don't let it get way out of range
-       //      host_serverframe_timevalue = -0.2;
-       //host_serverframe_timevalue += host_frametime;
-       // process frames (several if rendering is too slow to run well as a server)
-       while(temp_host_frametime > 0.0)
-       {
-               host_frametime = temp_host_frametime;
-               if (host_frametime > 0.05)
-                       host_frametime = 0.05;
-               temp_host_frametime -= host_frametime;
-       //      host_serverframe_timevalue -= host_frametime;
-               _Host_ServerFrame ();
-       }
-       host_frametime = save_host_frametime;
-
-// send all messages to the clients
-       SV_SendClientMessages ();
-// LordHavoc: sadly, this didn't look good to the person running the server in listen mode
-       /*
-// wait until enough time has built up when the framerate exceeds sys_ticrate
-       if (host_serverframe_timevalue >= sys_ticrate.value)
-       //{
-       //      while(host_serverframe_timevalue >= sys_ticrate.value)
-       //              host_serverframe_timevalue -= sys_ticrate.value;
-// send all messages to the clients
-               SV_SendClientMessages ();
-       }
-       */
-}
-
-#else
-
 double frametimetotal = 0, lastservertime = 0;
 void Host_ServerFrame (void)
 {
@@ -655,8 +586,6 @@ void Host_ServerFrame (void)
        SV_SendClientMessages ();
 }
 
-#endif
-
 
 /*
 ==================
@@ -862,6 +791,8 @@ void Host_InitVCR (quakeparms_t *parms)
        
 }
 
+void Render_Init();
+
 /*
 ====================
 Host_Init
@@ -914,18 +845,13 @@ void Host_Init (quakeparms_t *parms)
                if (!host_basepal)
                        Sys_Error ("Couldn't load gfx/palette.lmp");
                host_basepal[765] = host_basepal[766] = host_basepal[767] = 0; // LordHavoc: force the transparent color to black
-//             host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp", false);
-//             if (!host_colormap)
-//                     Sys_Error ("Couldn't load gfx/colormap.lmp");
 
 #ifndef _WIN32 // on non win32, mouse comes before video for security reasons
                IN_Init ();
 #endif
                VID_Init (host_basepal);
 
-               Draw_Init ();
-               SCR_Init ();
-               R_Init ();
+               Render_Init();
                S_Init ();
                CDAudio_Init ();
                Sbar_Init ();
@@ -977,6 +903,7 @@ void Host_Shutdown(void)
 
        if (cls.state != ca_dedicated)
        {
+               R_ShutdownModules();
                VID_Shutdown();
        }
 }
index c08e92125405bcbb31a682cc5b70a47858a8d28f..1e18df996305f07311dc68d1b8c91ac67cb35bd1 100644 (file)
@@ -1469,15 +1469,15 @@ void Host_Viewframe_f (void)
 
 void PrintFrameName (model_t *m, int frame)
 {
-       aliashdr_t                      *hdr;
-       maliasframedesc_t       *pframedesc;
+       maliashdr_t     *mheader;
+       maliasframe_t   *frameinfo;
 
-       hdr = (aliashdr_t *)Mod_Extradata (m);
-       if (!hdr)
+       mheader = (maliashdr_t *)Mod_Extradata (m);
+       if (!mheader)
                return;
-       pframedesc = &hdr->frames[frame];
+       frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame];
        
-       Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
+       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
 }
 
 /*
diff --git a/image.c b/image.c
index d48bee4ede3948d268925bb3ed2be4812a629472..6740daca29e9b710f26bbf149d9e84054bec25f6 100644 (file)
--- a/image.c
+++ b/image.c
@@ -4,6 +4,59 @@
 int            image_width;
 int            image_height;
 
+// note: pal must be 32bit color
+void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal)
+{
+       int *iout = (void *)out;
+       while (pixels >= 8)
+       {
+               iout[0] = pal[in[0]];
+               iout[1] = pal[in[1]];
+               iout[2] = pal[in[2]];
+               iout[3] = pal[in[3]];
+               iout[4] = pal[in[4]];
+               iout[5] = pal[in[5]];
+               iout[6] = pal[in[6]];
+               iout[7] = pal[in[7]];
+               in += 8;
+               iout += 8;
+               pixels -= 8;
+       }
+       if (pixels & 4)
+       {
+               iout[0] = pal[in[0]];
+               iout[1] = pal[in[1]];
+               iout[2] = pal[in[2]];
+               iout[3] = pal[in[3]];
+               in += 4;
+               iout += 4;
+       }
+       if (pixels & 2)
+       {
+               iout[0] = pal[in[0]];
+               iout[1] = pal[in[1]];
+               in += 2;
+               iout += 2;
+       }
+       if (pixels & 1)
+               iout[0] = pal[in[0]];
+}
+
+extern byte qgamma[];
+void Image_CopyRGBAGamma(byte *in, byte *out, int pixels)
+{
+       while (pixels--)
+       {
+               out[0] = qgamma[in[0]];
+               out[1] = qgamma[in[1]];
+               out[2] = qgamma[in[2]];
+               out[3] =        in[3] ;
+               in += 4;
+               out += 4;
+       }
+}
+
+
 /*
 =================================================================
 
@@ -101,6 +154,7 @@ byte* LoadPCX (FILE *f, int matchwidth, int matchheight)
                        }
                }
        }
+       fclose(f);
        image_width = pcx->xmax+1;
        image_height = pcx->ymax+1;
        return image_rgba;
@@ -184,7 +238,7 @@ byte* LoadTGA (FILE *fin, int matchwidth, int matchheight)
 
        if (targa_header.colormap_type !=0 
                || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
-               Host_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+               Host_Error ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
 
        columns = targa_header.width;
        rows = targa_header.height;
@@ -309,12 +363,50 @@ byte* LoadTGA (FILE *fin, int matchwidth, int matchheight)
        return image_rgba;
 }
 
+/*
+============
+LoadLMP
+============
+*/
+byte* LoadLMP (FILE *f, int matchwidth, int matchheight)
+{
+       byte    *image_rgba;
+       int             width, height;
+
+       // parse the very complicated header *chuckle*
+       width = fgetLittleLong(f);
+       height = fgetLittleLong(f);
+       if ((unsigned) width > 4096 || (unsigned) height > 4096)
+               Host_Error("LoadLMP: invalid size\n");
+       if (matchwidth && width != matchwidth)
+               return NULL;
+       if (matchheight && height != matchheight)
+               return NULL;
+
+       image_rgba = malloc(width*height*4);
+       fread(image_rgba + width*height*3, 1, width*height, f);
+       fclose(f);
+
+       Image_Copy8bitRGBA(image_rgba + width*height*3, image_rgba, width*height, d_8to24table);
+       image_width = width;
+       image_height = height;
+       return image_rgba;
+}
+
 byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight)
 {
        FILE    *f;
        char    basename[128], name[128];
-       byte    *image_rgba;
+       byte    *image_rgba, *c;
        COM_StripExtension(filename, basename); // strip the extension to allow TGA skins on Q2 models despite the .pcx in the skin name
+       // replace *'s with +, so commandline utils don't get confused when dealing with the external files
+       c = basename;
+       while (*c)
+       {
+               if (*c == '*')
+                       *c = '+';
+               c++;
+       }
        sprintf (name, "textures/%s.tga", basename);
        COM_FOpenFile (name, &f, true);
        if (f)
@@ -331,6 +423,13 @@ byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int ma
        COM_FOpenFile (name, &f, true);
        if (f)
                return LoadPCX (f, matchwidth, matchheight);
+       sprintf (name, "%s.lmp", basename);
+       COM_FOpenFile (name, &f, true);
+       if (f)
+               return LoadLMP (f, matchwidth, matchheight);
+       if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
+               return image_rgba;
+       COM_StripExtension(filename, basename); // do it again with a * this time
        if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
                return image_rgba;
        if (complain)
@@ -338,22 +437,28 @@ byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int ma
        return NULL;
 }
 
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight)
+int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
 {
+       int texnum;
        byte *data;
        if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
                return 0;
+       texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
+       free(data);
+       return texnum;
+       /*
        if (texnum >= 0) // specific texnum, not cached
        {
                glBindTexture(GL_TEXTURE_2D, texnum);
-               GL_Upload32 (data, image_width, image_height, true, true);
+               GL_Upload32 (data, image_width, image_height, mipmap, true);
                free(data);
                return texnum;
        }
        else // any texnum, cached
        {
-               texnum = GL_LoadTexture (filename, image_width, image_height, data, true, true, 4);
+               texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
                free(data);
                return texnum;
        }
+       */
 }
diff --git a/image.h b/image.h
new file mode 100644 (file)
index 0000000..375f511
--- /dev/null
+++ b/image.h
@@ -0,0 +1,3 @@
+
+extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
+extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
index d290c4b84bf82927cc415f6d570d4295e5c61415..2f7b5f2409e90ec8f35ffd1dc5a4d7face22e104 100644 (file)
@@ -29,14 +29,14 @@ void Mod_AliasInit (void)
 {
 }
 
-aliashdr_t     *pheader;
-
-typedef struct
-{
-       int v[3];
-       vec3_t normal;
-} temptris_t;
-temptris_t *temptris;
+//aliashdr_t   *pheader;
+
+//typedef struct
+//{
+//     int v[3];
+//     vec3_t normal;
+//} temptris_t;
+//temptris_t *temptris;
 //stvert_t     stverts[MAXALIASVERTS];
 //mtriangle_t  triangles[MAXALIASTRIS];
 
@@ -50,16 +50,23 @@ byte                *player_8bit_texels;
 
 float          aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations
 
-// LordHavoc: changed to use the normals from the model data itself
+#define MAXVERTS 8192
+float vertst[MAXVERTS][2];
+int vertusage[MAXVERTS];
+int vertonseam[MAXVERTS];
+int vertremap[MAXVERTS];
+unsigned short temptris[MAXVERTS][3];
+
 #define NUMVERTEXNORMALS       162
 extern float   r_avertexnormals[NUMVERTEXNORMALS][3];
-void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
+void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
 {
-       int i;
+       int i, j;
        vec3_t temp;
-       for (i = 0;i < numverts;i++)
+       for (i = 0;i < inverts;i++)
        {
-               VectorCopy(v[i].v, out[i].v);
+               if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
+                       continue;
                temp[0] = v[i].v[0] * scale[0] + translate[0];
                temp[1] = v[i].v[1] * scale[1] + translate[1];
                temp[2] = v[i].v[2] * scale[2] + translate[2];
@@ -70,62 +77,23 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
                if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
                if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
                if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
-               out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
-               out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
-               out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
-       }               
-       /*
-       int i, j;
-       vec3_t t1, t2;
-       struct
-       {
-               vec3_t v;
-               vec3_t normal;
-               int count;
-       } tempvert[MD2MAX_VERTS];
-       temptris_t *tris;
-       // decompress vertices
-       for (i = 0;i < numverts;i++)
-       {
-               VectorCopy(v[i].v, out[i].v);
-               tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0];
-               tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1];
-               tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2];
-               tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0;
-               tempvert[i].count = 0;
-               // update bounding box
-               if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0];
-               if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1];
-               if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2];
-               if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0];
-               if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1];
-               if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2];
-       }
-       // calculate surface normals
-       tris = temptris;
-       for (i = 0;i < numtris;i++)
-       {
-               VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1);
-               VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2);
-               CrossProduct(t1, t2, tris->normal);
-               VectorNormalize(tris->normal);
-               // add surface normal to vertices
-               for (j = 0;j < 3;j++)
+               j = vertremap[i]; // not onseam
+               if (j >= 0)
                {
-                       VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
-                       tempvert[tris->v[j]].count++;
+                       VectorCopy(v[i].v, out[j].v);
+                       out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+                       out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+                       out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+               }
+               j = vertremap[i+inverts]; // onseam
+               if (j >= 0)
+               {
+                       VectorCopy(v[i].v, out[j].v);
+                       out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+                       out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+                       out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
                }
-               tris++;
-       }
-       // average normals and write out 1.7bit format
-       for (i = 0;i < pheader->numtris;i++)
-       {
-               VectorNormalize(tempvert[i].normal);
-               out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0);
-               out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0);
-               out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0);
        }
-       */
 }
 
 /*
@@ -133,35 +101,25 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
 Mod_LoadAliasFrame
 =================
 */
-void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
+void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
 {
        trivertx_t              *pinframe;
-       int                             i;
        daliasframe_t   *pdaliasframe;
        
        pdaliasframe = (daliasframe_t *)pin;
 
-       strcpy (frame->name, pdaliasframe->name);
-       frame->firstpose = posenum;
-       frame->numposes = 1;
-
-       for (i=0 ; i<3 ; i++)
-       {
-       // these are byte values, so we don't have to worry about
-       // endianness
-               frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
-               frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i]; // LordHavoc: was setting bboxmin a second time (bug)
-       }
+       strcpy(frame->name, pdaliasframe->name);
+       frame->start = posenum;
+       frame->length = 1;
+       frame->rate = 10.0f; // unnecessary but...
 
        pinframe = (trivertx_t *)(pdaliasframe + 1);
 
-//     poseverts[posenum] = pinframe;
-       Mod_ConvertAliasVerts(pheader->numverts, pheader->numtris, pheader->scale, pheader->scale_origin, pinframe, (void *)((int) pheader + pheader->posedata + sizeof(trivert2) * pheader->numverts * posenum));
-//     // LordHavoc: copy the frame data
-//     memcpy((void *)((int) pheader + pheader->posedata + sizeof(trivertx_t) * pheader->numverts * posenum), pinframe, sizeof(trivertx_t) * pheader->numverts);
+       Mod_ConvertAliasVerts(inverts, mheader->scale, mheader->scale_origin, pinframe, *posevert);
+       *posevert += outverts;
        posenum++;
 
-       pinframe += pheader->numverts;
+       pinframe += inverts;
 
        return (void *)pinframe;
 }
@@ -172,44 +130,31 @@ void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
 Mod_LoadAliasGroup
 =================
 */
-void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
+void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
 {
-       daliasgroup_t           *pingroup;
-       int                                     i, numframes;
-       daliasinterval_t        *pin_intervals;
-       void                            *ptemp;
+       int             i, numframes;
+       void    *ptemp;
+       float   interval;
        
-       pingroup = (daliasgroup_t *)pin;
-
-       numframes = LittleLong (pingroup->numframes);
-
-       frame->firstpose = posenum;
-       frame->numposes = numframes;
-
-       for (i=0 ; i<3 ; i++)
-       {
-       // these are byte values, so we don't have to worry about endianness
-               frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
-               frame->bboxmax.v[i] = pingroup->bboxmax.v[i]; // LordHavoc: was setting bboxmin a second time (bug)
-       }
-
-       pin_intervals = (daliasinterval_t *)(pingroup + 1);
+       numframes = LittleLong (((daliasgroup_t *)pin)->numframes);
 
-       frame->interval = LittleFloat (pin_intervals->interval);
+       strcpy(frame->name, "group");
+       frame->start = posenum;
+       frame->length = numframes;
+       interval = LittleFloat (((daliasinterval_t *)(((daliasgroup_t *)pin) + 1))->interval); // FIXME: support variable framerate groups?
+       if (interval < 0.01f)
+               Host_Error("Mod_LoadAliasGroup: invalid interval");
+       frame->rate = 1.0f / interval;
 
-       pin_intervals += numframes;
-
-       ptemp = (void *)pin_intervals;
+       ptemp = (void *)(((daliasinterval_t *)(((daliasgroup_t *)pin) + 1)) + numframes);
 
        for (i=0 ; i<numframes ; i++)
        {
-//             poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
-               Mod_ConvertAliasVerts(pheader->numverts, pheader->numtris, pheader->scale, pheader->scale_origin, (void *)((daliasframe_t *)ptemp + 1), (void *)((int) pheader + pheader->posedata + sizeof(trivert2) * pheader->numverts * posenum));
-//             // LordHavoc: copy the frame data
-//             memcpy((void *)((int) pheader + pheader->posedata + sizeof(trivertx_t) * pheader->numverts * posenum), (void *)((daliasframe_t *)ptemp + 1), sizeof(trivertx_t) * pheader->numverts);
+               ((daliasframe_t *)ptemp)++;
+               Mod_ConvertAliasVerts(inverts, mheader->scale, mheader->scale_origin, ptemp, *posevert);
+               *posevert += outverts;
                posenum++;
-
-               ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
+               ptemp = (trivertx_t *)ptemp + inverts;
        }
 
        return ptemp;
@@ -293,84 +238,179 @@ void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
        }
 }
 
+int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+{
+       int i, pixels, passed;
+       byte pixeltest[16];
+       for (i = 0;i < 16;i++)
+               pixeltest[i] = (bits & (1 << i)) != 0;
+       pixels = width*height;
+       passed = 0;
+       while(pixels--)
+       {
+               if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
+               {
+                       passed++;
+                       // turn to white while copying
+                       if (*in >= 128 && *in < 224) // backwards ranges
+                               *out = (*in & 15) ^ 15;
+                       else
+                               *out = *in & 15;
+               }
+               else
+                       *out = 0;
+               in++;
+               out++;
+       }
+       if (passed)
+               return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+       else
+               return 0;
+}
+
+int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+{
+       int i, pixels, passed;
+       byte pixeltest[16];
+       for (i = 0;i < 16;i++)
+               pixeltest[i] = (bits & (1 << i)) != 0;
+       pixels = width*height;
+       passed = 0;
+       while(pixels--)
+       {
+               if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
+               {
+                       passed++;
+                       *out = *in;
+               }
+               else
+                       *out = 0;
+               in++;
+               out++;
+       }
+       if (passed)
+               return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+       else
+               return 0;
+}
+
 /*
 ===============
 Mod_LoadAllSkins
 ===============
 */
-void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int bytesperpixel)
+void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int width, int height)
 {
-       int             i, j, k;
+       int             i, j;
        char    name[32];
        int             s;
        byte    *skin;
-       byte    *texels;
        daliasskingroup_t               *pinskingroup;
        int             groupskins;
        daliasskininterval_t    *pinskinintervals;
+       int             skinranges, skincount, *skintexnum, *skinrange, skinnum;
+       void    *temp;
+       byte    *skintemp = NULL;
        
        skin = (byte *)(pskintype + 1);
 
        if (numskins < 1 || numskins > MAX_SKINS)
                Host_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
 
-       s = pheader->skinwidth * pheader->skinheight;
+       s = width * height;
+       skintemp = malloc(s);
 
+       // LordHavoc: skim the data, measure the number of skins and number of groups
+       skinranges = numskins;
+       skincount = 0;
+       temp = pskintype;
+       for (i = 0;i < numskins;i++)
+       {
+               pskintype++;
+               if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
+               {
+                       skincount++;
+                       (byte *)pskintype += s;
+               }
+               else
+               {
+                       groupskins = LittleLong (((daliasskingroup_t *)pskintype)->numskins);
+                       skincount += groupskins;
+                       (byte *)pskintype += (s + sizeof(daliasskininterval_t)) * groupskins + sizeof(daliasskingroup_t);
+               }
+       }
+       pskintype = temp;
+
+       skinrange = loadmodel->skinanimrange;
+       skintexnum = loadmodel->skinanim;
+//     skinrange = Hunk_AllocName (sizeof(int) * (skinranges + skincount), loadname);  
+//     skintexnum = skinrange + skinranges * 2;
+//     loadmodel->skinanimrange = (int) skinrange - (int) pheader;
+//     loadmodel->skinanim = (int) skintexnum - (int) pheader;
+       skinnum = 0;
        for (i = 0;i < numskins;i++)
        {
-               if (pskintype->type == ALIAS_SKIN_SINGLE)
+               *skinrange++ = skinnum; // start of the range
+               pskintype++;
+               if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
                {
-                       if (bytesperpixel == 1)
-                               Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
-
-                       // save 8 bit texels for the player model to remap
-       //              if (!strcmp(loadmodel->name,"progs/player.mdl")) {
-                               texels = Hunk_AllocName(s, loadname);
-                               pheader->texels[i] = texels - (byte *)pheader;
-                               memcpy (texels, (byte *)(pskintype + 1), s);
-       //              }
+                       *skinrange++ = 1; // single skin
+                       skinnum++;
                        sprintf (name, "%s_%i", loadmodel->name, i);
-                       pheader->gl_texturenum[i][0] =
-                       pheader->gl_texturenum[i][1] =
-                       pheader->gl_texturenum[i][2] =
-                       pheader->gl_texturenum[i][3] =
-                               GL_LoadTexture (name, pheader->skinwidth, pheader->skinheight, (byte *)(pskintype + 1), true, false, bytesperpixel);
-                       pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
+
+                       Mod_FloodFillSkin( skin, width, height );
+                       *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FBD, va("%s_normal", name)); // normal (no special colors)
+                       *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0040, va("%s_pants",  name)); // pants
+                       *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0002, va("%s_shirt",  name)); // shirt
+                       *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow",   name)); // glow
+                       *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body",   name)); // body (normal + pants + shirt, but not glow)
+                       pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                }
                else
                {
                        // animating skin group.  yuck.
-                       pskintype++;
                        pinskingroup = (daliasskingroup_t *)pskintype;
                        groupskins = LittleLong (pinskingroup->numskins);
                        pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
 
                        pskintype = (void *)(pinskinintervals + groupskins);
 
+                       *skinrange++ = groupskins; // number of skins
+                       skinnum += groupskins;
                        for (j = 0;j < groupskins;j++)
                        {
-                                       if (bytesperpixel == 1)
-                                               Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
-                                       if (j == 0)
-                                       {
-                                               texels = Hunk_AllocName(s, loadname);
-                                               pheader->texels[i] = texels - (byte *)pheader;
-                                               memcpy (texels, (byte *)(pskintype), s);
-                                       }
-                                       sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
-                                       pheader->gl_texturenum[i][j&3] = 
-                                               GL_LoadTexture (name, pheader->skinwidth, pheader->skinheight, (byte *)(pskintype), true, false, bytesperpixel);
-                                       pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
+                               sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
+
+                               Mod_FloodFillSkin( skin, width, height );
+                               *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FBD, va("%s_normal", name)); // normal (no special colors)
+                               *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0040, va("%s_pants",  name)); // pants
+                               *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0002, va("%s_shirt",  name)); // shirt
+                               *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow",   name)); // glow
+                               *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body",   name)); // body (normal + pants + shirt, but not glow)
+                               pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                        }
-                       k = j;
-                       for (;j < 4;j++)
-                               pheader->gl_texturenum[i][j&3] = pheader->gl_texturenum[i][j - k]; 
                }
        }
+       loadmodel->numskins = numskins;
+       free(skintemp);
 
        return (void *)pskintype;
 }
 
+void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
+{
+       int             i;
+       for (i = 0;i < numskins;i++)
+       {
+               pskintype++;
+               if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
+                       (byte *)pskintype += skinsize;
+               else
+                       (byte *)pskintype += (skinsize + sizeof(daliasskininterval_t)) * LittleLong (((daliasskingroup_t *)pskintype)->numskins) + sizeof(daliasskingroup_t);
+       }
+       return pskintype;
+}
+
 //=========================================================================
 
 //void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr);
@@ -384,164 +424,164 @@ Mod_LoadAliasModel
 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX);
 void Mod_LoadAliasModel (model_t *mod, void *buffer)
 {
-       int                                     i, j, version, numframes, size, start, end, total;
+       int                                     i, j, version, numframes, start, end, total, numverts, numtris, numposes, numskins, skinwidth, skinheight, f, totalverts;
        mdl_t                           *pinmodel;
        stvert_t                        *pinstverts;
        dtriangle_t                     *pintriangles;
        daliasframetype_t       *pframetype;
        daliasskintype_t        *pskintype;
-       // LordHavoc: 32bit textures
-       int                                     bytesperpixel;
-       unsigned short          *poutvertindices;
        float                           *pouttexcoords, scales, scalet;
-       temptris_t                      *tris;
+       maliashdr_t                     *mheader;
+       unsigned short          *pouttris;
+       maliasframe_t           *frame;
+       trivert2                        *posevert;
 
        start = Hunk_LowMark ();
 
-       if (!temptris)
-               temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
-
        pinmodel = (mdl_t *)buffer;
 
        version = LittleLong (pinmodel->version);
-       if (version != ALIAS_VERSION && version != ALIAS32_VERSION)
-               Host_Error ("%s has wrong version number (%i should be %i or %i)",
-                                mod->name, version, ALIAS_VERSION, ALIAS32_VERSION);
+       if (version != ALIAS_VERSION)
+               Host_Error ("%s has wrong version number (%i should be %i)",
+                                mod->name, version, ALIAS_VERSION);
 
        mod->type = ALIASTYPE_MDL;
 
-//
-// allocate space for a working header, plus all the data except the frames,
-// skin and group info
-//
-//     size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * sizeof (pinmodel->frames[0]));
-       size = sizeof (aliashdr_t);
-       size += LittleLong (pinmodel->numverts) * sizeof(float[2][2]);
-       size += LittleLong (pinmodel->numtris) * sizeof(unsigned short[3]);
-       size += LittleLong (pinmodel->numframes) * (sizeof(trivert2) * LittleLong (pinmodel->numverts) + sizeof(maliasframedesc_t));
-       BOUNDI(size,256,4194304);
-       pheader = Hunk_AllocName (size, loadname);
+       numframes = LittleLong(pinmodel->numframes);
+       BOUNDI(numframes,0,65536);
+       numverts = LittleLong(pinmodel->numverts);
+       BOUNDI(numverts,0,MAXALIASVERTS);
+       numtris = LittleLong(pinmodel->numtris);
+       BOUNDI(numtris,0,65536);
+       numskins = LittleLong(pinmodel->numskins);
+       BOUNDI(numskins,0,256);
+       skinwidth = LittleLong (pinmodel->skinwidth);
+       BOUNDI(skinwidth,0,4096);
+       skinheight = LittleLong (pinmodel->skinheight);
+       BOUNDI(skinheight,0,1024);
        
+       pskintype = (daliasskintype_t *)&pinmodel[1];
+       pinstverts = (stvert_t *)Mod_SkipAllSkins (numskins, pskintype, skinwidth * skinheight);
+       pintriangles = (dtriangle_t *)&pinstverts[numverts];
+       pframetype = (daliasframetype_t *)&pintriangles[numtris];
+
+       numposes = 0;
+       for (i=0 ; i<numframes ; i++)
+       {
+               if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE)
+               {
+                       numposes++;
+                       pframetype = (daliasframetype_t *)((int)pframetype + sizeof(daliasframetype_t)                         + (sizeof(daliasframe_t)                            + sizeof(trivertx_t) * numverts)    );
+               }
+               else
+               {
+                       f = LittleLong (((daliasgroup_t *)((int)pframetype + sizeof(daliasframetype_t)))->numframes);
+                       numposes += f;
+                       pframetype = (daliasframetype_t *)((int)pframetype + sizeof(daliasframetype_t) + sizeof(daliasgroup_t) + (sizeof(daliasframe_t) + sizeof(daliasinterval_t) + sizeof(trivertx_t) * numverts) * f);
+               }
+       }
+
+       // rebuild the model
+       mheader = Hunk_AllocName (sizeof(maliashdr_t), loadname);
        mod->flags = LittleLong (pinmodel->flags);
        mod->type = mod_alias;
-
 // endian-adjust and copy the data, starting with the alias model header
-       pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
-       BOUNDF(pheader->boundingradius,0,65536);
-       pheader->numskins = LittleLong (pinmodel->numskins);
-       BOUNDI(pheader->numskins,0,256);
-       pheader->skinwidth = LittleLong (pinmodel->skinwidth);
-       BOUNDI(pheader->skinwidth,0,4096);
-       pheader->skinheight = LittleLong (pinmodel->skinheight);
-       BOUNDI(pheader->skinheight,0,1024);
-//LordHavoc: 32bit textures
-       bytesperpixel = version == ALIAS32_VERSION ? 4 : 1;
-
-//     if (pheader->skinheight > MAX_LBM_HEIGHT)
-//             Host_Error ("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT);
-
-       pheader->numverts = LittleLong (pinmodel->numverts);
-       BOUNDI(pheader->numverts,0,MAXALIASVERTS);
-       /*
-       if (pheader->numverts <= 0)
-               Host_Error ("model %s has no vertices", mod->name);
-       if (pheader->numverts > MAXALIASVERTS)
-               Host_Error ("model %s has too many vertices", mod->name);
-       */
-
-       pheader->numtris = LittleLong (pinmodel->numtris);
-       BOUNDI(pheader->numtris,0,65536);
-//     if (pheader->numtris <= 0)
-//             Host_Error ("model %s has no triangles", mod->name);
-
-       pheader->numframes = LittleLong (pinmodel->numframes);
-       BOUNDI(pheader->numframes,0,65536);
-       numframes = pheader->numframes;
-//     if (numframes < 1)
-//             Host_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
-
-       pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
-       BOUNDF(pheader->size,0,65536);
+       mheader->numverts = numverts;
+       mod->numtris = mheader->numtris = numtris;
+       mod->numframes = mheader->numframes = numframes;
        mod->synctype = LittleLong (pinmodel->synctype);
-       BOUNDI(pheader->synctype,0,2);
-       mod->numframes = pheader->numframes;
+       BOUNDI(mod->synctype,0,2);
 
        for (i=0 ; i<3 ; i++)
        {
-               pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
-               BOUNDF(pheader->scale[i],0,65536);
-               pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
-               BOUNDF(pheader->scale_origin[i],-65536,65536);
-               pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
-               BOUNDF(pheader->eyeposition[i],-65536,65536);
+               mheader->scale[i] = LittleFloat (pinmodel->scale[i]);
+               BOUNDF(mheader->scale[i],0,65536);
+               mheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
+               BOUNDF(mheader->scale_origin[i],-65536,65536);
        }
 
-// load the skins
+       // load the skins
        pskintype = (daliasskintype_t *)&pinmodel[1];
-       pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype, bytesperpixel);
+       pskintype = Mod_LoadAllSkins(numskins, pskintype, skinwidth, skinheight);
 
-// load base s and t vertices
+       // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data)
        pinstverts = (stvert_t *)pskintype;
-       pouttexcoords = (float *)&pheader->frames[numframes];
-       pheader->texcoords = (int) pouttexcoords - (int) pheader;
 
        // LordHavoc: byteswap and convert stvert data
-       scales = 1.0 / pheader->skinwidth;
-       scalet = 1.0 / pheader->skinheight;
-       for (i = 0;i < pheader->numverts;i++)
+       scales = 1.0 / skinwidth;
+       scalet = 1.0 / skinheight;
+       for (i = 0;i < numverts;i++)
        {
-               pouttexcoords[i*2] = LittleLong (pinstverts[i].s) * scales;
-               pouttexcoords[i*2+1] = LittleLong (pinstverts[i].t) * scalet;
-               pouttexcoords[(i+pheader->numverts)*2] = LittleLong (pinstverts[i].s) * scales + 0.5;
-               pouttexcoords[(i+pheader->numverts)*2+1] = LittleLong (pinstverts[i].t) * scalet;
-               if (pouttexcoords[i*2] >= 0.5) // already a back side coordinate
-               {
-                       pouttexcoords[i*2] -= 0.5;
-                       pouttexcoords[(i+pheader->numverts)*2] -= 0.5;
-               }
-               // LordHavoc: CTF's v_star.mdl failed these checks
-//             BOUNDF(pouttexcoords[i*2],0.0,1.0);
-//             BOUNDF(pouttexcoords[i*2+1],0.0,1.0);
-//             BOUNDF(pouttexcoords[(i+pheader->numverts)*2],0.0,1.0);
-//             BOUNDF(pouttexcoords[(i+pheader->numverts)*2+1],0.0,1.0);
+               vertonseam[i] = LittleLong(pinstverts[i].onseam);
+               vertst[i][0] = LittleLong(pinstverts[i].s) * scales;
+               vertst[i][1] = LittleLong(pinstverts[i].t) * scalet;
+               vertst[i+numverts][0] = vertst[i][0] + 0.5;
+               vertst[i+numverts][1] = vertst[i][1];
+               vertusage[i] = 0;
+               vertusage[i+numverts] = 0;
        }
 
 // load triangle data
-       pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
-       poutvertindices = (unsigned short *)&pouttexcoords[pheader->numverts*4];
-       pheader->vertindices = (int) poutvertindices - (int) pheader;
-       // LordHavoc: sort triangles into front and back lists
-       // so they can be drawn refering to different texture coordinate arrays,
-       // but sharing vertex data
-       pheader->frontfaces = 0;
-       pheader->backfaces = 0;
-       tris = temptris;
-       for (i=0 ; i<pheader->numtris ; i++)
+       pouttris = Hunk_AllocName(sizeof(unsigned short[3]) * numtris, loadname);
+       mheader->tridata = (int) pouttris - (int) mheader;
+       pintriangles = (dtriangle_t *)&pinstverts[mheader->numverts];
+
+       // count the vertices used
+       for (i = 0;i < numverts*2;i++)
+               vertusage[i] = 0;
+       for (i = 0;i < numtris;i++)
        {
-               if (LittleLong(pintriangles[i].facesfront))
+               temptris[i][0] = LittleLong(pintriangles[i].vertindex[0]);
+               temptris[i][1] = LittleLong(pintriangles[i].vertindex[1]);
+               temptris[i][2] = LittleLong(pintriangles[i].vertindex[2]);
+               if (!LittleLong(pintriangles[i].facesfront)) // backface
                {
-                       pheader->frontfaces++;
-                       for (j=0 ; j<3 ; j++)
-                               *poutvertindices++ = LittleLong (pintriangles[i].vertindex[j]);
+                       if (vertonseam[temptris[i][0]]) temptris[i][0] += numverts;
+                       if (vertonseam[temptris[i][1]]) temptris[i][1] += numverts;
+                       if (vertonseam[temptris[i][2]]) temptris[i][2] += numverts;
                }
-               for (j=0 ; j<3 ; j++)
-                       tris->v[j] = LittleLong (pintriangles[i].vertindex[j]);
-               tris++;
+               vertusage[temptris[i][0]]++;
+               vertusage[temptris[i][1]]++;
+               vertusage[temptris[i][2]]++;
        }
-       for (i=0 ; i<pheader->numtris ; i++)
+       // build remapping table and compact array
+       totalverts = 0;
+       for (i = 0;i < numverts*2;i++)
        {
-               if (!LittleLong(pintriangles[i].facesfront))
+               if (vertusage[i])
                {
-                       pheader->backfaces++;
-                       for (j=0 ; j<3 ; j++)
-                               *poutvertindices++ = LittleLong (pintriangles[i].vertindex[j]);
+                       vertremap[i] = totalverts;
+                       vertst[totalverts][0] = vertst[i][0];
+                       vertst[totalverts][1] = vertst[i][1];
+                       totalverts++;
                }
+               else
+                       vertremap[i] = -1; // not used at all
+       }
+       mheader->numverts = totalverts;
+       // remap the triangle references
+       for (i = 0;i < numtris;i++)
+       {
+               *pouttris++ = vertremap[temptris[i][0]];
+               *pouttris++ = vertremap[temptris[i][1]];
+               *pouttris++ = vertremap[temptris[i][2]];
+       }
+       // store the texture coordinates
+       pouttexcoords = Hunk_AllocName(sizeof(float[2]) * totalverts, loadname);
+       mheader->texdata = (int) pouttexcoords - (int) mheader;
+       for (i = 0;i < totalverts;i++)
+       {
+               *pouttexcoords++ = vertst[i][0];
+               *pouttexcoords++ = vertst[i][1];
        }
 
 // load the frames
        posenum = 0;
-       pheader->posedata = (int) poutvertindices - (int) pheader;
-       pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
+       frame = Hunk_AllocName(sizeof(maliasframe_t) * numframes, loadname);
+       mheader->framedata = (int) frame - (int) mheader;
+       posevert = Hunk_AllocName(sizeof(trivert2) * numposes * totalverts, loadname);
+       mheader->posedata = (int) posevert - (int) mheader;
+       pframetype = (daliasframetype_t *)&pintriangles[numtris];
 
        // LordHavoc: doing proper bbox for model
        aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000;
@@ -549,18 +589,12 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
 
        for (i=0 ; i<numframes ; i++)
        {
-               aliasframetype_t        frametype;
-
-               frametype = LittleLong (pframetype->type);
-
-               if (frametype == ALIAS_SINGLE)
-                       pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
+               if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE)
+                       pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
                else
-                       pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
+                       pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
        }
 
-       pheader->numposes = posenum;
-
        // LordHavoc: fixed model bbox - was //FIXME: do this right
        //mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
        //mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
@@ -577,17 +611,91 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        Cache_Alloc (&mod->cache, total, loadname);
        if (!mod->cache.data)
                return;
-       memcpy (mod->cache.data, pheader, total);
+       memcpy (mod->cache.data, mheader, total);
 
        Hunk_FreeToLowMark (start);
 }
 
+void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
+{
+       int i;
+       vec3_t temp;
+       for (i = 0;i < numverts;i++)
+       {
+               VectorCopy(v[i].v, out[i].v);
+               temp[0] = v[i].v[0] * scale[0] + translate[0];
+               temp[1] = v[i].v[1] * scale[1] + translate[1];
+               temp[2] = v[i].v[2] * scale[2] + translate[2];
+               // update bounding box
+               if (temp[0] < aliasbboxmin[0]) aliasbboxmin[0] = temp[0];
+               if (temp[1] < aliasbboxmin[1]) aliasbboxmin[1] = temp[1];
+               if (temp[2] < aliasbboxmin[2]) aliasbboxmin[2] = temp[2];
+               if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
+               if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
+               if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+               out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+               out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+               out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+       }               
+       /*
+       int i, j;
+       vec3_t t1, t2;
+       struct
+       {
+               vec3_t v;
+               vec3_t normal;
+               int count;
+       } tempvert[MD2MAX_VERTS];
+       temptris_t *tris;
+       // decompress vertices
+       for (i = 0;i < numverts;i++)
+       {
+               VectorCopy(v[i].v, out[i].v);
+               tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0];
+               tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1];
+               tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2];
+               tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0;
+               tempvert[i].count = 0;
+               // update bounding box
+               if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0];
+               if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1];
+               if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2];
+               if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0];
+               if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1];
+               if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2];
+       }
+       // calculate surface normals
+       tris = temptris;
+       for (i = 0;i < numtris;i++)
+       {
+               VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1);
+               VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2);
+               CrossProduct(t1, t2, tris->normal);
+               VectorNormalize(tris->normal);
+               // add surface normal to vertices
+               for (j = 0;j < 3;j++)
+               {
+                       VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
+                       tempvert[tris->v[j]].count++;
+               }
+               tris++;
+       }
+       // average normals and write out 1.7bit format
+       for (i = 0;i < pheader->numtris;i++)
+       {
+               VectorNormalize(tempvert[i].normal);
+               out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0);
+               out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0);
+               out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0);
+       }
+       */
+}
+
 /*
 =================
 Mod_LoadQ2AliasModel
 =================
 */
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight);
 void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 {
        int                                     i, j, version, size, *pinglcmd, *poutglcmd, start, end, total, framesize;
@@ -597,12 +705,12 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        md2frame_t                      *pinframe;
        md2memframe_t           *poutframe;
        char                            *pinskins;
-       temptris_t                      *tris;
+//     temptris_t                      *tris;
 
        start = Hunk_LowMark ();
 
-       if (!temptris)
-               temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
+//     if (!temptris)
+//             temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
 
        pinmodel = (md2_t *)buffer;
 
@@ -628,6 +736,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        mod->flags = 0; // there are no MD2 flags
        mod->numframes = LittleLong(pinmodel->num_frames);
        mod->synctype = ST_RAND;
+       mod->numtris = LittleLong(pinmodel->num_tris); // LordHavoc: to simplify renderer decisions
 
        if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= LittleLong(pinmodel->ofs_end)))
                Host_Error ("%s is not a valid model", mod->name);
@@ -644,7 +753,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                Host_Error ("%s has invalid number of triangles: %i", mod->name, LittleLong(pinmodel->num_tris));
        if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > MD2MAX_VERTS)
                Host_Error ("%s has invalid number of vertices: %i", mod->name, LittleLong(pinmodel->num_xyz));
-       if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > 256) //MD2MAX_FRAMES)
+       if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES)
                Host_Error ("%s has invalid number of frames: %i", mod->name, LittleLong(pinmodel->num_frames));
        if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MD2MAX_SKINS)
                Host_Error ("%s has invalid number of skins: %i", mod->name, LittleLong(pinmodel->num_skins));
@@ -660,25 +769,39 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 // load the skins
        if (pheader->num_skins)
        {
+               int *skin, *skinrange;
+               skinrange = loadmodel->skinanimrange;
+               skin = loadmodel->skinanim;
+//             skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);  
+//             skin = skinrange + pheader->num_skins * 2;
+//             loadmodel->skinanimrange = (int) skinrange - (int) pheader;
+//             loadmodel->skinanim = (int) skin - (int) pheader;
                pinskins = (void*)((int) pinmodel + LittleLong(pinmodel->ofs_skins));
                for (i = 0;i < pheader->num_skins;i++)
                {
-                       pheader->gl_texturenum[i] = loadtextureimage (-1, pinskins, TRUE, 0, 0);
+                       *skinrange++ = i;
+                       *skinrange++ = 1;
+                       *skin++ = loadtextureimage (pinskins, 0, 0, true, true);
+                       *skin++ = 0; // the extra 4 layers are currently unused
+                       *skin++ = 0;
+                       *skin++ = 0;
+                       *skin++ = 0;
                        pinskins += MD2MAX_SKINNAME;
                }
        }
+       loadmodel->numskins = pheader->num_skins;
 
 // load triangles
        pintriangles = (void*)((int) pinmodel + LittleLong(pinmodel->ofs_tris));
        pouttriangles = (void*)&pheader[1];
        pheader->ofs_tris = (int) pouttriangles - (int) pheader;
-       tris = temptris;
+//     tris = temptris;
        // swap the triangle list
        for (i=0 ; i<pheader->num_tris ; i++)
        {
                for (j=0 ; j<3 ; j++)
                {
-                       tris->v[j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]);
+                       temptris[i][j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]);
                        pouttriangles->index_st[j] = LittleShort (pintriangles->index_st[j]);
                        if (pouttriangles->index_xyz[j] >= pheader->num_xyz)
                                Host_Error ("%s has invalid vertex indices", mod->name);
@@ -687,7 +810,6 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                }
                pintriangles++;
                pouttriangles++;
-               tris++;
        }
 
        // LordHavoc: doing proper bbox for model
@@ -705,7 +827,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                        poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
                        poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
                }
-               Mod_ConvertAliasVerts (pheader->num_xyz, pheader->num_tris, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]);
+               Mod_ConvertQ2AliasVerts (pheader->num_xyz, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]);
                pinframe = (void*) &pinframe->verts[j];
                poutframe = (void*) &poutframe->verts[j];
        }
index a00d41e1036b0393c661489772f85fba11fa363e..aafcb33d4578e9e77865ca7a7d9fe8dd7c3a1ee3 100644 (file)
@@ -29,6 +29,7 @@ Alias models are position independent, so the cache manager can move them.
 
 #include "modelgen.h"
 
+/*
 typedef struct
 {
        int                                     firstpose;
@@ -54,11 +55,11 @@ typedef struct
        maliasgroupframedesc_t  frames[1];
 } maliasgroup_t;
 
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
 typedef struct mtriangle_s {
        int                                     facesfront;
        int                                     vertindex[3];
 } mtriangle_t;
+*/
 
 // LordHavoc: new vertex format
 typedef struct {
@@ -83,30 +84,34 @@ typedef struct {
        synctype_t      synctype;
        int                     flags;
        float           size;
+} daliashdr_t;
 
-       int                                     numposes;
-       int                                     posedata;       // LordHavoc: numposes*numverts*trivert2
-       int                                     frontfaces; // LordHavoc: how many front faces
-       int                                     backfaces; // LordHavoc: how many back faces
-//     int                                     poseverts;
-//     int                                     posedata;       // numposes*poseverts trivert_t
-//     int                                     commands;       // gl command list with embedded s/t
-       int                                     texcoords;      // LordHavoc: texture coordinates
-       int                                     vertindices;    // LordHavoc: vertex numbers
-       int                                     gl_texturenum[MAX_SKINS][4];
-       int                                     texels[MAX_SKINS];      // only for player skins
-       maliasframedesc_t       frames[1];      // variable sized
-} aliashdr_t;
+typedef struct
+{
+       char name[16]; // LordHavoc: only kept this for reasons of viewthing support
+       unsigned short start;
+       unsigned short length;
+       float rate; // in poses per second
+} maliasframe_t;
+
+typedef struct
+{
+       vec3_t          scale;
+       vec3_t          scale_origin;
+       int                     numverts;
+       int                     numtris;
+       int                     numframes;
+       int                     numposes;
+       int                     framedata; // LordHavoc: unsigned short start
+       int                     texdata; // LordHavoc: texture coordinate array
+       int                     posedata; // LordHavoc: vertex data for all the poses
+       int                     tridata; // LordHavoc: vertex indices for the triangles
+} maliashdr_t;
 
 #define        MAXALIASVERTS   4096
 #define        MAXALIASFRAMES  1024
 #define        MAXALIASTRIS    4096
 
-extern aliashdr_t      *pheader;
-//extern       stvert_t        stverts[MAXALIASVERTS];
-//extern       mtriangle_t     triangles[MAXALIASTRIS];
-//extern       trivertx_t      *poseverts[MAXALIASFRAMES];
-
 /*
 ========================================================================
 
@@ -146,7 +151,7 @@ typedef struct
        float           scale[3];       // multiply byte verts by this
        float           translate[3];   // then add this
        char            name[16];       // frame name from grabbing
-       trivertx_t      verts[0];       // variable sized
+       trivertx_t      verts[];        // variable sized
 } md2frame_t;
 
 // LordHavoc: memory representation is different than disk
@@ -154,7 +159,7 @@ typedef struct
 {
        float           scale[3];       // multiply byte verts by this
        float           translate[3];   // then add this
-       trivert2        verts[0];       // variable sized
+       trivert2        verts[];        // variable sized
 } md2memframe_t;
 
 
@@ -205,8 +210,6 @@ typedef struct
        int                     ofs_tris;               // offset for dtriangles
        int                     ofs_frames;             // offset for first frame
        int                     ofs_glcmds;     
-
-       int                     gl_texturenum[MAX_SKINS];
 } md2mem_t;
 
 #define ALIASTYPE_MDL 1
index 03f9dc924accca934e7dac81a0d1701a7a66f711..913e9b3d6a1053a72cd6b0c8bd384558961f0b91 100644 (file)
@@ -867,29 +867,70 @@ void Mod_LoadClipnodes (lump_t *l)
        loadmodel->clipnodes = out;
        loadmodel->numclipnodes = count;
 
-       hull = &loadmodel->hulls[1];
-       hull->clipnodes = out;
-       hull->firstclipnode = 0;
-       hull->lastclipnode = count-1;
-       hull->planes = loadmodel->planes;
-       hull->clip_mins[0] = -16;
-       hull->clip_mins[1] = -16;
-       hull->clip_mins[2] = -24;
-       hull->clip_maxs[0] = 16;
-       hull->clip_maxs[1] = 16;
-       hull->clip_maxs[2] = 32;
-
-       hull = &loadmodel->hulls[2];
-       hull->clipnodes = out;
-       hull->firstclipnode = 0;
-       hull->lastclipnode = count-1;
-       hull->planes = loadmodel->planes;
-       hull->clip_mins[0] = -32;
-       hull->clip_mins[1] = -32;
-       hull->clip_mins[2] = -24;
-       hull->clip_maxs[0] = 32;
-       hull->clip_maxs[1] = 32;
-       hull->clip_maxs[2] = 64;
+       if (hlbsp)
+       {
+               hull = &loadmodel->hulls[1];
+               hull->clipnodes = out;
+               hull->firstclipnode = 0;
+               hull->lastclipnode = count-1;
+               hull->planes = loadmodel->planes;
+               hull->clip_mins[0] = -16;
+               hull->clip_mins[1] = -16;
+               hull->clip_mins[2] = -36;
+               hull->clip_maxs[0] = 16;
+               hull->clip_maxs[1] = 16;
+               hull->clip_maxs[2] = 36;
+
+               hull = &loadmodel->hulls[2];
+               hull->clipnodes = out;
+               hull->firstclipnode = 0;
+               hull->lastclipnode = count-1;
+               hull->planes = loadmodel->planes;
+               hull->clip_mins[0] = -32;
+               hull->clip_mins[1] = -32;
+               hull->clip_mins[2] = -32;
+               hull->clip_maxs[0] = 32;
+               hull->clip_maxs[1] = 32;
+               hull->clip_maxs[2] = 32;
+
+               hull = &loadmodel->hulls[3];
+               hull->clipnodes = out;
+               hull->firstclipnode = 0;
+               hull->lastclipnode = count-1;
+               hull->planes = loadmodel->planes;
+               hull->clip_mins[0] = -16;
+               hull->clip_mins[1] = -16;
+               hull->clip_mins[2] = -18;
+               hull->clip_maxs[0] = 16;
+               hull->clip_maxs[1] = 16;
+               hull->clip_maxs[2] = 18;
+       }
+       else
+       {
+               hull = &loadmodel->hulls[1];
+               hull->clipnodes = out;
+               hull->firstclipnode = 0;
+               hull->lastclipnode = count-1;
+               hull->planes = loadmodel->planes;
+               hull->clip_mins[0] = -16;
+               hull->clip_mins[1] = -16;
+               hull->clip_mins[2] = -24;
+               hull->clip_maxs[0] = 16;
+               hull->clip_maxs[1] = 16;
+               hull->clip_maxs[2] = 32;
+
+               hull = &loadmodel->hulls[2];
+               hull->clipnodes = out;
+               hull->firstclipnode = 0;
+               hull->lastclipnode = count-1;
+               hull->planes = loadmodel->planes;
+               hull->clip_mins[0] = -32;
+               hull->clip_mins[1] = -32;
+               hull->clip_mins[2] = -24;
+               hull->clip_maxs[0] = 32;
+               hull->clip_maxs[1] = 32;
+               hull->clip_maxs[2] = 64;
+       }
 
        for (i=0 ; i<count ; i++, out++, in++)
        {
index ea85c5891d5f84cf6af494466701605c183f7aa2..ecfe872a74720ee91fa995af4c15ab7cd32f5b02 100644 (file)
@@ -153,7 +153,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
 {
        void    *d;
        unsigned *buf;
-       byte    stackbuf[1024];         // avoid dirtying the cache heap
+//     byte    stackbuf[1024];         // avoid dirtying the cache heap
 
        if (!mod->needload)
        {
@@ -168,7 +168,8 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
        }
 
 // load the file
-       buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), false);
+       buf = (unsigned *)COM_LoadMallocFile (mod->name, false);
+//     buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), false);
        if (!buf)
        {
                if (crash)
@@ -202,6 +203,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
                Mod_LoadBrushModel (mod, buf);
                break;
        }
+       free(buf);
 
        return mod;
 }
index 865ef39eb362a8c13f49c003813d41d61993be87..d3a701a792545c0cc6b076c1eba9381e83fef611 100644 (file)
@@ -105,6 +105,12 @@ typedef struct model_s
        byte            *lightdata;
        char            *entities;
 
+       // LordHavoc: useful for sprites and models
+       int                     numtris;
+       int                     numskins;
+       int                     skinanimrange[1024]; // array of start and length pairs, note: offset from ->cache.data
+       int                     skinanim[1024*5]; // texture numbers for each frame (indexed by animrange), note: offset from ->cache.data, second note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow)
+
 // additional model data
        cache_user_t    cache;          // only access through Mod_Extradata
 
index b8b75dd3b5e9fa43a7b71b360ba5fed980765587..41691072378464104843128017d8ac166f00b579 100644 (file)
@@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // *********************************************************
 
 #define ALIAS_VERSION  6
-#define ALIAS32_VERSION        7
 
 #define ALIAS_ONSEAM                           0x0020
 
index 3c5a773baad675113f75f9b7e564f4eb8c48dcd9..0d5265ed4657df7b6f5a4d26aca726e11bb25e67 100644 (file)
@@ -129,7 +129,7 @@ int WINS_Init (void)
        
        if (hInst == NULL)
        {
-               Con_SafePrintf ("Failed to load winsock.dll\n");
+               Con_SafePrintf ("Failed to load wsock32.dll\n");
                winsock_lib_initialized = false;
                return -1;
        }
@@ -156,7 +156,7 @@ int WINS_Init (void)
                !pgethostname || !pgethostbyname || !pgethostbyaddr ||
                !pgetsockname)
        {
-               Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n");
+               Con_SafePrintf ("Couldn't GetProcAddress from wsock32.dll\n");
                return -1;
        }
 
index 4dd41a936b6290d25848dc90bdfb477d5d635b36..a608a074cd24bafe558cac5a4d363778a891525a 100644 (file)
--- a/pr_exec.c
+++ b/pr_exec.c
@@ -358,318 +358,6 @@ int PR_LeaveFunction (void)
 PR_ExecuteProgram
 ====================
 */
-/*
-void PR_ExecuteProgram (func_t fnum)
-{
-       eval_t  *a, *b, *c;
-       int                     s;
-       dstatement_t    *st;
-       dfunction_t     *f, *newf;
-       int             runaway;
-       int             i;
-       edict_t *ed;
-       int             exitdepth;
-       eval_t  *ptr;
-
-       if (!fnum || fnum >= progs->numfunctions)
-       {
-               if (pr_global_struct->self)
-                       ED_Print (PROG_TO_EDICT(pr_global_struct->self));
-               Host_Error ("PR_ExecuteProgram: NULL function");
-       }
-       
-       f = &pr_functions[fnum];
-
-       runaway = 100000;
-       pr_trace = false;
-
-// make a stack frame
-       exitdepth = pr_depth;
-
-       s = PR_EnterFunction (f);
-       
-while (1)
-{
-       s++;    // next statement
-
-       st = &pr_statements[s];
-       // LordHavoc: fix for 32768 QC def limit (just added unsigned short typecast)
-       a = (eval_t *)&pr_globals[(unsigned short) st->a];
-       b = (eval_t *)&pr_globals[(unsigned short) st->b];
-       c = (eval_t *)&pr_globals[(unsigned short) st->c];
-       
-       if (!--runaway)
-               PR_RunError ("runaway loop error");
-               
-       pr_xfunction->profile++;
-       pr_xstatement = s;
-       
-       if (pr_trace)
-               PR_PrintStatement (st);
-               
-       switch (st->op)
-       {
-       case OP_ADD_F:
-               c->_float = a->_float + b->_float;
-               break;
-       case OP_ADD_V:
-               c->vector[0] = a->vector[0] + b->vector[0];
-               c->vector[1] = a->vector[1] + b->vector[1];
-               c->vector[2] = a->vector[2] + b->vector[2];
-               break;
-               
-       case OP_SUB_F:
-               c->_float = a->_float - b->_float;
-               break;
-       case OP_SUB_V:
-               c->vector[0] = a->vector[0] - b->vector[0];
-               c->vector[1] = a->vector[1] - b->vector[1];
-               c->vector[2] = a->vector[2] - b->vector[2];
-               break;
-
-       case OP_MUL_F:
-               c->_float = a->_float * b->_float;
-               break;
-       case OP_MUL_V:
-               c->_float = a->vector[0]*b->vector[0]
-                               + a->vector[1]*b->vector[1]
-                               + a->vector[2]*b->vector[2];
-               break;
-       case OP_MUL_FV:
-               c->vector[0] = a->_float * b->vector[0];
-               c->vector[1] = a->_float * b->vector[1];
-               c->vector[2] = a->_float * b->vector[2];
-               break;
-       case OP_MUL_VF:
-               c->vector[0] = b->_float * a->vector[0];
-               c->vector[1] = b->_float * a->vector[1];
-               c->vector[2] = b->_float * a->vector[2];
-               break;
-
-       case OP_DIV_F:
-               c->_float = a->_float / b->_float;
-               break;
-       
-       case OP_BITAND:
-               c->_float = (int)a->_float & (int)b->_float;
-               break;
-       
-       case OP_BITOR:
-               c->_float = (int)a->_float | (int)b->_float;
-               break;
-       
-               
-       case OP_GE:
-               c->_float = a->_float >= b->_float;
-               break;
-       case OP_LE:
-               c->_float = a->_float <= b->_float;
-               break;
-       case OP_GT:
-               c->_float = a->_float > b->_float;
-               break;
-       case OP_LT:
-               c->_float = a->_float < b->_float;
-               break;
-       case OP_AND:
-               c->_float = a->_float && b->_float;
-               break;
-       case OP_OR:
-               c->_float = a->_float || b->_float;
-               break;
-               
-       case OP_NOT_F:
-               c->_float = !a->_float;
-               break;
-       case OP_NOT_V:
-               c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
-               break;
-       case OP_NOT_S:
-               c->_float = !a->string || !pr_strings[a->string];
-               break;
-       case OP_NOT_FNC:
-               c->_float = !a->function;
-               break;
-       case OP_NOT_ENT:
-               c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
-               break;
-
-       case OP_EQ_F:
-               c->_float = a->_float == b->_float;
-               break;
-       case OP_EQ_V:
-               c->_float = (a->vector[0] == b->vector[0]) &&
-                                       (a->vector[1] == b->vector[1]) &&
-                                       (a->vector[2] == b->vector[2]);
-               break;
-       case OP_EQ_S:
-               c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
-               break;
-       case OP_EQ_E:
-               c->_float = a->_int == b->_int;
-               break;
-       case OP_EQ_FNC:
-               c->_float = a->function == b->function;
-               break;
-
-
-       case OP_NE_F:
-               c->_float = a->_float != b->_float;
-               break;
-       case OP_NE_V:
-               c->_float = (a->vector[0] != b->vector[0]) ||
-                                       (a->vector[1] != b->vector[1]) ||
-                                       (a->vector[2] != b->vector[2]);
-               break;
-       case OP_NE_S:
-               c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
-               break;
-       case OP_NE_E:
-               c->_float = a->_int != b->_int;
-               break;
-       case OP_NE_FNC:
-               c->_float = a->function != b->function;
-               break;
-
-//==================
-       case OP_STORE_F:
-       case OP_STORE_ENT:
-       case OP_STORE_FLD:              // integers
-       case OP_STORE_S:
-       case OP_STORE_FNC:              // pointers
-               b->_int = a->_int;
-               break;
-       case OP_STORE_V:
-               b->vector[0] = a->vector[0];
-               b->vector[1] = a->vector[1];
-               b->vector[2] = a->vector[2];
-               break;
-               
-       case OP_STOREP_F:
-       case OP_STOREP_ENT:
-       case OP_STOREP_FLD:             // integers
-       case OP_STOREP_S:
-       case OP_STOREP_FNC:             // pointers
-               ptr = (eval_t *)((byte *)sv.edicts + b->_int);
-               ptr->_int = a->_int;
-               break;
-       case OP_STOREP_V:
-               ptr = (eval_t *)((byte *)sv.edicts + b->_int);
-               ptr->vector[0] = a->vector[0];
-               ptr->vector[1] = a->vector[1];
-               ptr->vector[2] = a->vector[2];
-               break;
-               
-       case OP_ADDRESS:
-               ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
-               NUM_FOR_EDICT(ed);              // make sure it's in range
-#endif
-               if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
-                       PR_RunError ("assignment to world entity");
-               c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
-               break;
-               
-       case OP_LOAD_F:
-       case OP_LOAD_FLD:
-       case OP_LOAD_ENT:
-       case OP_LOAD_S:
-       case OP_LOAD_FNC:
-               ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
-               NUM_FOR_EDICT(ed);              // make sure it's in range
-#endif
-               a = (eval_t *)((int *)&ed->v + b->_int);
-               c->_int = a->_int;
-               break;
-
-       case OP_LOAD_V:
-               ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
-               NUM_FOR_EDICT(ed);              // make sure it's in range
-#endif
-               a = (eval_t *)((int *)&ed->v + b->_int);
-               c->vector[0] = a->vector[0];
-               c->vector[1] = a->vector[1];
-               c->vector[2] = a->vector[2];
-               break;
-               
-//==================
-
-       case OP_IFNOT:
-               if (!a->_int)
-                       s += st->b - 1; // offset the s++
-               break;
-               
-       case OP_IF:
-               if (a->_int)
-                       s += st->b - 1; // offset the s++
-               break;
-               
-       case OP_GOTO:
-               s += st->a - 1; // offset the s++
-               break;
-               
-       case OP_CALL0:
-       case OP_CALL1:
-       case OP_CALL2:
-       case OP_CALL3:
-       case OP_CALL4:
-       case OP_CALL5:
-       case OP_CALL6:
-       case OP_CALL7:
-       case OP_CALL8:
-               pr_argc = st->op - OP_CALL0;
-               if (!a->function)
-                       PR_RunError ("NULL function");
-
-               newf = &pr_functions[a->function];
-
-               if (newf->first_statement < 0)
-               {       // negative statements are built in functions
-                       i = -newf->first_statement;
-                       if (i >= pr_numbuiltins)
-                               PR_RunError ("Bad builtin call number");
-                       pr_builtins[i] ();
-                       break;
-               }
-
-               s = PR_EnterFunction (newf);
-               break;
-
-       case OP_DONE:
-       case OP_RETURN:
-               pr_globals[OFS_RETURN] = pr_globals[st->a];
-               pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
-               pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
-       
-               s = PR_LeaveFunction ();
-               if (pr_depth == exitdepth)
-                       return;         // all done
-               break;
-               
-       case OP_STATE:
-               ed = PROG_TO_EDICT(pr_global_struct->self);
-#ifdef FPS_20
-               ed->v.nextthink = pr_global_struct->time + 0.05;
-#else
-               ed->v.nextthink = pr_global_struct->time + 0.1;
-#endif
-               //if (a->_float != ed->v.frame) // LordHavoc: this was silly
-               //{
-                       ed->v.frame = a->_float;
-               //}
-               ed->v.think = b->function;
-               break;
-               
-       default:
-               PR_RunError ("Bad opcode %i", st->op);
-       }
-}
-
-}
-*/
-
 // LordHavoc: optimized
 #define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
@@ -706,7 +394,7 @@ void PR_ExecuteProgram (func_t fnum)
                while (1)
                {
                        st++;
-                       if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
+                       if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
                        {
                                pr_xstatement = st - pr_statements;
                                PR_RunError ("runaway loop error");
@@ -991,11 +679,7 @@ void PR_ExecuteProgram (func_t fnum)
                                
                        case OP_STATE:
                                ed = PROG_TO_EDICT(pr_global_struct->self);
-               #ifdef FPS_20
-                               ed->v.nextthink = pr_global_struct->time + 0.05;
-               #else
                                ed->v.nextthink = pr_global_struct->time + 0.1;
-               #endif
                                ed->v.frame = OPA->_float;
                                ed->v.think = OPB->function;
                                break;
@@ -1011,7 +695,7 @@ void PR_ExecuteProgram (func_t fnum)
                while (1)
                {
                        st++;
-                       if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
+                       if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
                        {
                                pr_xstatement = st - pr_statements;
                                PR_RunError ("runaway loop error");
@@ -1296,11 +980,7 @@ void PR_ExecuteProgram (func_t fnum)
                                
                        case OP_STATE:
                                ed = PROG_TO_EDICT(pr_global_struct->self);
-               #ifdef FPS_20
-                               ed->v.nextthink = pr_global_struct->time + 0.05;
-               #else
                                ed->v.nextthink = pr_global_struct->time + 0.1;
-               #endif
                                ed->v.frame = OPA->_float;
                                ed->v.think = OPB->function;
                                break;
index 8b4d26af240dc0cb7ea7eccfd41369242d83629d..573af6e75623726263a87033c29db268cc2259b3 100644 (file)
@@ -19,11 +19,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 // quakedef.h -- primary header for client
 
-//#define      GLTEST                  // experimental stuff
-
 #define        QUAKE_GAME                      // as opposed to utilities
 
-#define        VERSION                         1.05
+#define        VERSION                         1.50
 
 #ifndef FALSE
 #define FALSE 0
@@ -31,6 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #endif
 
 //define       PARANOID                        // speed sapping error checking
+#ifdef _DEBUG
+#define ASSERT(condition) if (!(condition)) Sys_Error("assertion (##condition) failed at " __FILE__ ":" __LINE__ "\n");
+#else
+#define ASSERT(condition)
+#endif
 
 #define        GAMENAME        "id1"
 
@@ -261,7 +264,6 @@ extern      cvar_t          developer;
 extern qboolean        host_initialized;               // true if into command execution
 extern double          host_frametime;
 extern byte            *host_basepal;
-extern byte            *host_colormap;
 extern int                     host_framecount;        // incremented every frame, never reset
 extern double          realtime;                       // not bounded in any way, changed at
                                                                                // start of every frame, never reset
@@ -298,3 +300,7 @@ extern      cvar_t  chase_active;
 void Chase_Init (void);
 void Chase_Reset (void);
 void Chase_Update (void);
+
+void fractalnoise(unsigned char *noise, int size);
+
+#include "image.h"
diff --git a/r_crosshairs.c b/r_crosshairs.c
new file mode 100644 (file)
index 0000000..e2be867
--- /dev/null
@@ -0,0 +1,82 @@
+#include "quakedef.h"
+
+cvar_t crosshair_brightness = {"crosshair_brightness", "1.0", true};
+cvar_t crosshair_alpha = {"crosshair_alpha", "1.0", true};
+cvar_t crosshair_flashspeed = {"crosshair_flashspeed", "2", true};
+cvar_t crosshair_flashrange = {"crosshair_flashrange", "0.1", true};
+
+#define NUMCROSSHAIRS 1
+
+int crosshairtex[NUMCROSSHAIRS];
+
+char crosshairtex1[16*16] =
+       "0000000000000000"
+       "0000000000000000"
+       "0000000000000000"
+       "0003000000003000"
+       "0000500000050000"
+       "0000070000700000"
+       "0000007007000000"
+       "0000000000000000"
+       "0000000000000000"
+       "0000007007000000"
+       "0000070000700000"
+       "0000500000050000"
+       "0003000000003000"
+       "0000000000000000"
+       "0000000000000000"
+       "0000000000000000"
+;
+
+void r_crosshairs_start()
+{
+       int i;
+       byte data[64*64][4];
+       for (i = 0;i < 16*16;i++)
+       {
+               data[i][0] = data[i][1] = data[i][2] = 255;
+               data[i][3] = (crosshairtex1[i] - '0') * 255 / 7;
+       }
+       crosshairtex[0] = GL_LoadTexture("crosshair0", 16, 16, &data[0][0], false, true, 4);
+}
+
+void r_crosshairs_shutdown()
+{
+}
+
+void R_Crosshairs_Init()
+{
+       Cvar_RegisterVariable(&crosshair_brightness);
+       Cvar_RegisterVariable(&crosshair_alpha);
+       Cvar_RegisterVariable(&crosshair_flashspeed);
+       Cvar_RegisterVariable(&crosshair_flashrange);
+       R_RegisterModule("R_Crosshairs", r_crosshairs_start, r_crosshairs_shutdown);
+}
+
+void DrawCrosshair(int num)
+{
+       byte *color;
+       float scale, base;
+//     Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
+       if (num < 0 || num >= NUMCROSSHAIRS)
+               num = 0;
+       if (cl.viewentity)
+       {
+               int i = (cl.scores[cl.viewentity-1].colors & 0xF) << 4;
+               if (i >= 208 && i < 224) // blue
+                       i += 8;
+               else if (i < 128 || i >= 224) // 128-224 are backwards ranges (bright to dark, rather than dark to bright)
+                       i += 15;
+               color = (byte *) &d_8to24table[i];
+       }
+       else
+               color = (byte *) &d_8to24table[15];
+       if (crosshair_flashspeed.value >= 0.01f)
+//             scale = (sin(realtime * crosshair_flashspeed.value * (M_PI*2.0f)) * crosshair_flashrange.value + 1.0f) * (1.0f / 255.0f);
+               base = (sin(realtime * crosshair_flashspeed.value * (M_PI*2.0f)) * crosshair_flashrange.value);
+       else
+               base = 0.0f;
+       scale = crosshair_brightness.value / 255.0f;
+       Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, r_refdef.vrect.x + r_refdef.vrect.width * 0.5f - 8.0f, r_refdef.vrect.y + r_refdef.vrect.height * 0.5f - 8.0f, 16.0f, 16.0f);
+}
+
index 775beee83a9d2c52c4c6980bc7f60ed60ff12bce..bb50a11ce59b27c417fa38e26faacae67a568812 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -23,9 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 cvar_t r_lightmodels = {"r_lightmodels", "1"};
 
-void rlight_init()
+void r_light_start()
+{
+}
+
+void r_light_shutdown()
+{
+}
+
+void R_Light_Init()
 {
        Cvar_RegisterVariable(&r_lightmodels);
+       R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
 }
 
 int    r_dlightframecount;
@@ -146,6 +155,7 @@ void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitind
        R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
 }
 
+int lightframe = 0;
 void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
 {
        mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
@@ -160,7 +170,6 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                int             i, k, l, m, c;
                msurface_t *surf, **mark;
                mleaf_t *leaf;
-               static int lightframe = 0;
                byte    *in = pvsleaf->compressed_vis;
                int             row = (model->numleafs+7)>>3;
                float   low[3], high[3], radius;
@@ -190,10 +199,12 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                if (leaf->contents == CONTENTS_SOLID)
                                                        continue;
                                                // if out of the light radius, skip
+                                               /*
                                                if (leaf->minmaxs[0] > high[0] || leaf->minmaxs[3] < low[0]
                                                 || leaf->minmaxs[1] > high[1] || leaf->minmaxs[4] < low[1]
                                                 || leaf->minmaxs[2] > high[2] || leaf->minmaxs[5] < low[2])
                                                        continue;
+                                               */
                                                if (leaf->dlightframe != r_dlightframecount) // not dynamic until now
                                                {
                                                        leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0;
@@ -209,7 +220,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                                                                if (surf->visframe != r_framecount || surf->lightframe == lightframe)
                                                                        continue;
                                                                surf->lightframe = lightframe;
-                                                               if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDiff(lightorigin, surf->plane)) >= 0))
+                                                               //if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDiff(lightorigin, surf->plane)) >= 0))
                                                                {
                                                                        if (surf->dlightframe != r_dlightframecount) // not dynamic until now
                                                                        {
@@ -273,6 +284,7 @@ vec3_t                      lightspot;
 
 extern cvar_t r_ambient;
 
+/*
 int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end)
 {
        float           front, back, frac;
@@ -368,13 +380,176 @@ void R_LightPoint (vec3_t color, vec3_t p)
                color[0] = color[1] = color[2] = 255;
                return;
        }
+
+       end[0] = p[0];
+       end[1] = p[1];
+       end[2] = p[2] - 2048;
+
+       color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
+       RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
+}
+
+void SV_LightPoint (vec3_t color, vec3_t p)
+{
+       vec3_t          end;
+       
+       if (!sv.worldmodel->lightdata)
+       {
+               color[0] = color[1] = color[2] = 255;
+               return;
+       }
        
        end[0] = p[0];
        end[1] = p[1];
        end[2] = p[2] - 2048;
 
+       color[0] = color[1] = color[2] = 0;
+       RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
+}
+*/
+
+int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz)
+{
+       int             side, distz = endz - startz;
+       float   front, back;
+       float   mid;
+
+loc0:
+       if (node->contents < 0)
+               return false;           // didn't hit anything
+
+       switch (node->plane->type)
+       {
+       case PLANE_X:
+               node = node->children[x < node->plane->dist];
+               goto loc0;
+       case PLANE_Y:
+               node = node->children[y < node->plane->dist];
+               goto loc0;
+       case PLANE_Z:
+               side = startz < node->plane->dist;
+               if ((endz < node->plane->dist) == side)
+               {
+                       node = node->children[side];
+                       goto loc0;
+               }
+               // found an intersection
+//             mid = startz + (endz - startz) * (startz - node->plane->dist) / (startz - endz);
+//             mid = startz + distz * (startz - node->plane->dist) / (-distz);
+//             mid = startz + (-(startz - node->plane->dist));
+//             mid = startz - (startz - node->plane->dist);
+//             mid = startz + node->plane->dist - startz;
+               mid = node->plane->dist;
+               break;
+       default:
+               back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
+               front += startz * node->plane->normal[2];
+               back += endz * node->plane->normal[2];
+               side = front < node->plane->dist;
+               if ((back < node->plane->dist) == side)
+               {
+                       node = node->children[side];
+                       goto loc0;
+               }
+               // found an intersection
+//             mid = startz + (endz - startz) * ((front - node->plane->dist) / ((front - node->plane->dist) - (back - node->plane->dist)));
+//             mid = startz + (endz - startz) * ((front - node->plane->dist) / (front - back));
+               mid = startz + distz * (front - node->plane->dist) / (front - back);
+               break;
+       }
+       
+       // go down front side
+       if (node->children[side]->contents >= 0 && RecursiveLightPoint (color, node->children[side], x, y, startz, mid))
+               return true;    // hit something
+       else
+       {
+               // check for impact on this node
+               if (node->numsurfaces)
+               {
+                       int i, ds, dt;
+                       msurface_t *surf;
+                       lightspot[0] = x;
+                       lightspot[1] = y;
+                       lightspot[2] = mid;
+                       lightplane = node->plane;
+
+                       surf = cl.worldmodel->surfaces + node->firstsurface;
+                       for (i = 0;i < node->numsurfaces;i++, surf++)
+                       {
+                               if (surf->flags & SURF_DRAWTILED)
+                                       continue;       // no lightmaps
+
+                               ds = (int) (x * surf->texinfo->vecs[0][0] + y * surf->texinfo->vecs[0][1] + mid * surf->texinfo->vecs[0][2] + surf->texinfo->vecs[0][3]);
+                               dt = (int) (x * surf->texinfo->vecs[1][0] + y * surf->texinfo->vecs[1][1] + mid * surf->texinfo->vecs[1][2] + surf->texinfo->vecs[1][3]);
+
+                               if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
+                                       continue;
+                               
+                               ds -= surf->texturemins[0];
+                               dt -= surf->texturemins[1];
+                               
+                               if (ds > surf->extents[0] || dt > surf->extents[1])
+                                       continue;
+
+                               if (surf->samples)
+                               {
+                                       byte *lightmap;
+                                       int maps, line3, size3, dsfrac = ds & 15, dtfrac = dt & 15, scale = 0, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
+                                       line3 = ((surf->extents[0]>>4)+1)*3;
+                                       size3 = ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
+
+                                       lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
+
+                                       for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
+                                       {
+                                               scale = d_lightstylevalue[surf->styles[maps]];
+                                               r00 += lightmap[      0] * scale;g00 += lightmap[      1] * scale;b00 += lightmap[      2] * scale;
+                                               r01 += lightmap[      3] * scale;g01 += lightmap[      4] * scale;b01 += lightmap[      5] * scale;
+                                               r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
+                                               r11 += lightmap[line3+3] * scale;g11 += lightmap[line3+4] * scale;b11 += lightmap[line3+5] * scale;
+                                               lightmap += size3;
+                                       }
+
+                                       color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f);
+                                       color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f);
+                                       color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f);
+                               }
+                               return true; // success
+                       }
+               }
+
+               // go down back side
+               node = node->children[side ^ 1];
+               startz = mid;
+               distz = endz - startz;
+               goto loc0;
+//             return RecursiveLightPoint (color, node->children[side ^ 1], x, y, mid, endz);
+       }
+}
+
+void R_LightPoint (vec3_t color, vec3_t p)
+{
+       if (r_fullbright.value || !cl.worldmodel->lightdata)
+       {
+               color[0] = color[1] = color[2] = 255;
+               return;
+       }
+       
        color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
-       RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
+       RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
+}
+
+// LordHavoc: added light checking to the server
+void SV_LightPoint (vec3_t color, vec3_t p)
+{
+       if (!sv.worldmodel->lightdata)
+       {
+               color[0] = color[1] = color[2] = 255;
+               return;
+       }
+       
+       color[0] = color[1] = color[2] = 0;
+       RecursiveLightPoint (color, sv.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
 }
 
 // LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting
@@ -397,8 +572,8 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits)
                                        continue;
                                k = (j<<5)+i;
                                VectorSubtract (org, cl_dlights[k].origin, dist);
-                               f = DotProduct(dist, dist) + 65536.0f;
-                               r = cl_dlights[k].radius*cl_dlights[k].radius*16.0f;
+                               f = DotProduct(dist, dist) + LIGHTOFFSET;
+                               r = cl_dlights[k].radius*cl_dlights[k].radius*LIGHTSCALE;
                                if (f < r)
                                {
                                        brightness = r * 16.0f / f;
@@ -426,8 +601,8 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org)
                if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
                        continue;
                VectorSubtract (org, cl_dlights[i].origin, dist);
-               f = DotProduct(dist, dist) + 65536.0f;
-               r = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
+               f = DotProduct(dist, dist) + LIGHTOFFSET;
+               r = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
                if (f < r)
                {
                        brightness = r * 16.0f / f;
@@ -449,14 +624,14 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p)
 extern float *aliasvert;
 extern float *aliasvertnorm;
 extern byte *aliasvertcolor;
-extern vec_t shadecolor[];
 extern float modelalpha;
 extern qboolean lighthalf;
 extern int modeldlightbits[8];
-void R_LightModel(int numverts, vec3_t center)
+void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
 {
-       int i, j, nearlights = 0;
-       vec3_t dist;
+       // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
+       int i, j, nearlights = 0, color;
+       vec3_t dist, mod;
        float t, t1, t2, t3, *avn;
        byte r,g,b,a, *avc;
        struct
@@ -464,12 +639,6 @@ void R_LightModel(int numverts, vec3_t center)
                vec3_t color;
                vec3_t origin;
        } nearlight[MAX_DLIGHTS];
-       if (!lighthalf)
-       {
-               shadecolor[0] *= 2.0f;
-               shadecolor[1] *= 2.0f;
-               shadecolor[2] *= 2.0f;
-       }
        avc = aliasvertcolor;
        avn = aliasvertnorm;
        a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
@@ -477,25 +646,39 @@ void R_LightModel(int numverts, vec3_t center)
        {
                if (lighthalf)
                {
-                       r = (byte) ((float) (128.0f * currententity->colormod[0]));
-                       g = (byte) ((float) (128.0f * currententity->colormod[1]));
-                       b = (byte) ((float) (128.0f * currententity->colormod[2]));
+                       ((byte *)&color)[0] = (byte) ((float) (128.0f * currententity->colormod[0]));
+                       ((byte *)&color)[1] = (byte) ((float) (128.0f * currententity->colormod[1]));
+                       ((byte *)&color)[2] = (byte) ((float) (128.0f * currententity->colormod[2]));
                }
                else
                {
-                       r = (byte) ((float) (255.0f * currententity->colormod[0]));
-                       g = (byte) ((float) (255.0f * currententity->colormod[1]));
-                       b = (byte) ((float) (255.0f * currententity->colormod[2]));
+                       ((byte *)&color)[0] = (byte) ((float) (255.0f * currententity->colormod[0]));
+                       ((byte *)&color)[1] = (byte) ((float) (255.0f * currententity->colormod[1]));
+                       ((byte *)&color)[2] = (byte) ((float) (255.0f * currententity->colormod[2]));
                }
+               ((byte *)&color)[3] = a;
                for (i = 0;i < numverts;i++)
                {
-                       *avc++ = r;
-                       *avc++ = g;
-                       *avc++ = b;
-                       *avc++ = a;
+                       *((int *)avc) = color;
+                       avc += 4;
                }
                return;
        }
+       if (lighthalf)
+       {
+               mod[0] = currententity->colormod[0] * 0.5f;
+               mod[1] = currententity->colormod[1] * 0.5f;
+               mod[2] = currententity->colormod[2] * 0.5f;
+       }
+       else
+       {
+               mod[0] = currententity->colormod[0];
+               mod[1] = currententity->colormod[1];
+               mod[2] = currententity->colormod[2];
+       }
+       basecolor[0] *= mod[0];
+       basecolor[1] *= mod[1];
+       basecolor[2] *= mod[2];
        if (r_lightmodels.value)
        {
                for (i = 0;i < MAX_DLIGHTS;i++)
@@ -507,30 +690,19 @@ void R_LightModel(int numverts, vec3_t center)
                        }
                        if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
                                continue;
-//                     if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
-//                             continue;
                        VectorSubtract (center, cl_dlights[i].origin, dist);
-                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
-                       t2 = DotProduct(dist,dist) + 65536.0f;
+                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
+                       t2 = DotProduct(dist,dist) + LIGHTOFFSET;
                        if (t2 < t1)
                        {
                                VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
-                               nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               if (lighthalf)
-                               {
-                                       nearlight[nearlights].color[0] *= 0.5f;
-                                       nearlight[nearlights].color[1] *= 0.5f;
-                                       nearlight[nearlights].color[2] *= 0.5f;
-                               }
-                               t1 = 0.5f / t2;
-                               shadecolor[0] += nearlight[nearlights].color[0] * t1;
-                               shadecolor[1] += nearlight[nearlights].color[1] * t1;
-                               shadecolor[2] += nearlight[nearlights].color[2] * t1;
-                               nearlight[nearlights].color[0] *= currententity->colormod[0];
-                               nearlight[nearlights].color[1] *= currententity->colormod[1];
-                               nearlight[nearlights].color[2] *= currententity->colormod[2];
+                               nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
+                               nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
+                               nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
+                               t1 = (128.0f / LIGHTSCALE) / t2;
+                               basecolor[0] += nearlight[nearlights].color[0] * t1;
+                               basecolor[1] += nearlight[nearlights].color[1] * t1;
+                               basecolor[2] += nearlight[nearlights].color[2] * t1;
                                nearlights++;
                        }
                }
@@ -546,35 +718,28 @@ void R_LightModel(int numverts, vec3_t center)
                        }
                        if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
                                continue;
-//                     if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
-//                             continue;
                        VectorSubtract (center, cl_dlights[i].origin, dist);
-                       t2 = DotProduct(dist,dist) + 65536.0f;
-                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
+                       t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
+                       t2 = DotProduct(dist,dist) + LIGHTOFFSET;
                        if (t2 < t1)
                        {
-                               dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
-                               if (lighthalf)
-                               {
-                                       dist[0] *= 0.5f;
-                                       dist[1] *= 0.5f;
-                                       dist[2] *= 0.5f;
-                               }
-                               t1 = 0.75f / t2;
-                               shadecolor[0] += dist[0] * t1;
-                               shadecolor[1] += dist[1] * t1;
-                               shadecolor[2] += dist[2] * t1;
+                               dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
+                               dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
+                               dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
+                               t1 = (192.0f / LIGHTSCALE) / t2;
+                               basecolor[0] += dist[0] * t1;
+                               basecolor[1] += dist[1] * t1;
+                               basecolor[2] += dist[2] * t1;
                        }
                }
        }
-       shadecolor[0] *= currententity->colormod[0];
-       shadecolor[1] *= currententity->colormod[1];
-       shadecolor[2] *= currententity->colormod[2];
-       t1 = bound(0, shadecolor[0], 255);r = (byte) t1;
-       t1 = bound(0, shadecolor[1], 255);g = (byte) t1;
-       t1 = bound(0, shadecolor[2], 255);b = (byte) t1;
+       t1 = bound(0, basecolor[0], 255);r = (byte) t1;
+       t1 = bound(0, basecolor[1], 255);g = (byte) t1;
+       t1 = bound(0, basecolor[2], 255);b = (byte) t1;
+       ((byte *)&color)[0] = r;
+       ((byte *)&color)[1] = g;
+       ((byte *)&color)[2] = b;
+       ((byte *)&color)[3] = a;
        if (nearlights)
        {
                int temp;
@@ -590,29 +755,27 @@ void R_LightModel(int numverts, vec3_t center)
                                if (t > 0)
                                {
                                        t /= DotProduct(v,v);
-                                       temp = (int) ((float) (shadecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
-                                       temp = (int) ((float) (shadecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
-                                       temp = (int) ((float) (shadecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
+                                       temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[0] = temp;
+                                       temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[1] = temp;
+                                       temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[2] = temp;
+                                       avc[3] = a;
                                }
                                else
-                               {
-                                       *avc++ = r;
-                                       *avc++ = g;
-                                       *avc++ = b;
-                               }
-                               *avc++ = a;
+                                       *((int *)avc) = color;
+                               avc += 4;
                                av+=3;
                                avn+=3;
                        }
                }
                else
                {
-                       int i1, i2, i3;
+                       int i1, i2, i3, k;
                        for (i = 0;i < numverts;i++)
                        {
-                               t1 = shadecolor[0];
-                               t2 = shadecolor[1];
-                               t3 = shadecolor[2];
+                               t1 = basecolor[0];
+                               t2 = basecolor[1];
+                               t3 = basecolor[2];
+                               k = false;
                                for (j = 0;j < nearlights;j++)
                                {
                                        VectorSubtract(nearlight[j].origin, av, v);
@@ -623,15 +786,19 @@ void R_LightModel(int numverts, vec3_t center)
                                                t1 += nearlight[j].color[0] * t;
                                                t2 += nearlight[j].color[1] * t;
                                                t3 += nearlight[j].color[2] * t;
+                                               k = true;
                                        }
                                }
-                               i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;
-                               i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;
-                               i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;
-                               *avc++ = i1;
-                               *avc++ = i2;
-                               *avc++ = i3;
-                               *avc++ = a;
+                               if (k) // dodge the costly float -> int conversions
+                               {
+                                       i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;avc[0] = i1;
+                                       i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;avc[1] = i2;
+                                       i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;avc[2] = i3;
+                                       avc[3] = a;
+                               }
+                               else
+                                       *((int *)avc) = color;
+                               avc += 4;
                        }
                }
        }
@@ -639,10 +806,8 @@ void R_LightModel(int numverts, vec3_t center)
        {
                for (i = 0;i < numverts;i++)
                {
-                       *avc++ = r;
-                       *avc++ = g;
-                       *avc++ = b;
-                       *avc++ = a;
+                       *((int *)avc) = color;
+                       avc += 4;
                }
        }
 }
diff --git a/r_light.h b/r_light.h
new file mode 100644 (file)
index 0000000..ac6d256
--- /dev/null
+++ b/r_light.h
@@ -0,0 +1,18 @@
+
+// LordHavoc: 256 dynamic lights
+#define        MAX_DLIGHTS             256
+typedef struct
+{
+       vec3_t  origin;
+       float   radius;
+       float   die;                            // stop lighting after this time
+       float   decay;                          // drop this each second
+       float   minlight;                       // don't add when contributing less
+       int             key;
+       vec3_t  color;                          // LordHavoc: colored lighting
+       qboolean        dark;                   // subtracts light instead of adding
+} dlight_t;
+
+// LordHavoc: this affects the lighting scale of the whole game
+#define LIGHTOFFSET 16384.0f
+#define LIGHTSCALE 4.0f
diff --git a/r_modules.c b/r_modules.c
new file mode 100644 (file)
index 0000000..1c30a4c
--- /dev/null
@@ -0,0 +1,72 @@
+
+#include "quakedef.h"
+
+typedef struct rendermodule_s
+{
+       int active; // set by start, cleared by shutdown
+       char *name;
+       void(*start)();
+       void(*shutdown)();
+}
+rendermodule_t;
+
+rendermodule_t rendermodule[64];
+
+void R_Modules_Init()
+{
+       int i;
+       for (i = 0;i < 64;i++)
+               rendermodule[i].name = NULL;
+}
+
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)())
+{
+       int i;
+       for (i = 0;i < 64;i++)
+       {
+               if (rendermodule[i].name == NULL)
+                       break;
+               if (!strcmp(name, rendermodule[i].name))
+                       Sys_Error("R_RegisterModule: module \"%s\" registered twice\n", name);
+       }
+       if (i >= 64)
+               Sys_Error("R_RegisterModule: ran out of renderer module slots (64)\n");
+       rendermodule[i].active = 0;
+       rendermodule[i].name = name;
+       rendermodule[i].start = start;
+       rendermodule[i].shutdown = shutdown;
+}
+
+void R_StartModules ()
+{
+       int i;
+       for (i = 0;i < 64;i++)
+       {
+               if (rendermodule[i].name == NULL)
+                       continue;
+               if (rendermodule[i].active)
+                       Sys_Error("R_StartModules: module \"%s\" already active\n", rendermodule[i].name);
+               rendermodule[i].active = 1;
+               rendermodule[i].start();
+       }
+}
+
+void R_ShutdownModules ()
+{
+       int i;
+       for (i = 0;i < 64;i++)
+       {
+               if (rendermodule[i].name == NULL)
+                       continue;
+               if (!rendermodule[i].active)
+                       continue;
+               rendermodule[i].active = 0;
+               rendermodule[i].shutdown();
+       }
+}
+
+void R_Restart ()
+{
+       R_ShutdownModules();
+       R_StartModules();
+}
diff --git a/r_modules.h b/r_modules.h
new file mode 100644 (file)
index 0000000..38aa9c6
--- /dev/null
@@ -0,0 +1,6 @@
+
+void R_Modules_Init();
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)());
+void R_StartModules ();
+void R_ShutdownModules ();
+void R_Restart ();
index 24824c2fb508bd62c6c845d26f8de1d99c94250e..b2f6baf29315ca23caf11acb4609886263373921 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -70,9 +70,6 @@ particle_t    **freeparticles; // list used only in compacting particles array
 cvar_t r_particles = {"r_particles", "1"};
 cvar_t r_dynamicparticles = {"r_dynamicparticles", "0", TRUE};
 
-void fractalnoise(char *noise, int size);
-void fractalnoise_zeroedge(char *noise, int size);
-
 void R_InitParticleTexture (void)
 {
        int             x,y,d,i;
@@ -80,9 +77,6 @@ void R_InitParticleTexture (void)
        byte    data[32][32][4], noise1[32][32], noise2[32][32];
        vec3_t  normal, light;
 
-       particletexture = texture_extension_number++;
-       glBindTexture(GL_TEXTURE_2D, particletexture);
-
        for (x=0 ; x<32 ; x++)
        {
                for (y=0 ; y<32 ; y++)
@@ -95,13 +89,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+       particletexture = GL_LoadTexture ("particletexture", 32, 32, &data[0][0][0], true, true, 4);
 
        for (i = 0;i < 8;i++)
        {
@@ -127,17 +115,9 @@ void R_InitParticleTexture (void)
                                        data[y][x][3] = 0;
                        }
 
-               smokeparticletexture[i] = texture_extension_number++;
-               glBindTexture(GL_TEXTURE_2D, smokeparticletexture[i]);
-               glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-               glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               smokeparticletexture[i] = GL_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], true, true, 4);
        }
 
-       rainparticletexture = texture_extension_number++;
-       glBindTexture(GL_TEXTURE_2D, rainparticletexture);
-
        for (x=0 ; x<32 ; x++)
        {
                for (y=0 ; y<32 ; y++)
@@ -159,15 +139,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-       bubbleparticletexture = texture_extension_number++;
-       glBindTexture(GL_TEXTURE_2D, bubbleparticletexture);
+       rainparticletexture = GL_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], true, true, 4);
 
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
@@ -206,12 +178,20 @@ void R_InitParticleTexture (void)
                                data[y][x][3] = 0;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       bubbleparticletexture = GL_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], true, true, 4);
+}
 
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+void r_part_start()
+{
+       particles = (particle_t *) malloc (r_numparticles * sizeof(particle_t));
+       freeparticles = (void *) malloc (r_numparticles * sizeof(particle_t *));
+       R_InitParticleTexture ();
+}
 
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+void r_part_shutdown()
+{
+       free(particles);
+       free(freeparticles);
 }
 
 /*
@@ -219,7 +199,7 @@ void R_InitParticleTexture (void)
 R_InitParticles
 ===============
 */
-void R_InitParticles (void)
+void R_Particles_Init (void)
 {
        int             i;
 
@@ -236,12 +216,10 @@ void R_InitParticles (void)
                r_numparticles = MAX_PARTICLES;
        }
 
-       particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
-       freeparticles = (void *) Hunk_AllocName (r_numparticles * sizeof(particle_t *), "particles");
-
        Cvar_RegisterVariable (&r_particles);
        Cvar_RegisterVariable (&r_dynamicparticles);
-       R_InitParticleTexture ();
+
+       R_RegisterModule("R_Particles", r_part_start, r_part_shutdown);
 }
 
 #define particle(ptype, pcolor, ptex, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\
index c4ed70e717a694570e5204c0d02b74b72b419314..2347d941c9e7d9b9f40127741ab871563d2aee39 100644 (file)
--- a/render.h
+++ b/render.h
@@ -68,7 +68,6 @@ typedef struct entity_s
        struct efrag_s                  *efrag;                 // linked list of efrags
        int                                             frame;
        float                                   syncbase;               // for client-side animations
-//     byte                                    *colormap;
        int                                             colormap;
        int                                             effects;                // light, particals, etc
        int                                             skinnum;                // for Alias models
@@ -129,7 +128,7 @@ extern      struct texture_s        *r_notexture_mip;
 
 // LordHavoc: generic image loader
 byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight);
+int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap);
 
 void R_Init (void);
 void R_InitTextures (void);
index f2bf0ad5018ffdfa1bfac01b0021bce15ce2e49b..a22d9395cbfcbaf99effde9ce4f0791f6b4b1c56 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -1341,23 +1341,3 @@ void SV_SpawnServer (char *server)
        
        Con_DPrintf ("Server spawned.\n");
 }
-
-// LordHavoc: added light checking to the server
-int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end);
-void SV_LightPoint (vec3_t color, vec3_t p)
-{
-       vec3_t          end;
-       
-       if (!sv.worldmodel->lightdata)
-       {
-               color[0] = color[1] = color[2] = 255;
-               return;
-       }
-       
-       end[0] = p[0];
-       end[1] = p[1];
-       end[2] = p[2] - 2048;
-
-       color[0] = color[1] = color[2] = 0;
-       RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
-}
index 99ec8842ad780c7fb50fb8e855a9dc8490e156db..6ac56f8b3a25e6b973006ae527a3ecc0345c226b 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -597,25 +597,8 @@ void GL_Init (void)
        // LordHavoc: report supported extensions
        Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
 
-//     glClearColor (1,0,0,0);
        glCullFace(GL_FRONT);
-//     glEnable(GL_TEXTURE_2D);
-//
-//     glEnable(GL_ALPHA_TEST);
        glAlphaFunc(GL_GREATER, 0.5);
-//
-//     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-//     glShadeModel (GL_FLAT);
-//
-//     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-//     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-//     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-//     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-//
-//     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-//
-//     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-//     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 }
 
 /*
index f6d5654f9ac23545484659dd0e78cd592426c1db..719e0203f7e84a1177718bed6f7adcc255328e72 100644 (file)
@@ -98,7 +98,7 @@ void Check_Gamma (unsigned char *pal)
        }
 
        // gamma correct the palette
-       for (i=0 ; i<768 ; i++)
-               pal[i] = qgamma[pal[i]];
+       //for (i=0 ; i<768 ; i++)
+       //      pal[i] = qgamma[pal[i]];
        // note: 32bit uploads are corrected by the upload functions
 }
index d28c8d2f2115fb5016284ee96f60aec4d9d6e41a..64f9c41a5f5acbaae6f26d4c60e94cdd5ed67fcd 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -568,27 +568,8 @@ void GL_Init (void)
        // LordHavoc: report supported extensions
        Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
        // LordHavoc: set up state
-//     glEnable(GL_DEPTH_TEST);
-//     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-//     glShadeModel(GL_SMOOTH);
-//     glEnable(GL_TEXTURE_2D);
        glAlphaFunc(GL_GREATER, 0.5);
-//     if (isRagePro || isG200)
-//     {
-//             glEnable(GL_ALPHA_TEST);
-//             glAlphaFunc(GL_GREATER, 0.5);
-//     }
-//     else
-//             glDisable(GL_ALPHA_TEST);
-//     glDepthMask(1);
-//     glDisable(GL_DITHER); // LordHavoc: disable dithering
-//     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-//     glEnable(GL_BLEND);
-
-//     glClearColor (0,0,0,0); // LordHavoc: changed from red to black
        glCullFace(GL_FRONT);
-
-//     glAlphaFunc(GL_GREATER, 0.666);
 }
 
 /*
diff --git a/view.c b/view.c
index f2daebbd8dc2e6f7ff8106681907bc789b0e5ee3..3645467cada6a8c572d6dc7e3622acd2d1cde6d3 100644 (file)
--- a/view.c
+++ b/view.c
@@ -54,7 +54,8 @@ cvar_t        crosshair = {"crosshair", "0", true};
 cvar_t cl_crossx = {"cl_crossx", "0", false};
 cvar_t cl_crossy = {"cl_crossy", "0", false};
 
-cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
+//cvar_t       gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
+cvar_t gl_polyblend = {"gl_polyblend", "1", true};
 
 float  v_dmg_time, v_dmg_roll, v_dmg_pitch;
 
@@ -277,29 +278,32 @@ void V_ParseDamage (void)
 
        cl.faceanimtime = cl.time + 0.2;                // but sbar face into pain frame
 
-       cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
-       if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
-               cl.cshifts[CSHIFT_DAMAGE].percent = 0;
-       if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
-               cl.cshifts[CSHIFT_DAMAGE].percent = 150;
-
-       if (armor > blood)              
-       {
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
-       }
-       else if (armor)
-       {
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
-       }
-       else
+       if (gl_polyblend.value)
        {
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
-               cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
+               cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
+               if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
+                       cl.cshifts[CSHIFT_DAMAGE].percent = 0;
+               if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
+                       cl.cshifts[CSHIFT_DAMAGE].percent = 150;
+
+               if (armor > blood)              
+               {
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
+               }
+               else if (armor)
+               {
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
+               }
+               else
+               {
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
+                       cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
+               }
        }
 
 //
@@ -345,10 +349,13 @@ When you run over an item, the server sends this command
 */
 void V_BonusFlash_f (void)
 {
-       cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
-       cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
-       cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
-       cl.cshifts[CSHIFT_BONUS].percent = 50;
+       if (gl_polyblend.value)
+       {
+               cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
+               cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
+               cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
+               cl.cshifts[CSHIFT_BONUS].percent = 50;
+       }
 }
 
 /*
@@ -362,6 +369,11 @@ void V_SetContentsColor (int contents)
 {
        cshift_t* c;
        c = &cl.cshifts[CSHIFT_CONTENTS]; // just to shorten the code below
+       if (!gl_polyblend.value)
+       {
+               c->percent = 0;
+               return;
+       }
        switch (contents)
        {
        case CONTENTS_EMPTY:
@@ -402,6 +414,11 @@ V_CalcPowerupCshift
 */
 void V_CalcPowerupCshift (void)
 {
+       if (!gl_polyblend.value)
+       {
+               cl.cshifts[CSHIFT_POWERUP].percent = 0;
+               return;
+       }
        if (cl.items & IT_QUAD)
        {
                cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
@@ -450,11 +467,12 @@ void V_CalcBlend (void)
        b = 0;
        a = 0;
 
-       if (gl_cshiftpercent.value)
-       {
+//     if (gl_cshiftpercent.value)
+//     {
                for (j=0 ; j<NUM_CSHIFTS ; j++) 
                {
-                       a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
+//                     a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
+                       a2 = cl.cshifts[j].percent * (1.0f / 255.0f);
 
                        if (!a2)
                                continue;
@@ -473,7 +491,7 @@ void V_CalcBlend (void)
                        g *= a2;
                        b *= a2;
                }
-       }
+//     }
 
        v_blend[0] = bound(0, r * (1.0/255.0), 1);
        v_blend[1] = bound(0, g * (1.0/255.0), 1);
@@ -799,7 +817,7 @@ void V_CalcRefdef (void)
 
        view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
        view->frame = cl.stats[STAT_WEAPONFRAME];
-       view->colormap = 0; //vid.colormap;
+       view->colormap = -1; // no special coloring
 
 // set up the refresh position
        if (!intimerefresh)
@@ -885,7 +903,8 @@ void V_Init (void)
        Cvar_RegisterVariable (&crosshair);
        Cvar_RegisterVariable (&cl_crossx);
        Cvar_RegisterVariable (&cl_crossy);
-       Cvar_RegisterVariable (&gl_cshiftpercent);
+//     Cvar_RegisterVariable (&gl_cshiftpercent);
+       Cvar_RegisterVariable (&gl_polyblend);
 
        Cvar_RegisterVariable (&cl_rollspeed);
        Cvar_RegisterVariable (&cl_rollangle);
diff --git a/world.c b/world.c
index a83dd216918141d21b3f296b4267578776ed9863..0519bd85e0f6a80961fc7417ee8264e2a18b020a 100644 (file)
--- a/world.c
+++ b/world.c
@@ -124,6 +124,7 @@ Offset is filled in to contain the adjustment that must be added to the
 testing object's origin to get a point to use with the returned hull.
 ================
 */
+extern qboolean hlbsp;
 hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
 {
        model_t         *model;
@@ -149,12 +150,29 @@ hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
 
                VectorSubtract (maxs, mins, size);
                // LordHavoc: FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-               if (size[0] < 3)
-                       hull = &model->hulls[0];
-               else if (size[0] <= 32)
-                       hull = &model->hulls[1];
+               if (hlbsp)
+               {
+                       if (size[0] < 3)
+                               hull = &model->hulls[0]; // 0x0x0
+                       else if (size[0] <= 32)
+                       {
+                               if (size[2] < 54) // pick the nearest of 36 or 72
+                                       hull = &model->hulls[3]; // 32x32x36
+                               else
+                                       hull = &model->hulls[1]; // 32x32x72
+                       }
+                       else
+                               hull = &model->hulls[2]; // 64x64x64
+               }
                else
-                       hull = &model->hulls[2];
+               {
+                       if (size[0] < 3)
+                               hull = &model->hulls[0]; // 0x0x0
+                       else if (size[0] <= 32)
+                               hull = &model->hulls[1]; // 32x32x56
+                       else
+                               hull = &model->hulls[2]; // 64x64x88
+               }
 
 // calculate an offset value to center the origin
                VectorSubtract (hull->clip_mins, mins, offset);