]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
misc. cleanup, bubble trails fixed, improved lightmap compatibility.
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 31 Aug 2000 14:09:05 +0000 (14:09 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 31 Aug 2000 14:09:05 +0000 (14:09 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@15 d7cf8633-e32d-0410-b094-e92efae38249

14 files changed:
cl_input.c
cl_main.c
cl_parse.c
cl_tent.c
client.h
gl_poly.c
gl_rmain.c
gl_rsurf.c
gl_warp.c
glquake.h
host_cmd.c
mathlib.h
model_alias.c
r_part.c

index a4a7e4d2aaf4802e6ddabdc436772bfb84946f83..a43a9d9a3d4d0f15f0cba835617aea6d62af1c6c 100644 (file)
@@ -351,7 +351,7 @@ void CL_SendMove (usercmd_t *cmd)
        upmove += cmd->upmove;
        total++;
        // LordHavoc: cap outgoing movement messages to sys_ticrate
-       if (cl.maxclients > 1 && realtime - lastmovetime < sys_ticrate.value)
+       if ((cl.maxclients > 1) && (realtime - lastmovetime < sys_ticrate.value))
                return;
        lastmovetime = realtime;
        // average what has happened during this time
@@ -381,6 +381,7 @@ void CL_SendMove (usercmd_t *cmd)
     MSG_WriteShort (&buf, sidemove);
     MSG_WriteShort (&buf, upmove);
 
+       forwardmove = sidemove = upmove = 0;
 //
 // send button bits
 //
index af1b4a0437e1feb7b6909bf306b4fe4904a4b812..0a42a264a3ae615883bd83fbd60bf12facf7b447 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -812,6 +812,25 @@ void CL_PModel_f (void)
                val->_float = i;
 }
 
+/*
+======================
+CL_Fog_f
+======================
+*/
+extern float fog_density, fog_red, fog_green, fog_blue;
+void CL_Fog_f (void)
+{
+       if (Cmd_Argc () == 1)
+       {
+               Con_Printf ("\"fog\" is \"%f %f %f %f\"\n", fog_density, fog_red, fog_green, fog_blue);
+               return;
+       }
+       fog_density = atof(Cmd_Argv(1));
+       fog_red = atof(Cmd_Argv(2));
+       fog_green = atof(Cmd_Argv(3));
+       fog_blue = atof(Cmd_Argv(4));
+}
+
 cvar_t demo_nehahra = {"demo_nehahra", "0"};
 
 /*
@@ -860,6 +879,8 @@ void CL_Init (void)
        Cmd_AddCommand ("playdemo", CL_PlayDemo_f);
        Cmd_AddCommand ("timedemo", CL_TimeDemo_f);
 
+       Cmd_AddCommand ("fog", CL_Fog_f);
+
        // LordHavoc: added pausedemo
        Cmd_AddCommand ("pausedemo", CL_PauseDemo_f);
        // LordHavoc: added pmodel command (like name, etc, only intended for Nehahra)
index b389312ff9255204503f07d848206bbecef845b7..b1f240b073493384256b3de6df599c4f3c17ba49 100644 (file)
@@ -267,6 +267,11 @@ void CL_ParseEntityLump(char *entdata)
 //                     if (r_skyboxsize.value < 64)
 //                             r_skyboxsize.value = 64;
 //             }
+               else if (!strcmp("fog", key))
+               {
+                       scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
+                       j = 0;
+               }
                else if (!strcmp("fog_density", key))
                        fog_density = atof(value);
                else if (!strcmp("fog_red", key))
@@ -521,7 +526,7 @@ void CL_ParseUpdate (int bits)
        {
                if (i > cl.maxclients)
                        Host_Error ("i >= cl.maxclients");
-               ent->colormap = cl.scores[i-1].translations;
+               ent->colormap = vid.colormap; // cl.scores[i-1].translations;
        }
 
        skin = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
@@ -740,44 +745,6 @@ void CL_ParseClientdata (int bits)
        }
 }
 
-/*
-=====================
-CL_NewTranslation
-=====================
-*/
-void CL_NewTranslation (int slot)
-{
-       int             i, j;
-       int             top, bottom;
-       byte    *dest, *source;
-       
-       if (slot > cl.maxclients)
-               Host_Error ("CL_NewTranslation: slot > cl.maxclients");
-       dest = cl.scores[slot].translations;
-       source = vid.colormap;
-       memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
-       top = cl.scores[slot].colors & 0xf0;
-       bottom = (cl.scores[slot].colors &15)<<4;
-       R_TranslatePlayerSkin (slot);
-
-       for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
-       {
-               // LordHavoc: corrected color ranges
-               if (top < 128 || (top >= 224 && top < 240))     // the artists made some backwards ranges.  sigh.
-                       memcpy (dest + TOP_RANGE, source + top, 16);
-               else
-                       for (j=0 ; j<16 ; j++)
-                               dest[TOP_RANGE+j] = source[top+15-j];
-                               
-               // LordHavoc: corrected color ranges
-               if (bottom < 128 || (bottom >= 224 && bottom < 240))
-                       memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
-               else
-                       for (j=0 ; j<16 ; j++)
-                               dest[BOTTOM_RANGE+j] = source[bottom+15-j];             
-       }
-}
-
 /*
 =====================
 CL_ParseStatic
@@ -992,7 +959,7 @@ void CL_ParseServerMessage (void)
                        if (i >= cl.maxclients)
                                Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
                        cl.scores[i].colors = MSG_ReadByte ();
-                       CL_NewTranslation (i);
+                       R_TranslatePlayerSkin (i);
                        break;
                        
                case svc_particle:
index 573dc59383fda3c126fbffbf65e88ad0ac928229..a3795adfc083f306ff5c774d29069d4a521534ff 100644 (file)
--- a/cl_tent.c
+++ b/cl_tent.c
@@ -576,8 +576,7 @@ void CL_UpdateTEnts (void)
                        dl->die = cl.time + 0.001;
                        dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 1;
 
-                       for (i=0 ; i<3 ; i++)
-                               org[i] += dist[i]*30;
+                       VectorMA(org, 30, dist, org);
                        d -= 30;
                }
        }
index ca030ddcfba80674665393406120c2202ea08f72..45ae787e485afbac37440f36ff602054d85f9866 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[VID_GRADES*256];
+       byte    translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
 } scoreboard_t;
 
 typedef struct
@@ -346,7 +346,6 @@ void CL_TimeDemo_f (void);
 // cl_parse.c
 //
 void CL_ParseServerMessage (void);
-void CL_NewTranslation (int slot);
 
 //
 // view
index 9dad35b38306d7e40d7517a7a2331d2a6092ff69..fdc8a896ea453952910f02e30d02ac734684ff5a 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -639,31 +639,94 @@ void skypolyclear()
 }
 
 extern qboolean isATI;
+
+extern char skyname[];
+extern int solidskytexture, alphaskytexture;
 void skypolyrender()
 {
        int i, j;
        skypoly_t *p;
        skyvert_t *vert;
+       float length, speedscale;
+       vec3_t dir;
        if (currentskypoly < 1)
                return;
        // testing
 //     Con_DPrintf("skypolyrender: %i polys %i vertices\n", currentskypoly, currentskyvert);
-       glDisable(GL_TEXTURE_2D);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glDisable(GL_ALPHA_TEST);
        glDisable(GL_BLEND);
        // make sure zbuffer is enabled
        glEnable(GL_DEPTH_TEST);
        glDepthMask(1);
-       glColor3fv(fogcolor); // note: gets rendered over by sky if fog is not enabled
-       for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+       if (!fogenabled && !skyname[0]) // normal quake sky
        {
-               vert = &skyvert[p->firstvert];
-               glBegin(GL_POLYGON);
-               for (j=0 ; j<p->verts ; j++, vert++)
-                       glVertex3fv (vert->v);
-               glEnd ();
+               glColor3f(0.5f, 0.5f, 0.5f);
+               glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+               glEnable(GL_TEXTURE_2D);
+               glDisable(GL_BLEND);
+               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glBindTexture(GL_TEXTURE_2D, solidskytexture); // upper clouds
+               speedscale = realtime*8;
+               speedscale -= (int)speedscale & ~127 ;
+               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+               {
+                       vert = &skyvert[p->firstvert];
+                       glBegin(GL_POLYGON);
+                       for (j=0 ; j<p->verts ; j++, vert++)
+                       {
+                               VectorSubtract (vert->v, r_origin, dir);
+                               dir[2] *= 3;    // flatten the sphere
+
+                               length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
+                               length = sqrt (length);
+                               length = 6*63/length;
+
+                               glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128));
+                               glVertex3fv (vert->v);
+                       }
+                       glEnd ();
+               }
+               glEnable(GL_BLEND);
+               glDepthMask(0);
+               glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds
+               speedscale = realtime*16;
+               speedscale -= (int)speedscale & ~127 ;
+               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+               {
+                       vert = &skyvert[p->firstvert];
+                       glBegin(GL_POLYGON);
+                       for (j=0 ; j<p->verts ; j++, vert++)
+                       {
+                               VectorSubtract (vert->v, r_origin, dir);
+                               dir[2] *= 3;    // flatten the sphere
+
+                               length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
+                               length = sqrt (length);
+                               length = 6*63/length;
+
+                               glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128));
+                               glVertex3fv (vert->v);
+                       }
+                       glEnd ();
+               }
+               glDisable(GL_BLEND);
+               glColor3f(1,1,1);
+               glDepthMask(1);
+       }
+       else
+       {
+               glDisable(GL_TEXTURE_2D);
+               glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+               glColor3fv(fogcolor); // note: gets rendered over by skybox if fog is not enabled
+               for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++)
+               {
+                       vert = &skyvert[p->firstvert];
+                       glBegin(GL_POLYGON);
+                       for (j=0 ; j<p->verts ; j++, vert++)
+                               glVertex3fv (vert->v);
+                       glEnd ();
+               }
+               glColor3f(1,1,1);
+               glEnable(GL_TEXTURE_2D);
        }
-       glColor3f(1,1,1);
-       glEnable(GL_TEXTURE_2D);
 }
index f90e467adc45881d4e619b25814411689bd30e84..fd784385b66bfe57ddebb85dd1f72c2131d1aa89 100644 (file)
@@ -93,9 +93,7 @@ cvar_t        gl_playermip = {"gl_playermip","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_particles = {"r_particles", "1"};
 //cvar_t       r_dynamicwater = {"r_dynamicwater", "1"};
-//cvar_t       r_smokealpha = {"r_smokealpha", "0.25"};
 //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 gl_fogenable = {"gl_fogenable", "0"};
@@ -238,7 +236,7 @@ void FOG_framebegin()
                if (fog_density)
                {
                        fogenabled = true;
-                       fogdensity = -4096.0f / (fog_density * fog_density);
+                       fogdensity = -4000.0f / (fog_density * fog_density);
                        fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
                        fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
                        fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
@@ -310,8 +308,6 @@ void rmain_registercvars()
        Cvar_RegisterVariable (&brightness);
        Cvar_RegisterVariable (&gl_lightmode);
 //     Cvar_RegisterVariable (&r_dynamicwater);
-//     Cvar_RegisterVariable (&r_particles);
-//     Cvar_RegisterVariable (&r_smokealpha);
 //     Cvar_RegisterVariable (&r_dynamicbothsides);
        Cvar_RegisterVariable (&r_fullbrights);
        if (nehahra)
@@ -1558,7 +1554,7 @@ r_refdef must be set before the first call
 */
 void R_RenderView (void)
 {
-       double currtime, temptime;
+//     double currtime, temptime;
 //     if (r_norefresh.value)
 //             return;
 
@@ -1569,47 +1565,34 @@ void R_RenderView (void)
 
        FOG_framebegin();
        transpolyclear();
-       wallpolyclear();
 
-       if (r_speeds2.value)
-       {
-               currtime = Sys_FloatTime();
-               Con_Printf("render time: ");
-       }
+//     if (r_speeds2.value)
+//     {
+//             currtime = Sys_FloatTime();
+//             Con_Printf("render time: ");
+//     }
        R_Clear();
-       TIMEREPORT("R_Clear")
+//     TIMEREPORT("R_Clear")
 
        // render normal view
 
        R_SetupFrame ();
-       TIMEREPORT("R_SetupFrame")
        R_SetFrustum ();
-       TIMEREPORT("R_SetFrustum")
        R_SetupGL ();
-       TIMEREPORT("R_SetupGL")
        R_MarkLeaves ();        // done here so we know if we're in water
-       TIMEREPORT("R_MarkLeaves")
        R_DrawWorld ();         // adds static entities to the list
-       TIMEREPORT("R_DrawWorld")
        S_ExtraUpdate ();       // don't let sound get messed up if going slow
-       TIMEREPORT("S_ExtraUpdate")
+       wallpolyclear();
        R_DrawEntitiesOnList1 (); // BSP models
-       TIMEREPORT("R_DrawEntitiesOnList1")
        wallpolyrender();
-       TIMEREPORT("wallpolyrender")
        R_DrawEntitiesOnList2 (); // other models
-       TIMEREPORT("R_DrawEntitiesOnList2")
 //     R_RenderDlights ();
        R_DrawViewModel ();
-       TIMEREPORT("R_DrawViewModel")
        R_DrawParticles ();
-       TIMEREPORT("R_DrawParticles")
        transpolyrender();
-       TIMEREPORT("transpolyrender")
 
        FOG_frameend();
        GL_BlendView();
-       TIMEREPORT("GL_BlendView")
-       if (r_speeds2.value)
-               Con_Printf("\n");
+//     if (r_speeds2.value)
+//             Con_Printf("\n");
 }
index 561976633d9cdfbb3dfd1940f0d95aeaf0accc32..514d83d4991ba5c0f0b85f01a7a0e62dfe0522a5 100644 (file)
@@ -39,13 +39,15 @@ int                 active_lightmaps;
 short allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
 
 byte *lightmaps[MAX_LIGHTMAPS];
+short lightmapupdate[MAX_LIGHTMAPS][2];
 
 int lightmapalign, lightmapalignmask; // LordHavoc: NVIDIA's broken subimage fix, see BuildLightmaps for notes
 cvar_t gl_lightmapalign = {"gl_lightmapalign", "4"};
 cvar_t gl_lightmaprgba = {"gl_lightmaprgba", "1"};
 cvar_t gl_nosubimagefragments = {"gl_nosubimagefragments", "0"};
+cvar_t gl_nosubimage = {"gl_nosubimage", "0"};
 
-qboolean lightmaprgba, nosubimagefragments;
+qboolean lightmaprgba, nosubimagefragments, nosubimage;
 int lightmapbytes;
 
 qboolean skyisvisible;
@@ -55,15 +57,17 @@ void glrsurf_init()
 {
        int i;
        for (i = 0;i < MAX_LIGHTMAPS;i++)
-               lightmaps[i] = (byte *) NULL;
+               lightmaps[i] = NULL;
        Cvar_RegisterVariable(&gl_lightmapalign);
        Cvar_RegisterVariable(&gl_lightmaprgba);
        Cvar_RegisterVariable(&gl_nosubimagefragments);
+       Cvar_RegisterVariable(&gl_nosubimage);
        // check if it's the glquake minigl driver
        if (strnicmp(gl_vendor,"3Dfx",4)==0)
        if (!gl_arrays)
        {
                Cvar_SetValue("gl_nosubimagefragments", 1);
+//             Cvar_SetValue("gl_nosubimage", 1);
                Cvar_SetValue("gl_lightmode", 0);
        }
 }
@@ -300,20 +304,16 @@ void R_UpdateLightmap(msurface_t *s, int lnum)
        int smax, tmax;
        // upload the new lightmap texture fragment
        glBindTexture(GL_TEXTURE_2D, lightmap_textures + lnum);
-       if (nosubimagefragments)
+       if (nosubimage || nosubimagefragments)
        {
-               smax = (s->extents[0]>>4)+1;
-               tmax = (s->extents[1]>>4)+1;
+               if (lightmapupdate[lnum][0] > s->light_t)
+                       lightmapupdate[lnum][0] = s->light_t;
+               if (lightmapupdate[lnum][1] < (s->light_t + ((s->extents[1]>>4)+1)))
+                       lightmapupdate[lnum][1] = (s->light_t + ((s->extents[1]>>4)+1));
                if (lightmaprgba)
-               {
                        R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, s->light_t, BLOCK_WIDTH, tmax, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[s->lightmaptexturenum] + s->light_t * (BLOCK_WIDTH * 4));
-               }
                else
-               {
                        R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, s->light_t, BLOCK_WIDTH, tmax, GL_RGB , GL_UNSIGNED_BYTE, lightmaps[s->lightmaptexturenum] + s->light_t * (BLOCK_WIDTH * 3));
-               }
        }
        else
        {
@@ -406,12 +406,45 @@ float     turbsin[256] =
 #define TURBSCALE (256.0 / (2 * M_PI))
 
 
+void UploadLightmaps()
+{
+       int i;
+       if (nosubimage || nosubimagefragments)
+       {
+               for (i = 0;i < MAX_LIGHTMAPS;i++)
+               {
+                       if (lightmapupdate[i][0] < lightmapupdate[i][1])
+                       {
+                               glBindTexture(GL_TEXTURE_2D, lightmap_textures + i);
+                               if (nosubimage)
+                               {
+                                       if (lightmaprgba)
+                                               glTexImage2D(GL_TEXTURE_2D, 0, 4, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i]);
+                                       else
+                                               glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i]);
+                               }
+                               else
+                               {
+                                       if (lightmaprgba)
+                                               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lightmapupdate[i][0], BLOCK_WIDTH, lightmapupdate[i][1] - lightmapupdate[i][0], GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i] + (BLOCK_WIDTH * 4 * lightmapupdate[i][0]));
+                                       else
+                                               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lightmapupdate[i][0], BLOCK_WIDTH, lightmapupdate[i][1] - lightmapupdate[i][0], GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i] + (BLOCK_WIDTH * 3 * lightmapupdate[i][0]));
+                               }
+                       }
+                       lightmapupdate[i][0] = BLOCK_HEIGHT;
+                       lightmapupdate[i][1] = 0;
+               }
+       }
+}
+
 /*
 ================
 DrawTextureChains
 ================
 */
 extern qboolean hlbsp;
+extern void R_Sky();
+extern char skyname[];
 void DrawTextureChains (void)
 {
        int             i, j, maps;
@@ -421,6 +454,97 @@ void DrawTextureChains (void)
        float           *v;
        float           os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(realtime * TURBSCALE + 96.0) & 255];
 
+       // first the sky
+       skypolyclear();
+       for (j = 0;j < cl.worldmodel->numtextures;j++)
+       {
+               if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
+                       continue;
+               // LordHavoc: decide the render type only once, because the surface properties were determined by texture anyway
+               // subdivided water surface warp
+               if (s->flags & SURF_DRAWSKY)
+               {
+                       cl.worldmodel->textures[j]->texturechain = NULL;
+                       t = R_TextureAnimation (cl.worldmodel->textures[j]);
+                       skyisvisible = true;
+                       if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
+                       {
+                               for (;s;s = s->texturechain)
+                               {
+                                       for (p=s->polys ; p ; p=p->next)
+                                       {
+                                               if (currentskypoly < MAX_SKYPOLYS && currentskyvert + p->numverts <= MAX_SKYVERTS)
+                                               {
+                                                       skypoly[currentskypoly].firstvert = currentskyvert;
+                                                       skypoly[currentskypoly++].verts = p->numverts;
+                                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
+                                                       {
+                                                               skyvert[currentskyvert].v[0] = v[0];
+                                                               skyvert[currentskyvert].v[1] = v[1];
+                                                               skyvert[currentskyvert++].v[2] = v[2];
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       skypolyrender(); // fogged sky polys, affects depth
+
+       if (skyname[0] && skyisvisible && !fogenabled)
+               R_Sky(); // does not affect depth, draws over the sky polys
+
+       // then walls
+       wallpolyclear();
+       for (j = 0;j < cl.worldmodel->numtextures;j++)
+       {
+               if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
+                       continue;
+               if (!(s->flags & SURF_DRAWTURB))
+               {
+                       cl.worldmodel->textures[j]->texturechain = NULL;
+                       t = R_TextureAnimation (cl.worldmodel->textures[j]);
+                       c_brush_polys++;
+                       for (;s;s = s->texturechain)
+                       {
+                               if (currentwallpoly < MAX_WALLPOLYS && currentwallvert < MAX_WALLVERTS && (currentwallvert + s->polys->numverts) <= MAX_WALLVERTS)
+                               {
+                                       // check for lightmap modification
+//                                     if (r_dynamic.value)
+//                                     {
+                                               if (s->dlightframe == r_framecount || s->cached_dlight || lighthalf != s->cached_lighthalf) // dynamic this frame or previously, or lighthalf changed
+                                                       R_UpdateLightmap(s, s->lightmaptexturenum);
+                                               else
+                                                       for (maps = 0 ; maps < MAXLIGHTMAPS && s->styles[maps] != 255 ; maps++)
+                                                               if (d_lightstylevalue[s->styles[maps]] != s->cached_light[maps])
+                                                               {
+                                                                       R_UpdateLightmap(s, s->lightmaptexturenum);
+                                                                       break;
+                                                               }
+//                                     }
+                                       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++].verts = s->polys->numverts;
+                                       for (i = 0,v = s->polys->verts[0];i<s->polys->numverts;i++, v += VERTEXSIZE)
+                                       {
+                                               wallvert[currentwallvert].vert[0] = v[0];
+                                               wallvert[currentwallvert].vert[1] = v[1];
+                                               wallvert[currentwallvert].vert[2] = v[2];
+                                               wallvert[currentwallvert].s = v[3];
+                                               wallvert[currentwallvert].t = v[4];
+                                               wallvert[currentwallvert].u = v[5];
+                                               wallvert[currentwallvert++].v = v[6];
+                                       }
+                               }
+                       }
+               }
+       }
+       UploadLightmaps();
+       wallpolyrender();
+
+       // then water (water gets diverted to transpoly list)
        for (j = 0;j < cl.worldmodel->numtextures;j++)
        {
                if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
@@ -608,68 +732,6 @@ void DrawTextureChains (void)
                                }
                        }
                }
-               else if (s->flags & SURF_DRAWSKY)
-               {
-                       skyisvisible = true;
-                       if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
-                       {
-                               for (;s;s = s->texturechain)
-                               {
-                                       for (p=s->polys ; p ; p=p->next)
-                                       {
-                                               if (currentskypoly < MAX_SKYPOLYS && currentskyvert + p->numverts <= MAX_SKYVERTS)
-                                               {
-                                                       skypoly[currentskypoly].firstvert = currentskyvert;
-                                                       skypoly[currentskypoly++].verts = p->numverts;
-                                                       for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
-                                                       {
-                                                               skyvert[currentskyvert].v[0] = v[0];
-                                                               skyvert[currentskyvert].v[1] = v[1];
-                                                               skyvert[currentskyvert++].v[2] = v[2];
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-               else // normal wall
-               {
-                       c_brush_polys++;
-                       for (;s;s = s->texturechain)
-                       {
-                               if (currentwallpoly < MAX_WALLPOLYS && currentwallvert < MAX_WALLVERTS && (currentwallvert + s->polys->numverts) <= MAX_WALLVERTS)
-                               {
-                                       // check for lightmap modification
-//                                     if (r_dynamic.value)
-//                                     {
-                                               if (s->dlightframe == r_framecount || s->cached_dlight || lighthalf != s->cached_lighthalf) // dynamic this frame or previously, or lighthalf changed
-                                                       R_UpdateLightmap(s, s->lightmaptexturenum);
-                                               else
-                                                       for (maps = 0 ; maps < MAXLIGHTMAPS && s->styles[maps] != 255 ; maps++)
-                                                               if (d_lightstylevalue[s->styles[maps]] != s->cached_light[maps])
-                                                               {
-                                                                       R_UpdateLightmap(s, s->lightmaptexturenum);
-                                                                       break;
-                                                               }
-//                                     }
-                                       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++].verts = s->polys->numverts;
-                                       for (i = 0,v = s->polys->verts[0];i<s->polys->numverts;i++, v += VERTEXSIZE)
-                                       {
-                                               wallvert[currentwallvert].vert[0] = v[0];
-                                               wallvert[currentwallvert].vert[1] = v[1];
-                                               wallvert[currentwallvert].vert[2] = v[2];
-                                               wallvert[currentwallvert].s = v[3];
-                                               wallvert[currentwallvert].t = v[4];
-                                               wallvert[currentwallvert].u = v[5];
-                                               wallvert[currentwallvert++].v = v[6];
-                                       }
-                               }
-                       }
-               }
        }
 }
 
@@ -932,6 +994,7 @@ e->angles[0] = -e->angles[0];       // stupid quake bug
                        }
                }
        }
+       UploadLightmaps();
 }
 
 /*
@@ -1179,7 +1242,6 @@ loc0:
 R_DrawWorld
 =============
 */
-extern void R_Sky();
 void R_DrawWorld (void)
 {
        entity_t        ent;
@@ -1195,20 +1257,14 @@ void R_DrawWorld (void)
        currententity = &ent;
 
        softwaretransformidentity(); // LordHavoc: clear transform
-       skypolyclear();
        skyisvisible = false;
 
        if (cl.worldmodel)
                R_WorldNode ();
 
-       DrawTextureChains ();
-
        glClear (GL_DEPTH_BUFFER_BIT);
 
-       skypolyrender(); // fogged sky polys, affects depth
-
-       if (skyisvisible && !fogenabled)
-               R_Sky(); // does not affect depth, draws over the sky polys
+       DrawTextureChains ();
 
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1309,11 +1365,13 @@ int AllocBlock (int w, int h, int *x, int *y)
                if (best + h > BLOCK_HEIGHT)
                        continue;
 
-               if (gl_nosubimagefragments.value)
+               if (nosubimagefragments || nosubimage)
+               {
                        if (!lightmaps[texnum])
                                lightmaps[texnum] = calloc(BLOCK_WIDTH*BLOCK_HEIGHT*4, 1);
+               }
                // LordHavoc: clear texture to blank image, fragments are uploaded using subimage
-               if (!allocated[texnum][0])
+               else if (!allocated[texnum][0])
                {
                        byte blank[BLOCK_WIDTH*BLOCK_HEIGHT*3];
                        memset(blank, 0, sizeof(blank));
@@ -1475,33 +1533,19 @@ void GL_CreateSurfaceLightmap (msurface_t *surf)
        tmax = (surf->extents[1]>>4)+1;
 
        surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
+       if (nosubimage || nosubimagefragments)
+               return;
        glBindTexture(GL_TEXTURE_2D, lightmap_textures + surf->lightmaptexturenum);
-       if (nosubimagefragments)
+       smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask;
+       if (lightmaprgba)
        {
-               if (lightmaprgba)
-               {
-                       R_BuildLightMap (surf, lightmaps[surf->lightmaptexturenum] + (surf->light_t * BLOCK_WIDTH + surf->light_s) * 4, BLOCK_WIDTH * 4);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, surf->light_t, BLOCK_WIDTH, tmax, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[surf->lightmaptexturenum] + surf->light_t * (BLOCK_WIDTH * 4));
-               }
-               else
-               {
-                       R_BuildLightMap (surf, lightmaps[surf->lightmaptexturenum] + (surf->light_t * BLOCK_WIDTH + surf->light_s) * 3, BLOCK_WIDTH * 3);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, surf->light_t, BLOCK_WIDTH, tmax, GL_RGB , GL_UNSIGNED_BYTE, lightmaps[surf->lightmaptexturenum] + surf->light_t * (BLOCK_WIDTH * 3));
-               }
+               R_BuildLightMap (surf, templight, smax * 4);
+               glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
        }
        else
        {
-               smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask;
-               if (lightmaprgba)
-               {
-                       R_BuildLightMap (surf, templight, smax * 4);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
-               }
-               else
-               {
-                       R_BuildLightMap (surf, templight, smax * 3);
-                       glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
-               }
+               R_BuildLightMap (surf, templight, smax * 3);
+               glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
        }
 }
 
@@ -1528,6 +1572,11 @@ void GL_BuildLightmaps (void)
        else
                nosubimagefragments = 0;
 
+       if (gl_nosubimage.value)
+               nosubimage = 1;
+       else
+               nosubimage = 0;
+
        if (gl_lightmaprgba.value)
        {
                lightmaprgba = true;
@@ -1551,7 +1600,7 @@ void GL_BuildLightmaps (void)
                lightmapalign <<= 1;
        gl_lightmapalign.value = lightmapalign;
        lightmapalignmask = ~(lightmapalign - 1);
-       if (nosubimagefragments)
+       if (nosubimagefragments || nosubimage)
        {
                lightmapalign = 1;
                lightmapalignmask = ~0;
@@ -1582,5 +1631,27 @@ void GL_BuildLightmaps (void)
                        BuildSurfaceDisplayList (m->surfaces + i);
                }
        }
+
+       if (nosubimage || nosubimagefragments)
+       {
+               if (gl_mtexable)
+                       qglSelectTexture(gl_mtex_enum+1);
+               for (i = 0;i < MAX_LIGHTMAPS;i++)
+               {
+                       if (!allocated[i][0])
+                               break;
+                       lightmapupdate[i][0] = BLOCK_HEIGHT;
+                       lightmapupdate[i][1] = 0;
+                       glBindTexture(GL_TEXTURE_2D, lightmap_textures + i);
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+                       if (lightmaprgba)
+                               glTexImage2D(GL_TEXTURE_2D, 0, 4, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i]);
+                       else
+                               glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i]);
+               }
+               if (gl_mtexable)
+                       qglSelectTexture(gl_mtex_enum+0);
+       }
 }
 
index 1dd2b28baf5dc388419804583344b0fd899d73e4..791001830d4c5417e150f5cb2150a50e112a993f 100644 (file)
--- a/gl_warp.c
+++ b/gl_warp.c
@@ -304,6 +304,7 @@ void R_SkyBox()
        glEnd();
 }
 
+/*
 float skydomeouter[33*33*3];
 float skydomeinner[33*33*3];
 unsigned short skydomeindices[32*66];
@@ -403,15 +404,18 @@ void R_SkyDome()
        skydome(skydomeinner, speedscale, 1.0 / 128.0);
        glDisable (GL_BLEND);
 }
+*/
 
 void R_Sky()
 {
+       if (!skyname[0])
+               return;
        glDisable(GL_DEPTH_TEST);
        glDepthMask(0);
-       if (skyname[0])
+//     if (skyname[0])
                R_SkyBox();
-       else // classic quake sky
-               R_SkyDome();
+//     else // classic quake sky
+//             R_SkyDome();
        glDepthMask(1);
        glEnable (GL_DEPTH_TEST);
        glColor3f (1,1,1);
index d77b35805831be192ebd5cea7879f48df9704723..237c6caae8d974de42037cf18681b7ef54241c33 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -142,6 +142,7 @@ typedef struct particle_s
        int                     texnum;
        float           alpha; // 0-255
        float           time2; // used for various things (snow fluttering, for example)
+       vec3_t          vel2; // used for snow fluttering (base velocity, wind for instance)
 } particle_t;
 
 
index 97372b39ed0624ebd1f6c7275969cb4336a9b543..841ca3e86d883ff283d584a76db034c7757be8f8 100644 (file)
@@ -32,15 +32,18 @@ Host_Quit_f
 ==================
 */
 
-extern void M_Menu_Quit_f (void);
+// LordHavoc: didn't like it asking me if I wanted to quit
+//extern void M_Menu_Quit_f (void);
 
 void Host_Quit_f (void)
 {
+       /*
        if (key_dest != key_console && cls.state != ca_dedicated)
        {
                M_Menu_Quit_f ();
                return;
        }
+       */
        CL_Disconnect ();
        Host_ShutdownServer(false);             
 
index 19d9a808eb5305bcf23db4037e674db4502fe24c..0fb1067e3150325a825724f22663b63de0b8708a 100644 (file)
--- a/mathlib.h
+++ b/mathlib.h
@@ -99,4 +99,6 @@ void BoxOnPlaneSideClassify(struct mplane_s *p);
 //             BoxOnPlaneSide( (emins), (emaxs), (p)))
 
 #define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal))
-#define PlaneDiff(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] - (plane)->dist : DotProduct((point), (plane)->normal) - (plane)->dist)
\ No newline at end of file
+#define PlaneDiff(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] - (plane)->dist : DotProduct((point), (plane)->normal) - (plane)->dist)
+
+#define lhrandom(MIN,MAX) ((rand() & 32767) * (((MAX)-(MIN)) * (1.0f / 32767.0f)) + (MIN))
index 4ea3403bb2972390cb017d1ba74d063a98a1e34e..523c5a8daea0fbc19fa2368cc7ff950c463f4607 100644 (file)
@@ -34,7 +34,7 @@ aliashdr_t    *pheader;
 typedef struct
 {
        int v[3];
-       vec3_t n;
+       vec3_t normal;
 } temptris_t;
 temptris_t *temptris;
 //stvert_t     stverts[MAXALIASVERTS];
@@ -57,7 +57,7 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
        struct
        {
                vec3_t v;
-               vec3_t n;
+               vec3_t normal;
                int count;
        } tempvert[MD2MAX_VERTS];
        temptris_t *tris;
@@ -68,7 +68,7 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
                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].n[0] = tempvert[i].n[1] = tempvert[i].n[2] = 0;
+               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];
@@ -84,12 +84,12 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
        {
                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->n);
-               VectorNormalize(tris->n);
+               CrossProduct(t1, t2, tris->normal);
+               VectorNormalize(tris->normal);
                // add surface normal to vertices
                for (j = 0;j < 3;j++)
                {
-                       VectorAdd(tris->n, tempvert[tris->v[j]].n, tempvert[tris->v[j]].n);
+                       VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
                        tempvert[tris->v[j]].count++;
                }
                tris++;
@@ -97,10 +97,10 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran
        // average normals and write out 1.7bit format
        for (i = 0;i < pheader->numtris;i++)
        {
-               VectorNormalize(tempvert[i].n);
-               out[i].n[0] = (signed char) (tempvert[i].n[0] * 127.0);
-               out[i].n[1] = (signed char) (tempvert[i].n[1] * 127.0);
-               out[i].n[2] = (signed char) (tempvert[i].n[2] * 127.0);
+               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);
        }
 }
 
index 5c822d9b8f82d59f27c5a28bdc957f99e7851ece..540494a8c83ab5d74dcc4ee5105fea3af260be66 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#define MAX_PARTICLES                  2048    // default max # of particles at one
+#define MAX_PARTICLES                  4096    // default max # of particles at one
                                                                                //  time
 #define ABSOLUTE_MIN_PARTICLES 512             // no fewer than this no matter what's
                                                                                //  on the command line
@@ -43,8 +43,7 @@ int                   r_numparticles;
 
 vec3_t                 r_pright, r_pup, r_ppn;
 
-//extern cvar_t r_particles/*, r_smoke*/, r_smokealpha;
-//cvar_t r_smokecolor = {"r_smokecolor", "0"};
+cvar_t r_particles = {"r_particles", "1", true};
 
 void fractalnoise(char *noise, int size);
 void fractalnoise_zeroedge(char *noise, int size);
@@ -53,15 +52,15 @@ void R_InitParticleTexture (void)
 {
        int             x,y,d;
        float   dx, dy, dz, f, dot;
-       byte    data[64][64][4], noise1[64][64], noise2[64][64];
+       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<64 ; x++)
+       for (x=0 ; x<32 ; x++)
        {
-               for (y=0 ; y<64 ; y++)
+               for (y=0 ; y<32 ; y++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        dx = x - 16;
@@ -71,7 +70,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
 
@@ -79,10 +78,10 @@ void R_InitParticleTexture (void)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
 
-       fractalnoise(&noise1[0][0], 64);
-       fractalnoise(&noise2[0][0], 64);
-       for (y = 0;y < 64;y++)
-               for (x = 0;x < 64;x++)
+       fractalnoise(&noise1[0][0], 32);
+       fractalnoise(&noise2[0][0], 32);
+       for (y = 0;y < 32;y++)
+               for (x = 0;x < 32;x++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = (noise1[y][x] >> 1) + 128;
                        dx = x - 16;
@@ -96,7 +95,7 @@ void R_InitParticleTexture (void)
        /*
        for (x=0 ; x<34 ; x+=2)
                for (y=0 ; y<34 ; y+=2)
-                       data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%64)+192;
+                       data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%32)+192;
        for (x=0 ; x<32 ; x+=2)
                for (y=0 ; y<32 ; y+=2)
                {
@@ -104,11 +103,11 @@ void R_InitParticleTexture (void)
                        data[y+1][x  ][0] = data[y+1][x  ][1] = data[y+1][x  ][2] = (int) (data[y  ][x  ][0] + data[y+2][x  ][0]) >> 1;
                        data[y+1][x+1][0] = data[y+1][x+1][1] = data[y+1][x+1][2] = (int) (data[y  ][x  ][0] + data[y  ][x+2][0] + data[y+2][x  ][0] + data[y+2][x+2][0]) >> 2;
                }
-       for (x=0 ; x<64 ; x++)
+       for (x=0 ; x<32 ; x++)
        {
-               for (y=0 ; y<64 ; y++)
+               for (y=0 ; y<32 ; y++)
                {
-                       //data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%192)+64;
+                       //data[y][x][0] = data[y][x][1] = data[y][x][2] = (rand()%192)+32;
                        dx = x - 16;
                        dy = y - 16;
                        d = (255 - (dx*dx+dy*dy));
@@ -119,15 +118,15 @@ void R_InitParticleTexture (void)
        */
        smokeparticletexture = texture_extension_number++;
        glBindTexture(GL_TEXTURE_2D, smokeparticletexture);
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
 
-       fractalnoise(&noise1[0][0], 64);
-       fractalnoise(&noise2[0][0], 64);
-       for (y = 0;y < 64;y++)
-               for (x = 0;x < 64;x++)
+       fractalnoise(&noise1[0][0], 32);
+       fractalnoise(&noise2[0][0], 32);
+       for (y = 0;y < 32;y++)
+               for (x = 0;x < 32;x++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = (noise1[y][x] >> 1) + 128;
                        dx = x - 16;
@@ -140,7 +139,7 @@ void R_InitParticleTexture (void)
 
        bloodcloudparticletexture = texture_extension_number++;
        glBindTexture(GL_TEXTURE_2D, bloodcloudparticletexture);
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
@@ -148,9 +147,9 @@ void R_InitParticleTexture (void)
        flareparticletexture = texture_extension_number++;
     glBindTexture(GL_TEXTURE_2D, flareparticletexture);
 
-       for (x=0 ; x<64 ; x++)
+       for (x=0 ; x<32 ; x++)
        {
-               for (y=0 ; y<64 ; y++)
+               for (y=0 ; y<32 ; y++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        dx = x - 16;
@@ -160,7 +159,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
 
@@ -170,9 +169,9 @@ void R_InitParticleTexture (void)
        rainparticletexture = texture_extension_number++;
     glBindTexture(GL_TEXTURE_2D, rainparticletexture);
 
-       for (x=0 ; x<64 ; x++)
+       for (x=0 ; x<32 ; x++)
        {
-               for (y=0 ; y<64 ; y++)
+               for (y=0 ; y<32 ; y++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        if (y < 24) // stretch the upper half to make a raindrop
@@ -191,7 +190,7 @@ void R_InitParticleTexture (void)
                        data[y][x][3] = (byte) d;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
 
@@ -203,9 +202,9 @@ void R_InitParticleTexture (void)
 
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
-       for (x=0 ; x<64 ; x++)
+       for (x=0 ; x<32 ; x++)
        {
-               for (y=0 ; y<64 ; y++)
+               for (y=0 ; y<32 ; y++)
                {
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
                        dx = x * (1.0 / 16.0) - 1.0;
@@ -230,15 +229,15 @@ void R_InitParticleTexture (void)
                                        f += ((dot *  2) - 1);
                                else if (dot < -0.5) // exterior reflection
                                        f += ((dot * -2) - 1);
-                               f *= 255;
+                               f *= 64;
                                f = bound(0, f, 255);
-                               data[y][x][3] = (byte) d;
+                               data[y][x][3] = (byte) f;
                        }
                        else
                                data[y][x][3] = 0;
                }
        }
-       glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       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);
 
@@ -270,7 +269,7 @@ void R_InitParticles (void)
 
        particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
 
-//     Cvar_RegisterVariable (&r_smokecolor);
+       Cvar_RegisterVariable (&r_particles);
        R_InitParticleTexture ();
 }
 
@@ -297,7 +296,7 @@ void R_EntityParticles (entity_t *ent)
        float           sr, sp, sy, cr, cp, cy;
        vec3_t          forward;
        float           dist;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        
        dist = 64;
        count = 50;
@@ -452,7 +451,7 @@ void R_ParticleExplosion (vec3_t org, int smoke)
 {
        int                     i, j;
        particle_t      *p;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        
        for (i=0 ; i<1024 ; i++)
        {
@@ -464,7 +463,7 @@ void R_ParticleExplosion (vec3_t org, int smoke)
                active_particles = p;
 
                p->texnum = flareparticletexture;
-               p->scale = 4+(rand()&7);
+               p->scale = lhrandom(2,5);
                p->alpha = rand()&255;
                p->die = cl.time + 5;
                p->color = ramp1[0];
@@ -497,7 +496,7 @@ void R_ParticleExplosion (vec3_t org, int smoke)
                        active_particles = p;
 
                        p->texnum = smokeparticletexture;
-                       p->scale = 24;
+                       p->scale = 12;
                        p->alpha = 80;
                        p->die = cl.time + 2;
                        p->type = pt_smoke;
@@ -522,7 +521,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        int                     i, j;
        particle_t      *p;
        int                     colorMod = 0;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i=0; i<512; i++)
        {
@@ -534,7 +533,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
                active_particles = p;
 
                p->texnum = flareparticletexture;
-               p->scale = 8;
+               p->scale = 4;
                p->alpha = 255;
                p->die = cl.time + 0.3;
                p->color = colorStart + (colorMod % colorLength);
@@ -559,7 +558,7 @@ void R_BlobExplosion (vec3_t org)
 {
        int                     i, j;
        particle_t      *p;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        
        for (i=0 ; i<1024 ; i++)
        {
@@ -571,7 +570,7 @@ void R_BlobExplosion (vec3_t org)
                active_particles = p;
 
                p->texnum = flareparticletexture;
-               p->scale = 8;
+               p->scale = 4;
                p->alpha = 255;
                p->die = cl.time + 1 + (rand()&8)*0.05;
 
@@ -608,7 +607,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
 {
        int                     i, j;
        particle_t      *p;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        
        for (i=0 ; i<count ; i++)
        {
@@ -622,7 +621,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                if (count == 1024)
                {       // rocket explosion
                        p->texnum = flareparticletexture;
-                       p->scale = 8;
+                       p->scale = 4;
                        p->alpha = 255;
                        p->die = cl.time + 5;
                        p->color = ramp1[0];
@@ -649,7 +648,7 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                else
                {
                        p->texnum = flareparticletexture;
-                       p->scale = 8;
+                       p->scale = 4;
                        p->alpha = 255;
                        p->die = cl.time + 0.1*(rand()%5);
                        p->color = (color&~7) + (rand()&7);
@@ -674,7 +673,7 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
 {
        int                     i, j;
        particle_t      *p;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        if (!free_particles)
                return;
@@ -685,7 +684,7 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
        if (type == 0) // sparks
        {
                p->texnum = smokeparticletexture;
-               p->scale = 20;
+               p->scale = 10;
                p->alpha = 64;
                p->color = (rand()&3)+12;
                p->type = pt_bulletpuff;
@@ -696,7 +695,7 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
        else // blood
        {
                p->texnum = bloodcloudparticletexture;
-               p->scale = 24;
+               p->scale = 12;
                p->alpha = 128;
                p->color = (rand()&3)+68;
                p->type = pt_bloodcloud;
@@ -715,7 +714,7 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count, int type)
                active_particles = p;
 
                p->texnum = flareparticletexture;
-               p->scale = 5;
+               p->scale = 2;
                p->alpha = 255;
                p->die = cl.time + 0.0625 * (rand()&15);
                /*
@@ -753,7 +752,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        vec3_t          diff;
        vec3_t          center;
        vec3_t          velscale;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        VectorSubtract(maxs, mins, diff);
        center[0] = (mins[0] + maxs[0]) * 0.5;
@@ -773,7 +772,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
                active_particles = p;
 
                p->texnum = bloodcloudparticletexture;
-               p->scale = 24;
+               p->scale = 12;
                p->alpha = 96 + (rand()&63);
                p->die = cl.time + 2; //0.015625 * (rand()%128);
                p->type = pt_fadespark;
@@ -793,7 +792,7 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        particle_t      *p;
        vec3_t          diff;
        float           t;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
        if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
@@ -810,7 +809,7 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                active_particles = p;
 
                p->texnum = flareparticletexture;
-               p->scale = 12;
+               p->scale = 6;
                p->alpha = 255;
                p->die = cl.time + 1 + (rand()&15)*0.0625;
                if (gravity)
@@ -837,7 +836,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        vec3_t          org;
        vec3_t          vel;
        float           t, z;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
        if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;}
        if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;}
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
@@ -873,7 +872,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                org[1] = diff[1] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[1];
                org[2] = z;
 
-               p->scale = 6;
+               p->scale = 1.5;
                p->alpha = 255;
                p->die = t;
                if (type == 1)
@@ -889,6 +888,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                p->color = colorbase + (rand()&3);
                VectorCopy(org, p->org);
                VectorCopy(vel, p->vel);
+               VectorCopy(vel, p->vel2);
        }
 }
 
@@ -905,7 +905,7 @@ void R_LavaSplash (vec3_t org)
        particle_t      *p;
        float           vel;
        vec3_t          dir;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i=-16 ; i<16 ; i+=2)
                for (j=-16 ; j<16 ; j+=2)
@@ -919,8 +919,8 @@ void R_LavaSplash (vec3_t org)
                                active_particles = p;
                
                                p->texnum = flareparticletexture;
-                               p->scale = 24;
-                               p->alpha = 255;
+                               p->scale = 10;
+                               p->alpha = 128;
                                p->die = cl.time + 2 + (rand()&31) * 0.02;
                                p->color = 224 + (rand()&7);
                                p->type = pt_slowgrav;
@@ -950,7 +950,7 @@ void R_TeleportSplash (vec3_t org)
        int                     i, j, k;
        particle_t      *p;
 //     vec3_t          dir;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        /*
        for (i=-16 ; i<16 ; i+=4)
@@ -997,7 +997,7 @@ void R_TeleportSplash (vec3_t org)
                                active_particles = p;
                
                                p->texnum = flareparticletexture;
-                               p->scale = 8;
+                               p->scale = 4;
                                p->alpha = (1 + rand()&7) * 32;
                                p->die = cl.time + 5;
                                p->color = 254; //8 + (rand()&7);
@@ -1020,7 +1020,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        int                     j, contents, bubbles;
        particle_t      *p;
        static int      tracercount;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        t = cl.oldtime;
        nt = cl.time;
@@ -1061,14 +1061,11 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 1: // grenade trail
                                if (bubbles)
                                {
-                                       dec = 0.01f;
+                                       dec = 0.005f;
                                        p->texnum = bubbleparticletexture;
-                                       p->scale = 6+(rand()&3);
+                                       p->scale = lhrandom(1,2);
                                        p->alpha = 255;
-//                                     if (r_smokecolor.value)
-//                                             p->color = r_smokecolor.value;
-//                                     else
-                                               p->color = (rand()&3)+12;
+                                       p->color = (rand()&3)+12;
                                        p->type = pt_bubble;
                                        p->die = cl.time + 2;
                                        for (j=0 ; j<3 ; j++)
@@ -1079,16 +1076,13 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                }
                                else
                                {
-                                       dec = 0.03f;
+                                       dec = 0.02f;
                                        p->texnum = smokeparticletexture;
-                                       p->scale = 12+(rand()&7);
+                                       p->scale = lhrandom(4, 7);
                                        p->alpha = 64 + (rand()&31);
-//                                     if (r_smokecolor.value)
-//                                             p->color = r_smokecolor.value;
-//                                     else
-                                               p->color = (rand()&3)+12;
+                                       p->color = (rand()&3)+12;
                                        p->type = pt_smoke;
-                                       p->die = cl.time + 2;
+                                       p->die = cl.time + 10000;
                                        VectorCopy(start, p->org);
                                }
                                break;
@@ -1097,7 +1091,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 1: // smoke smoke
                                dec = 0.016f;
                                p->texnum = smokeparticletexture;
-                               p->scale = 12+rand()&7;
+                               p->scale = lhrandom(6,9);
                                p->alpha = 64;
                                if (r_smokecolor.value)
                                        p->color = r_smokecolor.value;
@@ -1112,7 +1106,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 2: // blood
                                dec = 0.03f;
                                p->texnum = bloodcloudparticletexture;
-                               p->scale = 20+(rand()&7);
+                               p->scale = lhrandom(8, 12);
                                p->alpha = 255;
                                p->color = (rand()&3)+68;
                                p->type = pt_bloodcloud;
@@ -1128,7 +1122,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 5: // tracer
                                dec = 0.01f;
                                p->texnum = flareparticletexture;
-                               p->scale = 4;
+                               p->scale = 2;
                                p->alpha = 255;
                                p->die = cl.time + 0.2; //5;
                                p->type = pt_static;
@@ -1155,7 +1149,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 4: // slight blood
                                dec = 0.03f; // sparse trail
                                p->texnum = bloodcloudparticletexture;
-                               p->scale = 20+(rand()&7);
+                               p->scale = lhrandom(8,12);
                                p->alpha = 255;
                                p->color = (rand()&3)+68;
                                p->type = pt_fadespark2;
@@ -1170,7 +1164,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 6: // voor trail
                                dec = 0.05f; // sparse trail
                                p->texnum = flareparticletexture;
-                               p->scale = 20+(rand()&7);
+                               p->scale = lhrandom(4, 8);
                                p->alpha = 255;
                                p->color = 9*16 + 8 + (rand()&3);
                                p->type = pt_fadespark2;
@@ -1185,11 +1179,11 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 7: // Nehahra smoke tracer
                                dec = 0.14f;
                                p->texnum = smokeparticletexture;
-                               p->scale = 12+(rand()&7);
+                               p->scale = lhrandom(6, 10);
                                p->alpha = 64;
                                p->color = (rand()&3)+12;
                                p->type = pt_smoke;
-                               p->die = cl.time + 1;
+                               p->die = cl.time + 10000;
                                for (j=0 ; j<3 ; j++)
                                        p->org[j] = start[j] + ((rand()&3)-2);
                                break;
@@ -1208,7 +1202,7 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        float           len;
        particle_t      *p;
        static int      tracercount;
-//     if (!r_particles.value) return; // LordHavoc: particles are optional
+       if (!r_particles.value) return; // LordHavoc: particles are optional
 
        VectorSubtract (end, start, vec);
        len = VectorNormalizeLength (vec);
@@ -1226,7 +1220,7 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
                VectorCopy (vec3_origin, p->vel);
 
                p->texnum = flareparticletexture;
-               p->scale = 16;
+               p->scale = 8;
                p->alpha = 192;
                p->color = color;
                p->type = pt_smoke;
@@ -1240,7 +1234,6 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
 }
 
 
-//extern qboolean isG200, isATI, isRagePro;
 extern qboolean lighthalf;
 
 /*
@@ -1253,7 +1246,7 @@ extern    cvar_t  sv_gravity;
 void R_DrawParticles (void)
 {
        particle_t              *p, *kill;
-       int                             i, /*texnum, */r,g,b,a;
+       int                             i, r,g,b,a;
        float                   grav, grav1, time1, time2, time3, dvel, frametime, scale, scale2;
        byte                    *color24;
        vec3_t                  up, right, uprightangles, forward2, up2, right2, v;
@@ -1262,23 +1255,6 @@ void R_DrawParticles (void)
        if (!active_particles)
                return;
 
-       /*
-       texnum = particletexture;
-    glBindTexture(GL_TEXTURE_2D, texnum);
-       glEnable (GL_BLEND);
-       // LordHavoc: Matrox G200 cards can't handle per pixel alpha at all...
-       // and ATI Rage Pro can't modulate a per pixel alpha texture
-       if (isG200 || isRagePro)
-               glEnable(GL_ALPHA_TEST);
-       else
-               glDisable(GL_ALPHA_TEST);
-       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       glDepthMask(0); // disable zbuffer updates
-       glShadeModel(GL_FLAT);
-       glBegin (GL_TRIANGLES);
-       */
-
        VectorScale (vup, 1.5, up);
        VectorScale (vright, 1.5, right);
 
@@ -1328,51 +1304,7 @@ void R_DrawParticles (void)
                VectorSubtract(p->org, r_refdef.vieworg, v);
                if (DotProduct(v, v) >= 256.0f)
                {
-                       scale = p->scale * -0.25;scale2 = p->scale * 0.75;
-                       /*
-                       if (p->texnum != texnum)
-                       {
-                               texnum = p->texnum;
-                               glEnd();
-                               glBindTexture(GL_TEXTURE_2D, texnum);
-                               glBegin(GL_TRIANGLES);
-                       }
-                       if (lighthalf)
-                       {
-                               color24 = (byte *)&d_8to24table[(int)p->color];
-                               if (p->texnum == smokeparticletexture)
-                                       glColor4ub((byte) (color24[0] >> 1), (byte) (color24[1] >> 1), (byte) (color24[2] >> 1), (byte) (p->alpha*r_smokealpha.value));
-                               else
-                                       glColor4ub((byte) (color24[0] >> 1), (byte) (color24[1] >> 1), (byte) (color24[2] >> 1), (byte) p->alpha);
-                       }
-                       else
-                       {
-                               color24 = (byte *) &d_8to24table[(int)p->color];
-                               if (p->texnum == smokeparticletexture)
-                                       glColor4ub(color24[0], color24[1], color24[2], (byte) (p->alpha*r_smokealpha.value));
-                               else
-                                       glColor4ub(color24[0], color24[1], color24[2], (byte) p->alpha);
-                       }
-                       if (p->texnum == rainparticletexture) // rain streak
-                       {
-                               glTexCoord2f (0,0);
-                               glVertex3f (p->org[0] + right2[0]*scale , p->org[1] + right2[1]*scale , p->org[2] + right2[2]*scale );
-                               glTexCoord2f (1,0);
-                               glVertex3f (p->org[0] + right2[0]*scale , p->org[1] + right2[1]*scale , p->org[2] + right2[2]*scale );
-                               glTexCoord2f (0,1);
-                               glVertex3f (p->org[0] + right2[0]*scale2, p->org[1] + right2[1]*scale2, p->org[2] + right2[2]*scale2);
-                       }
-                       else
-                       {
-                               glTexCoord2f (0,0);
-                               // LordHavoc: centered particle sprites
-                               glVertex3f (p->org[0] + up[0]*scale  + right[0]*scale , p->org[1] + up[1]*scale  + right[1]*scale , p->org[2] + up[2]*scale  + right[2]*scale );
-                               glTexCoord2f (1,0);
-                               glVertex3f (p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale );
-                               glTexCoord2f (0,1);
-                               glVertex3f (p->org[0] + up[0]*scale  + right[0]*scale2, p->org[1] + up[1]*scale  + right[1]*scale2, p->org[2] + up[2]*scale  + right[2]*scale2);
-                       }
-                       */
+                       scale = p->scale * -0.5;scale2 = p->scale * 0.5;
                        color24 = (byte *) &d_8to24table[(int)p->color];
                        r = color24[0];
                        g = color24[1];
@@ -1387,15 +1319,17 @@ void R_DrawParticles (void)
                        transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA);
                        if (p->texnum == rainparticletexture) // rain streak
                        {
-                               transpolyvert(p->org[0] + right2[0]*scale , p->org[1] + right2[1]*scale , p->org[2] + right2[2]*scale , 0,0,r,g,b,a);
-                               transpolyvert(p->org[0] + right2[0]*scale , p->org[1] + right2[1]*scale , p->org[2] + right2[2]*scale , 1,0,r,g,b,a);
-                               transpolyvert(p->org[0] + right2[0]*scale2, p->org[1] + right2[1]*scale2, p->org[2] + right2[2]*scale2, 0,1,r,g,b,a);
+                               transpolyvert(p->org[0] + up2[0]*scale  + right2[0]*scale , p->org[1] + up2[1]*scale  + right2[1]*scale , p->org[2] + up2[2]*scale  + right2[2]*scale , 0,1,r,g,b,a);
+                               transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale , p->org[1] + up2[1]*scale2 + right2[1]*scale , p->org[2] + up2[2]*scale2 + right2[2]*scale , 0,0,r,g,b,a);
+                               transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale2, p->org[1] + up2[1]*scale2 + right2[1]*scale2, p->org[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a);
+                               transpolyvert(p->org[0] + up2[0]*scale  + right2[0]*scale2, p->org[1] + up2[1]*scale  + right2[1]*scale2, p->org[2] + up2[2]*scale  + right2[2]*scale2, 1,1,r,g,b,a);
                        }
                        else
                        {
-                               transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale , p->org[1] + up[1]*scale  + right[1]*scale , p->org[2] + up[2]*scale  + right[2]*scale , 0,0,r,g,b,a);
-                               transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 1,0,r,g,b,a);
-                               transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale2, p->org[1] + up[1]*scale  + right[1]*scale2, p->org[2] + up[2]*scale  + right[2]*scale2, 0,1,r,g,b,a);
+                               transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale , p->org[1] + up[1]*scale  + right[1]*scale , p->org[2] + up[2]*scale  + right[2]*scale , 0,1,r,g,b,a);
+                               transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 0,0,r,g,b,a);
+                               transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale2, p->org[1] + up[1]*scale2 + right[1]*scale2, p->org[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a);
+                               transpolyvert(p->org[0] + up[0]*scale  + right[0]*scale2, p->org[1] + up[1]*scale  + right[1]*scale2, p->org[2] + up[2]*scale  + right[2]*scale2, 1,1,r,g,b,a);
                        }
                        transpolyend();
                }
@@ -1407,6 +1341,8 @@ void R_DrawParticles (void)
                switch (p->type)
                {
                case pt_static:
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
                case pt_fire:
                        p->ramp += time1;
@@ -1415,6 +1351,8 @@ void R_DrawParticles (void)
                        else
                                p->color = ramp3[(int)p->ramp];
                        p->vel[2] += grav;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
 
                case pt_explode:
@@ -1431,7 +1369,7 @@ void R_DrawParticles (void)
 
                case pt_explode2:
                        p->ramp += time3;
-                       if (p->ramp >=8)
+                       if (p->ramp >= 8 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        else
                                p->color = ramp2[(int)p->ramp];
@@ -1445,25 +1383,33 @@ void R_DrawParticles (void)
                        for (i=0 ; i<3 ; i++)
                                p->vel[i] += p->vel[i]*dvel;
                        p->vel[2] -= grav;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
 
                case pt_blob2:
                        for (i=0 ; i<2 ; i++)
                                p->vel[i] -= p->vel[i]*dvel;
                        p->vel[2] -= grav;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
 
                case pt_grav:
                        p->vel[2] -= grav1;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
                case pt_slowgrav:
                        p->vel[2] -= grav;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
+                               p->die = -1;
                        break;
 // LordHavoc: gunshot spark showers
                case pt_dust:
                        p->ramp += time1;
                        p->scale -= frametime * 4;
-                       if (p->ramp >= 8 || p->scale <= 0)
+                       if (p->ramp >= 8 || p->scale <= 0 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        else
                                p->color = ramp3[(int)p->ramp];
@@ -1471,18 +1417,21 @@ void R_DrawParticles (void)
                        break;
 // LordHavoc: for smoke trails
                case pt_smoke:
-                       p->scale += frametime * 16;
-                       p->alpha -= frametime * 64;
-                       p->vel[2] += grav;
+                       p->scale += frametime * 4;
+                       p->alpha -= frametime * 48;
+//                     p->vel[2] += grav;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_snow:
                        if (cl.time > p->time2)
                        {
-                               p->time2 = cl.time + 0.4;
-                               p->vel[0] = (rand()&63)-32;
-                               p->vel[1] = (rand()&63)-32;
+                               p->time2 = cl.time + (rand() & 3) * 0.1;
+                               p->vel[0] = (rand()&63)-32 + p->vel2[0];
+                               p->vel[1] = (rand()&63)-32 + p->vel2[1];
+                               p->vel[2] = (rand()&63)-32 + p->vel2[2];
+                               if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                                       p->die = -1;
                        }
                        break;
                case pt_bulletpuff:
@@ -1502,49 +1451,42 @@ void R_DrawParticles (void)
                case pt_fadespark:
                        p->alpha -= frametime * 256;
                        p->vel[2] -= grav;
-                       if (p->alpha < 1)
+                       if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        break;
                case pt_fadespark2:
                        p->alpha -= frametime * 512;
                        p->vel[2] -= grav;
-                       if (p->alpha < 1)
+                       if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        break;
                case pt_fallfadespark:
                        p->alpha -= frametime * 256;
                        p->vel[2] -= grav1;
-                       if (p->alpha < 1)
+                       if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        break;
                case pt_fallfadespark2:
                        p->alpha -= frametime * 512;
                        p->vel[2] -= grav1;
-                       if (p->alpha < 1)
+                       if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_SOLID)
                                p->die = -1;
                        break;
                case pt_bubble:
-                       p->vel[2] += grav1;
-                       if (p->vel[2] >= 100)
-                               p->vel[2] = 68+rand()&31;
+                       p->vel[2] += grav1 * 2;
+                       if (p->vel[2] >= 200)
+                               p->vel[2] = 136+rand()&63;
                        if (cl.time > p->time2)
                        {
                                p->time2 = cl.time + (rand()&7)*0.0625;
                                p->vel[0] = (rand()&63)-32;
                                p->vel[1] = (rand()&63)-32;
                        }
-                       p->alpha -= frametime * 32;
-                       if (p->alpha < 1)
+                       p->alpha -= frametime * 64;
+                       if (p->alpha < 1 || Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
                                p->die = -1;
                        break;
                }
        }
-
-       /*
-       glEnd ();
-       glShadeModel(GL_SMOOTH);
-       glDepthMask(1); // enable zbuffer updates
-       glDisable (GL_BLEND);
-       */
 }