improved TraceLine in chase.c to be more generally useful (should move it to another...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Feb 2001 23:39:54 +0000 (23:39 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Feb 2001 23:39:54 +0000 (23:39 +0000)
error checking in qmalloc/qfree
expanded COM_LoadFile max filename length from 32 to 1024
improved COM_LoadFile error messages
added COM_ToLowerString and COM_ToUpperString
.zym model support (not quite complete, in development)
unfinished transition to hardware model transforms (not used yet)
changed polylists to draw 5+ point polygons as GL_POLYGON instead of GL_TRIANGLE_FAN (I thought I had reverted to GL_POLYGON a long time ago... strange) for a minor speedup
new explosion effect (no particles)
reverted to lightmapped dynamic lighting effects (vertex hybrid still available as r_dlightmaps 0)
extreme speed improvements in which wall polygons are lit
minor optimization to lightmap building (memset to clear blocklights)
added and disabled texture caching to disk (it turned out to be a slowdown and a massive waste of space, but kept in source form incase it is ever useful)
much improved missing QC function errors (most notably think)
partial redesign of the skin colormapping engine (not used yet)
more consistent light falloff on different objects
created and scrapped a new particle explosion effect (way too fillrate intensive), superseded by the new explosion effect
only dynamically lights smoke and blood particles unless r_dynamicparticles is 2
possible fix for alt-tab bug in NVidia drivers (from Dabb)

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

31 files changed:
chase.c
cl_main.c
common.c
common.h
gl_models.c
gl_poly.c
gl_rmain.c
gl_rsurf.c
gl_screen.c
gl_textures.c
glquake.h
host.c
host_cmd.c
model_alias.c
model_alias.h
model_brush.h
model_shared.c
pr_edict.c
pr_exec.c
progs.h
r_light.c
r_light.h
r_part.c
render.h
sv_main.c
sv_phys.c
sv_user.c
transform.c
transform.h
vid_wgl.c
world.c

diff --git a/chase.c b/chase.c
index 8a46d76feb91f15419bc55dc530d71eca2f261da..21893960b14923dcea732e5455352eddf9276200 100644 (file)
--- a/chase.c
+++ b/chase.c
@@ -38,19 +38,22 @@ void Chase_Reset (void)
 //     start position 12 units behind head
 }
 
-void TraceLine (vec3_t start, vec3_t end, vec3_t impact)
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
 {
        trace_t trace;
 
        memset (&trace, 0, sizeof(trace));
-       VectorCopy (end, trace.endpos); // fix TraceLine endpoint bug
+       VectorCopy (end, trace.endpos);
+       trace.fraction = 1;
        SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
        VectorCopy (trace.endpos, impact);
+       VectorCopy (trace.plane.normal, normal);
+       return trace.fraction;
 }
 
 void Chase_Update (void)
 {
-       vec3_t  forward, up, right, stop, chase_dest;
+       vec3_t  forward, up, right, stop, chase_dest, normal;
        float   dist;
 
        chase_back.value = bound(0, chase_back.value, 128);
@@ -63,7 +66,7 @@ void Chase_Update (void)
        chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist;
        chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value;
 
-       TraceLine (r_refdef.vieworg, chase_dest, stop);
+       TraceLine (r_refdef.vieworg, chase_dest, stop, normal);
        chase_dest[0] = stop[0] + forward[0] * 8;
        chase_dest[1] = stop[1] + forward[1] * 8;
        chase_dest[2] = stop[2] + forward[2] * 8;
index 56d77abbe72e3c21d2553d2e98b88ce5de1d6a50..1abbfd2fe3a5498f233d3b5499a6d4f05413d803 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -345,6 +345,7 @@ void CL_DecayLights (void)
        
        time = cl.time - cl.oldtime;
 
+       c_dlights = 0;
        dl = cl_dlights;
        for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
        {
index a3baf1955ff57267f42001e484eb5fde28ea5841..a1e0a2e35d016eca0c0865fb70562cda417f9bdb 100644 (file)
--- a/common.c
+++ b/common.c
@@ -1175,6 +1175,8 @@ void *qmalloc(unsigned int size)
        qmalloctotal_alloc += size;
        qmalloctotal_alloccount++;
        mem = malloc(size+sizeof(unsigned int));
+       if (!mem)
+               return mem;
        *mem = size;
        return (void *)(mem + 1);
 }
@@ -1182,6 +1184,8 @@ void *qmalloc(unsigned int size)
 void qfree(void *mem)
 {
        unsigned int *m;
+       if (!mem)
+               return;
        m = mem;
        m--; // back up to size
        qmalloctotal_free += *m; // size
@@ -1621,7 +1625,7 @@ byte *COM_LoadFile (char *path, int usehunk, qboolean quiet)
 {
        int             h;
        byte    *buf;
-       char    base[32];
+       char    base[1024];
        int             len;
 
        buf = NULL;     // quiet compiler warning
@@ -1638,24 +1642,29 @@ byte *COM_LoadFile (char *path, int usehunk, qboolean quiet)
        {
        case 1:
                buf = Hunk_AllocName (len+1, va("%s (file)", path));
+               if (!buf)
+                       Sys_Error ("COM_LoadFile: not enough hunk space for %s (size %i)", path, len);
                break;
 //     case 0:
 //             buf = Z_Malloc (len+1);
+//             if (!buf)
+//                     Sys_Error ("COM_LoadFile: not enough zone space for %s (size %i)", path, len);
 //             break;
        case 3:
                buf = Cache_Alloc (loadcache, len+1, base);
+               if (!buf)
+                       Sys_Error ("COM_LoadFile: not enough cache space for %s (size %i)", path, len);
                break;
        case 5:
                buf = qmalloc (len+1);
+               if (!buf)
+                       Sys_Error ("COM_LoadFile: not enough available memory for %s (size %i)", path, len);
+               break;
+       default:
+               Sys_Error ("COM_LoadFile: bad usehunk");
                break;
-//     default:
-//             Sys_Error ("COM_LoadFile: bad usehunk");
-//             break;
        }
 
-       if (!buf)
-               Sys_Error ("COM_LoadFile: not enough space for %s", path);
-               
        ((byte *)buf)[len] = 0;
 
        Sys_FileRead (h, buf, len);                     
@@ -1938,3 +1947,29 @@ int COM_FileExists(char *filename)
 
        return false;
 }
+
+
+//======================================
+// LordHavoc: added these because they are useful
+
+void COM_ToLowerString(char *in, char *out)
+{
+       while (*in)
+       {
+               if (*in >= 'A' && *in <= 'Z')
+                       *out++ = *in++ + 'a' - 'A';
+               else
+                       *out++ = *in++;
+       }
+}
+
+void COM_ToUpperString(char *in, char *out)
+{
+       while (*in)
+       {
+               if (*in >= 'a' && *in <= 'z')
+                       *out++ = *in++ + 'A' - 'a';
+               else
+                       *out++ = *in++;
+       }
+}
index ad55254f6560dbfc2fe474c45209ad7637042c99..da25cafa0e4634dc32a4d14158b99893852c2713 100644 (file)
--- a/common.h
+++ b/common.h
@@ -212,3 +212,7 @@ int COM_FileExists(char *filename);
 extern struct cvar_s   registered;
 
 extern qboolean                standard_quake, rogue, hipnotic, nehahra;
+
+// LordHavoc: useful...
+extern void COM_ToLowerString(char *in, char *out);
+extern void COM_ToUpperString(char *in, char *out);
index 8b2d2823db8d942dd8858513a582ba919356940e..a496b1b345afb7219e960bfaf8f2eee690368ced 100644 (file)
@@ -1,11 +1,19 @@
 
 #include "quakedef.h"
 
+typedef struct
+{
+       float m[3][4];
+} zymbonematrix;
+
 // LordHavoc: vertex array
 float *aliasvert;
+float *modelaliasvert;
 float *aliasvertnorm;
 byte *aliasvertcolor;
 byte *aliasvertcolor2;
+zymbonematrix *zymbonepose;
+int *aliasvertusage;
 
 int chrometexture;
 
@@ -31,9 +39,12 @@ void gl_models_start()
 {
        // allocate vertex processing arrays
        aliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
+       modelaliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
        aliasvertnorm = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
        aliasvertcolor = qmalloc(sizeof(byte[MD2MAX_VERTS][4]));
        aliasvertcolor2 = qmalloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
+       zymbonepose = qmalloc(sizeof(zymbonematrix[256]));
+       aliasvertusage = qmalloc(sizeof(int[MD2MAX_VERTS]));
        makechrometexture();
 }
 
@@ -43,6 +54,8 @@ void gl_models_shutdown()
        qfree(aliasvertnorm);
        qfree(aliasvertcolor);
        qfree(aliasvertcolor2);
+       qfree(zymbonepose);
+       qfree(aliasvertusage);
 }
 
 void GL_Models_Init()
@@ -55,6 +68,7 @@ extern vec3_t softwaretransform_y;
 extern vec3_t softwaretransform_z;
 extern vec_t softwaretransform_scale;
 extern vec3_t softwaretransform_offset;
+extern cvar_t r_modelsdonttransformnormals;
 void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
 {
        int i;
@@ -78,45 +92,107 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1
                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++;
+               if (r_modelsdonttransformnormals.value)
+               {
+                       float *modelav = modelaliasvert;
+                       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;
+                               // save mostly un-transformed copy for lighting
+                               modelav[0] = point[0] * softwaretransform_scale;
+                               modelav[1] = point[1] * softwaretransform_scale;
+                               modelav[2] = point[2] * softwaretransform_scale;
+                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+                               // decompress but do not transform the normals
+                               avn[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
+                               avn[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
+                               avn[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
+                               modelav += 3;
+                               av += 3;
+                               avn += 3;
+                               verts1++;verts2++;
+                       }
+               }
+               else
+               {
+                       for (i = 0;i < vertcount;i++)
+                       {
+                               // rotate, scale, and translate the vertex locations
+                               point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
+                               point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
+                               point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
+                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+                               // rotate the normals
+                               point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
+                               point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
+                               point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
+                               avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+                               avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+                               avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                               av += 3;
+                               avn += 3;
+                               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++;
+               if (r_modelsdonttransformnormals.value)
+               {
+                       float *modelav = modelaliasvert;
+                       for (i = 0;i < vertcount;i++)
+                       {
+                               // rotate, scale, and translate the vertex locations
+                               point[0] = verts1->v[0] * scale1[0] + translate1[0];
+                               point[1] = verts1->v[1] * scale1[1] + translate1[1];
+                               point[2] = verts1->v[2] * scale1[2] + translate1[2];
+                               // save mostly un-transformed copy for lighting
+                               modelav[0] = point[0] * softwaretransform_scale;
+                               modelav[1] = point[1] * softwaretransform_scale;
+                               modelav[2] = point[2] * softwaretransform_scale;
+                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+                               // decompress normal but do not rotate it
+                               avn[0] = verts1->n[0] * (1.0f / 127.0f);
+                               avn[1] = verts1->n[1] * (1.0f / 127.0f);
+                               avn[2] = verts1->n[2] * (1.0f / 127.0f);
+                               modelav += 3;
+                               av += 3;
+                               avn += 3;
+                               verts1++;
+                       }
+               }
+               else
+               {
+                       for (i = 0;i < vertcount;i++)
+                       {
+                               // rotate, scale, and translate the vertex locations
+                               point[0] = verts1->v[0] * scale1[0] + translate1[0];
+                               point[1] = verts1->v[1] * scale1[1] + translate1[1];
+                               point[2] = verts1->v[2] * scale1[2] + translate1[2];
+                               av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+                               av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+                               av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+                               // rotate the normals
+                               point[0] = verts1->n[0] * (1.0f / 127.0f);
+                               point[1] = verts1->n[1] * (1.0f / 127.0f);
+                               point[2] = verts1->n[2] * (1.0f / 127.0f);
+                               avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+                               avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+                               avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+                               av += 3;
+                               avn += 3;
+                               verts1++;
+                       }
                }
        }
 }
@@ -223,7 +299,7 @@ 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)
+void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int *skin, int colormap, int effects, int flags)
 {
        int             i, pose;
        float   lerpscale, lerp;
@@ -398,7 +474,7 @@ 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)
+void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skin, int effects, int flags)
 {
        int *order, count;
        float lerp;
@@ -624,6 +700,420 @@ void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t
        glDepthMask(1);
 }
 
+void ZymoticLerpBones(int count, float lerp2, zymbonematrix *bone1, zymbonematrix *bone2, zymbone_t *bone, float rootorigin[3], float rootangles[3])
+{
+       float lerp1;
+       zymbonematrix *out, rootmatrix, m;
+       lerp1 = 1 - lerp2;
+       out = zymbonepose;
+       AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]);
+       rootmatrix.m[0][3] = rootorigin[0];
+       rootmatrix.m[1][3] = rootorigin[1];
+       rootmatrix.m[2][3] = rootorigin[2];
+       if (lerp1 != 1) // interpolation
+       {
+               while(count--)
+               {
+                       // interpolate matrices
+                       m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
+                       m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
+                       m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
+                       m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
+                       m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
+                       m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
+                       m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
+                       m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
+                       m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
+                       m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
+                       m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
+                       m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
+                       if (bone->parent >= 0)
+                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
+                       else
+                               R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
+                       bone1++;
+                       bone2++;
+                       bone++;
+                       out++;
+               }
+       }
+       else // no interpolation
+       {
+               while(count--)
+               {
+                       if (bone->parent >= 0)
+                               R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]);
+                       else
+                               R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]);
+                       bone1++;
+                       bone++;
+                       out++;
+               }
+       }
+}
+
+void ZymoticTransformVerts(int vertcount, int *bonecounts, zymvertex_t *vert)
+{
+       int c;
+       float *out = aliasvert;
+       zymbonematrix *matrix;
+       while(vertcount--)
+       {
+               c = *bonecounts++;
+               if (c == 1)
+               {
+                       matrix = &zymbonepose[vert->bonenum];
+                       out[0] = vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
+                       out[1] = vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
+                       out[2] = vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
+                       vert++;
+               }
+               else
+               {
+                       VectorClear(out);
+                       while(c--)
+                       {
+                               matrix = &zymbonepose[vert->bonenum];
+                               out[0] += vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
+                               out[1] += vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
+                               out[2] += vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
+                               vert++;
+                       }
+               }
+               out += 3;
+       }
+}
+
+float ixtable[4096];
+
+void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist)
+{
+       int a, b, c, d;
+       float *out, v1[3], v2[3], normal[3];
+       int *u;
+       if (!ixtable[1])
+       {
+               ixtable[0] = 0;
+               for (a = 1;a < 4096;a++)
+                       ixtable[a] = 1.0f / a;
+       }
+       // clear normals
+       memset(aliasvertnorm, 0, sizeof(float[3]) * vertcount);
+       memset(aliasvertusage, 0, sizeof(int) * vertcount);
+       // parse render list and accumulate surface normals
+       while(shadercount--)
+       {
+               d = *renderlist++;
+               while (d--)
+               {
+                       a = renderlist[0]*3;
+                       b = renderlist[1]*3;
+                       c = renderlist[2]*3;
+                       v1[0] = aliasvert[a+0] - aliasvert[b+0];
+                       v1[1] = aliasvert[a+1] - aliasvert[b+1];
+                       v1[2] = aliasvert[a+2] - aliasvert[b+2];
+                       v2[0] = aliasvert[c+0] - aliasvert[b+0];
+                       v2[1] = aliasvert[c+1] - aliasvert[b+1];
+                       v2[2] = aliasvert[c+2] - aliasvert[b+2];
+                       CrossProduct(v1, v2, normal);
+                       VectorNormalize(normal);
+                       // add surface normal to vertices
+                       aliasvertnorm[a+0] += normal[0];
+                       aliasvertnorm[a+1] += normal[1];
+                       aliasvertnorm[a+2] += normal[2];
+                       aliasvertusage[a]++;
+                       aliasvertnorm[b+0] += normal[0];
+                       aliasvertnorm[b+1] += normal[1];
+                       aliasvertnorm[b+2] += normal[2];
+                       aliasvertusage[b]++;
+                       aliasvertnorm[c+0] += normal[0];
+                       aliasvertnorm[c+1] += normal[1];
+                       aliasvertnorm[c+2] += normal[2];
+                       aliasvertusage[c]++;
+                       renderlist += 3;
+               }
+       }
+       // average surface normals
+       out = aliasvertnorm;
+       u = aliasvertusage;
+       while(vertcount--)
+       {
+               if (*u > 1)
+               {
+                       a = ixtable[*u];
+                       out[0] *= a;
+                       out[1] *= a;
+                       out[2] *= a;
+               }
+               u++;
+               out += 3;
+       }
+}
+
+void GL_DrawZymoticModelMesh(byte *colors, zymtype1header_t *m)
+{
+       int i, c, *renderlist, *texturenum;
+       if (!r_render.value)
+               return;
+       renderlist = (int *)(m->lump_render.start + (int) m);
+       texturenum = (int *)(m->lump_shaders.start + (int) m);
+       if (gl_vertexarrays.value)
+       {
+               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+               glEnableClientState(GL_VERTEX_ARRAY);
+
+               qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
+               glEnableClientState(GL_COLOR_ARRAY);
+
+               qglTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m));
+               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = (*renderlist++) * 3;
+                       glBindTexture(GL_TEXTURE_2D, *texturenum++);
+                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
+                       renderlist += c;
+               }
+
+               glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+               glDisableClientState(GL_COLOR_ARRAY);
+
+               glDisableClientState(GL_VERTEX_ARRAY);
+       }
+       else
+       {
+               int index;
+               float *tex;
+               tex = (float *)(m->lump_texcoords.start + (int) m);
+
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = *renderlist++;
+                       glBindTexture(GL_TEXTURE_2D, *texturenum++);
+                       glBegin(GL_TRIANGLES);
+                       while (c--)
+                       {
+                               index = *renderlist++;
+                               glTexCoord2fv(tex + index*2);
+                               glColor4ubv(colors + index*4);
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glTexCoord2fv(tex + index*2);
+                               glColor4ubv(colors + index*4);
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glTexCoord2fv(tex + index*2);
+                               glColor4ubv(colors + index*4);
+                               glVertex3fv(aliasvert + index*3);
+                       }
+                       glEnd();
+               }
+       }
+}
+
+void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
+{
+       vec3_t diff;
+       int i, c, *renderlist;
+       if (!r_render.value)
+               return;
+       renderlist = (int *)(m->lump_render.start + (int) m);
+       glDisable(GL_TEXTURE_2D);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(0); // disable zbuffer updates
+
+       VectorSubtract(org, r_refdef.vieworg, diff);
+       glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+       if (gl_vertexarrays.value)
+       {
+               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+               glEnableClientState(GL_VERTEX_ARRAY);
+
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = (*renderlist++) * 3;
+                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
+                       renderlist += c;
+               }
+
+               glDisableClientState(GL_VERTEX_ARRAY);
+       }
+       else
+       {
+               int index;
+               float *tex;
+               tex = (float *)(m->lump_texcoords.start + (int) m);
+
+               glBegin(GL_TRIANGLES);
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = *renderlist++;
+                       while (c--)
+                       {
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                       }
+               }
+               glEnd();
+       }
+       glEnable(GL_TEXTURE_2D);
+       glColor3f (1,1,1);
+}
+
+void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m)
+{
+       int i, c, *renderlist;
+       float *av, l;
+       if (!r_render.value)
+               return;
+
+       // flatten it to make a shadow
+       av = aliasvert + 2;
+       l = lightspot[2] + 0.125;
+       for (i = 0;i < m->numverts;i++, av+=3)
+               if (*av > l)
+                       *av = l;
+
+       renderlist = (int *)(m->lump_render.start + (int) m);
+       glDisable(GL_TEXTURE_2D);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(0); // disable zbuffer updates
+
+       glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+       if (gl_vertexarrays.value)
+       {
+               qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+               glEnableClientState(GL_VERTEX_ARRAY);
+
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = (*renderlist++) * 3;
+                       qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
+                       renderlist += c;
+               }
+
+               glDisableClientState(GL_VERTEX_ARRAY);
+       }
+       else
+       {
+               int index;
+               float *tex;
+               tex = (float *)(m->lump_texcoords.start + (int) m);
+
+               glBegin(GL_TRIANGLES);
+               for (i = 0;i < m->numshaders;i++)
+               {
+                       c = *renderlist++;
+                       while (c--)
+                       {
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                               index = *renderlist++;
+                               glVertex3fv(aliasvert + index*3);
+                       }
+               }
+               glEnd();
+       }
+       glEnable(GL_TEXTURE_2D);
+       glColor3f (1,1,1);
+}
+
+/*
+=================
+R_DrawZymoticFrame
+=================
+*/
+void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skinblah, int effects, int flags)
+{
+       zymscene_t *scene;
+       float scenetime, scenefrac;
+       int sceneframe1, sceneframe2;
+       zymbonematrix *basebonepose;
+       if ((frame >= m->numscenes) || (frame < 0))
+       {
+               Con_DPrintf ("R_ZymoticSetupFrame: no such frame %d\n", frame);
+               frame = 0;
+       }
+
+       scene = (zymscene_t *)(m->lump_scenes.start + (int) m) + frame;
+       if (ent->draw_lastmodel != ent->model || ent->draw_pose != frame || ent->draw_lerpstart >= cl.time)
+       {
+               ent->draw_lastmodel = ent->model;
+               ent->draw_lastpose = -1;
+               ent->draw_pose = frame;
+               ent->draw_lerpstart = cl.time;
+       }
+       scenetime = (cl.time - ent->draw_lerpstart) * scene->framerate;
+       sceneframe1 = (int) scenetime;
+       sceneframe2 = sceneframe1 + 1;
+       scenefrac = scenetime - sceneframe1;
+       if (scene->flags & ZYMSCENEFLAG_NOLOOP)
+       {
+               if (sceneframe1 > (scene->length - 1))
+                       sceneframe1 = (scene->length - 1);
+               if (sceneframe2 > (scene->length - 1))
+                       sceneframe2 = (scene->length - 1);
+       }
+       else
+       {
+               sceneframe1 %= scene->length;
+               sceneframe2 %= scene->length;
+       }
+       if (sceneframe2 == sceneframe1)
+               scenefrac = 0;
+
+       basebonepose = (zymbonematrix *)(m->lump_poses.start + (int) m);
+       ZymoticLerpBones(m->numbones, scenefrac, basebonepose + sceneframe1 * m->numbones, basebonepose + sceneframe2 * m->numbones, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles);
+       ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
+       ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
+
+       R_LightModel(m->numverts, org, color);
+
+       if (!r_render.value)
+               return;
+       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);
+       }
+
+       GL_DrawZymoticModelMesh(aliasvertcolor, m);
+
+       if (fogenabled)
+               GL_DrawZymoticModelMeshFog(org, m);
+
+       if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
+               GL_DrawZymoticModelMeshShadow(m);
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glEnable (GL_BLEND);
+       glDepthMask(1);
+}
+
 int modeldlightbits[8];
 extern int r_dlightframecount;
 
@@ -633,7 +1123,7 @@ 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)
+void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap)
 {
        int                     i;
        vec3_t          mins, maxs, color;
@@ -699,8 +1189,10 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i
                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);
+       if (clmodel->aliastype == ALIASTYPE_ZYM)
+               R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, 0, effects, flags);
+       else if (clmodel->aliastype == ALIASTYPE_MD2)
+               R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset[0], effects, flags);
        else
-               R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset, colormap, effects, flags);
+               R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset, colormap, effects, flags);
 }
index 2631e3520ce319611708a14f5ebf91bb0605b24e..2f53d5cd260f765c29639ecca94bc1472c86fa15 100644 (file)
--- a/gl_poly.c
+++ b/gl_poly.c
@@ -413,14 +413,14 @@ void transpolyrender()
                                                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                }
                        }
-                       qglDrawArrays(GL_TRIANGLE_FAN, p->firstvert, p->verts);
+                       qglDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                        if (p->glowtexnum)
                        {
                                texnum = p->glowtexnum; // highly unlikely to match next poly, but...
                                glBindTexture(GL_TEXTURE_2D, texnum);
                                tpolytype = TPOLYTYPE_ADD; // might match next poly
                                glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                               qglDrawArrays(GL_TRIANGLE_FAN, p->firstvert, p->verts);
+                               qglDrawArrays(GL_POLYGON, p->firstvert, p->verts);
                        }
                }
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -473,7 +473,7 @@ void transpolyrender()
                                                glBegin(GL_QUADS);
                                                break;
                                        default:
-                                               glBegin(GL_TRIANGLE_FAN);
+                                               glBegin(GL_POLYGON);
                                                points = -1; // to force a reinit on the next poly
                                                break;
                                        }
@@ -497,7 +497,7 @@ void transpolyrender()
                                                glBlendFunc(GL_SRC_ALPHA, GL_ONE);
                                        }
                                        points = -1;
-                                       glBegin(GL_TRIANGLE_FAN);
+                                       glBegin(GL_POLYGON);
                                        for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
                                        {
                                                glColor4ub(255,255,255,vert->a);
@@ -524,7 +524,7 @@ void transpolyrender()
                                                        texnum = p->fogtexnum;
                                                        glBindTexture(GL_TEXTURE_2D, texnum);
                                                }
-                                               glBegin(GL_TRIANGLE_FAN);
+                                               glBegin(GL_POLYGON);
                                                for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
                                                {
                                                        VectorSubtract(vert->v, r_refdef.vieworg,diff);
@@ -537,7 +537,7 @@ void transpolyrender()
                                        else
                                        {
                                                glDisable(GL_TEXTURE_2D);
-                                               glBegin(GL_TRIANGLE_FAN);
+                                               glBegin(GL_POLYGON);
                                                for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
                                                {
                                                        VectorSubtract(vert->v, r_refdef.vieworg,diff);
index 92fa54c41c9a34a183e18e22620078b233f3c3c8..24a08cdbaa36c736b1d60aed628bdf83aa12be15 100644 (file)
@@ -256,6 +256,7 @@ extern void GL_Misc_Init();
 extern void R_Crosshairs_Init();
 extern void R_Light_Init();
 extern void R_Particles_Init();
+extern void R_Explosion_Init();
 
 void Render_Init()
 {
@@ -270,6 +271,7 @@ void Render_Init()
        R_Crosshairs_Init();
        R_Light_Init();
        R_Particles_Init();
+       R_Explosion_Init();
        R_StartModules();
 }
 
@@ -380,7 +382,7 @@ void R_DrawEntitiesOnList2 (void)
                switch (currententity->model->type)
                {
                case mod_alias:
-                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
+                       R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap);
                        break;
 
                case mod_sprite:
@@ -411,7 +413,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, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
+       R_DrawAliasModel (currententity, FALSE, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap);
        glDepthRange (gldepthmin, gldepthmax);
 }
 
@@ -499,8 +501,7 @@ void R_SetupFrame (void)
        c_bmodels = 0;
        c_sprites = 0;
        c_particles = 0;
-       c_dlights = 0;
-
+//     c_dlights = 0;
 }
 
 
@@ -725,7 +726,7 @@ char r_speeds2_string1[81], r_speeds2_string2[81], r_speeds2_string3[81], r_spee
 void R_RenderView (void)
 {
        double starttime, currtime, temptime;
-       int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_transpoly, time_blend, time_total;
+       int time_clear, time_setup, time_world, time_bmodels, time_upload, time_sky, time_wall, time_models, time_moveparticles, time_drawparticles, time_moveexplosions, time_drawexplosions, time_transpoly, time_blend, time_total;
 //     double currtime, temptime;
 //     if (r_norefresh.value)
 //             return;
@@ -787,6 +788,10 @@ void R_RenderView (void)
        TIMEREPORT(time_moveparticles)
        R_DrawParticles ();
        TIMEREPORT(time_drawparticles)
+       R_MoveExplosions();
+       TIMEREPORT(time_moveexplosions)
+       R_DrawExplosions();
+       TIMEREPORT(time_drawexplosions)
 
        transpolyrender();
        TIMEREPORT(time_transpoly)
index 6ab30c4de943d417877350be801a8829a0a82413..9084da3262608cf5105906d4444a7c1b68588e13 100644 (file)
@@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 int            lightmap_textures;
 
-signed blocklights[18*18*3]; // LordHavoc: *3 for colored lighting
+signed int blocklights[18*18*3]; // LordHavoc: *3 for colored lighting
 
 // LordHavoc: skinny but tall lightmaps for quicker subimage uploads
 #define        BLOCK_WIDTH             128
@@ -50,6 +50,7 @@ cvar_t gl_texsort = {"gl_texsort", "1"};
 //cvar_t gl_funnywalls = {"gl_funnywalls", "0"}; // LordHavoc: see BuildSurfaceDisplayList
 cvar_t r_newworldnode = {"r_newworldnode", "0"};
 cvar_t r_oldclip = {"r_oldclip", "1"};
+cvar_t r_dlightmap = {"r_dlightmap", "1"};
 
 qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible;
 int lightmapbytes;
@@ -81,6 +82,7 @@ void GL_Surf_Init()
        Cvar_RegisterVariable(&gl_texsort);
        Cvar_RegisterVariable(&r_newworldnode);
        Cvar_RegisterVariable(&r_oldclip);
+       Cvar_RegisterVariable(&r_dlightmap);
        // check if it's the glquake minigl driver
        if (strncasecmp(gl_vendor,"3Dfx",4)==0)
        if (!gl_arrays)
@@ -93,6 +95,113 @@ void GL_Surf_Init()
        R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown);
 }
 
+int         dlightdivtable[32768];
+
+/*
+       R_AddDynamicLights
+*/
+int R_AddDynamicLights (msurface_t *surf)
+{
+       int         sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, j, s, t, smax, tmax, red, green, blue, lit, dist2, impacts, impactt;
+       unsigned int *bl;
+       float       dist;
+       vec3_t      impact, local;
+
+       // LordHavoc: use 64bit integer...  shame it's not very standardized...
+//#if _MSC_VER || __BORLANDC__
+//     __int64     k;
+//#else
+//     long long   k;
+//#endif
+
+       // LordHavoc: later note: MSVC and hopefully all other C compilers use a 64bit result for 32bit*32bit multiply, so that was not necessary
+       int                     k;
+
+       lit = false;
+
+       if (!dlightdivtable[1])
+       {
+               dlightdivtable[0] = 4194304;
+               for (s = 1; s < 32768; s++)
+                       dlightdivtable[s] = 4194304 / (s << 7);
+       }
+
+       smax = (surf->extents[0] >> 4) + 1;
+       tmax = (surf->extents[1] >> 4) + 1;
+
+       for (lnum = 0; lnum < MAX_DLIGHTS; lnum++)
+       {
+               if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
+                       continue;                                       // not lit by this light
+
+               VectorSubtract (cl_dlights[lnum].origin, currententity->origin, local);
+               dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
+
+               // for comparisons to minimum acceptable light
+               maxdist = (int) ((cl_dlights[lnum].radius * cl_dlights[lnum].radius) * LIGHTSCALE);
+
+               // clamp radius to avoid exceeding 32768 entry division table
+               if (maxdist > 4194304)
+                       maxdist = 4194304;
+
+               dist2 = dist * dist;
+               if (dist2 >= maxdist)
+                       continue;
+
+               impact[0] = cl_dlights[lnum].origin[0] - surf->plane->normal[0] * dist;
+               impact[1] = cl_dlights[lnum].origin[1] - surf->plane->normal[1] * dist;
+               impact[2] = cl_dlights[lnum].origin[2] - surf->plane->normal[2] * dist;
+
+               impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+               impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+               s = bound(0, impacts, smax * 16) - impacts;
+               t = bound(0, impactt, tmax * 16) - impactt;
+               i = s * s + t * t + dist2;
+               if (i > maxdist)
+                       continue;
+
+               // reduce calculations
+               for (s = 0, i = impacts; s < smax; s++, i -= 16)
+                       sdtable[s] = i * i + dist2;
+
+               maxdist3 = maxdist - (int) (dist * dist);
+
+               // convert to 8.8 blocklights format and scale up by radius
+               red = cl_dlights[lnum].color[0] * maxdist;
+               green = cl_dlights[lnum].color[1] * maxdist;
+               blue = cl_dlights[lnum].color[2] * maxdist;
+               bl = blocklights;
+
+               i = impactt;
+               for (t = 0; t < tmax; t++, i -= 16)
+               {
+                       td = i * i;
+                       // make sure some part of it is visible on this line
+                       if (td < maxdist3)
+                       {
+                               maxdist2 = maxdist - td;
+                               for (s = 0; s < smax; s++)
+                               {
+                                       if (sdtable[s] < maxdist2)
+                                       {
+                                               k = dlightdivtable[(sdtable[s] + td) >> 7];
+                                               j = (red   * k) >> 9;bl[0] += j;
+                                               j = (green * k) >> 9;bl[1] += j;
+                                               j = (blue  * k) >> 9;bl[2] += j;
+                                               lit = true;
+                                       }
+                                       bl += 3;
+                               }
+                       }
+                       else // skip line
+                               bl += smax * 3;
+               }
+       }
+       return lit;
+}
+
+
 /*
 ===============
 R_BuildLightMap
@@ -103,18 +212,20 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights
 void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
 {
        int                     smax, tmax;
-       int                     i, j, size;
+       int                     i, j, size, size3;
        byte            *lightmap;
        int                     scale;
        int                     maps;
        int                     *bl;
 
+       surf->cached_dlight = 0;
        surf->cached_lighthalf = lighthalf;
        surf->cached_ambient = r_ambient.value;
 
        smax = (surf->extents[0]>>4)+1;
        tmax = (surf->extents[1]>>4)+1;
        size = smax*tmax;
+       size3 = size*3;
        lightmap = surf->samples;
 
 // set to full bright if no light data
@@ -131,14 +242,15 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
        else
        {
 // clear to no light
-               bl = blocklights;
                j = r_ambient.value * 512.0f; // would be 256.0f logically, but using 512.0f to match winquake style
-               for (i=0 ; i<size ; i++)
+               if (j)
                {
-                       *bl++ = j;
-                       *bl++ = j;
-                       *bl++ = j;
+                       bl = blocklights;
+                       for (i = 0;i < size3;i++)
+                               *bl++ = j;
                }
+               else
+                       memset(&blocklights[0], 0, size*3*sizeof(int));
 
 // add all the lightmaps
                if (lightmap)
@@ -148,14 +260,13 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
                                scale = d_lightstylevalue[surf->styles[maps]];
                                surf->cached_light[maps] = scale;       // 8.8 fraction
                                bl = blocklights;
-                               for (i=0 ; i<size ; i++)
-                               {
-                                       *bl++ += *lightmap++ * scale;
+                               for (i = 0;i < size3;i++)
                                        *bl++ += *lightmap++ * scale;
-                                       *bl++ += *lightmap++ * scale;
-                               }
                        }
                }
+               if (r_dlightmap.value && surf->dlightframe == r_dlightframecount)
+                       if ((surf->cached_dlight = R_AddDynamicLights(surf)))
+                               c_light_polys++;
        }
        stride -= (smax*lightmapbytes);
        bl = blocklights;
@@ -464,7 +575,7 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha)
                        wv += 6;
                }
        }
-       if (s->dlightframe == r_dlightframecount && r_dynamic.value)
+       if (s->dlightframe == r_dlightframecount)
                RSurf_Light(s->dlightbits, s->polys);
        wv = wvert;
        // FIXME: make fog texture if water texture is transparent?
@@ -487,11 +598,14 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
        // 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]))
+               if (s->cached_dlight
+                || (r_dlightmap.value && s->dlightframe == r_dlightframecount)
+                || r_ambient.value != s->cached_ambient
+                || lighthalf != s->cached_lighthalf
+                || (s->styles[0] != 255 && d_lightstylevalue[s->styles[0]] != s->cached_light[0])
+                || (s->styles[1] != 255 && d_lightstylevalue[s->styles[1]] != s->cached_light[1])
+                || (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2])
+                || (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3]))
                        R_UpdateLightmap(s, s->lightmaptexturenum);
        }
        wv = wvert;
@@ -511,7 +625,7 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
        }
        if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS))
                return;
-       if (s->dlightframe == r_dlightframecount && r_dynamic.value)
+       if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount)
                lit = RSurf_Light(s->dlightbits, s->polys);
        wv = wvert;
        wp = &wallpoly[currentwallpoly];
@@ -600,7 +714,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod
                        wv += 6;
                }
        }
-       if (s->dlightframe == r_dlightframecount && r_dynamic.value)
+       if (s->dlightframe == r_dlightframecount)
                RSurf_Light(s->dlightbits, s->polys);
        wv = wvert;
        if (isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1))
index 0e593950b467a474dcdc4ab275f31dabb3c0f0cf..23b7047c659673243c03a35be398730a19a09586 100644 (file)
@@ -968,7 +968,7 @@ void SCR_UpdateScreen (void)
        GL_EndRendering ();
 }
 
-// for profiling, this is seperated
+// for profiling, this is separated
 void GL_Finish()
 {
        if (!r_render.value)
index 8afef82c5b865769e5052b50dbb4a4e0cddfa2af..e7c19f38bf4fe2d9b78300382f5697622f330969 100644 (file)
@@ -1,6 +1,6 @@
 #include "quakedef.h"
 
-cvar_t         gl_max_size = {"gl_max_size", "1024"};
+cvar_t         gl_max_size = {"gl_max_size", "2048"};
 cvar_t         gl_picmip = {"gl_picmip", "0"};
 cvar_t         gl_lerpimages = {"gl_lerpimages", "1"};
 cvar_t         r_upload = {"r_upload", "1"};
@@ -11,27 +11,29 @@ int         gl_filter_max = GL_LINEAR;
 
 int            texels;
 
-// 4096x4096
-#define MAXMIPS 12
+// 65536x65536
+#define MAXMIPS 16
 
 typedef struct
 {
+       char    identifier[64];
        int             texnum;
        int             texeldatasize;
        byte    *texels[MAXMIPS];
        unsigned short texelsize[MAXMIPS][2];
-       char    identifier[64];
-       short   width, height;
+       unsigned short width, height;
 // LordHavoc: CRC to identify cache mismatchs
        unsigned short crc;
        char    mipmap;
        char    alpha;
        char    bytesperpixel;
        char    lerped; // whether this texture was uploaded with or without interpolation
+       char    inuse; // cleared during texture purge when loading new level
+       char    pad; // unused
 } gltexture_t;
 
 #define        MAX_GLTEXTURES  4096
-gltexture_t    gltextures[MAX_GLTEXTURES];
+gltexture_t    *gltextures;
 int                    numgltextures;
 
 typedef struct
@@ -150,13 +152,13 @@ void GL_TextureStats_PrintTotal(void)
 
 char engineversion[40];
 
-void GL_UploadTexture (gltexture_t *glt);
+//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);
+//     int i;
+//     gltexture_t *glt;
+//     for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+//             GL_UploadTexture(glt);
 }
 
 void gl_textures_shutdown()
@@ -178,6 +180,8 @@ void GL_Textures_Init (void)
        if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide"))
                Cvar_Set ("gl_max_size", "256");
 
+       gltextures = qmalloc(sizeof(gltexture_t) * MAX_GLTEXTURES);
+       memset(gltextures, 0, sizeof(gltexture_t) * MAX_GLTEXTURES);
        Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
 
        R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
@@ -479,11 +483,15 @@ int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolea
 {
        unsigned short  crc;
        int                             i, width2, height2, width3, height3, w, h, mip;
-       gltexture_t             *glt;
+       gltexture_t             *glt, *freeglt;
+       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
+       //char                  cachefilename[1024], *cachefile;
 
        if (isDedicated)
                return 1;
 
+       freeglt = NULL;
+
        // 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
@@ -491,30 +499,45 @@ int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolea
        {
                for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
                {
-                       if (!strcmp (identifier, glt->identifier))
+                       if (glt->inuse)
                        {
-                               // LordHavoc: everyone hates cache mismatchs, so I fixed it
-                               if (crc != glt->crc || width != glt->width || height != glt->height)
+                               if (!strcmp (identifier, glt->identifier))
                                {
-                                       Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
-                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                                       // LordHavoc: everyone hates cache mismatchs, so I fixed it
+                                       if (crc != glt->crc || width != glt->width || height != glt->height)
+                                       {
+                                               Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
+                                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                                       }
+                                       if ((gl_lerpimages.value != 0) != glt->lerped)
+                                               goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+                                       return glt->texnum;
                                }
-                               if ((gl_lerpimages.value != 0) != glt->lerped)
-                                       goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
-                               return glt->texnum;
                        }
+                       else
+                               freeglt = glt;
                }
        }
+       else
+               i = 0;
        // LordHavoc: although this could be an else condition as it was in the original id code,
        //            it is more clear this way
-       // 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++;
+       if (freeglt)
+       {
+               glt = freeglt;
+               strcpy (glt->identifier, identifier);
+       }
+       else
+       {
+               // LordHavoc: check if there are still slots available
+               if (numgltextures >= MAX_GLTEXTURES)
+                       Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
+               glt = &gltextures[numgltextures++];
+               glt->texnum = texture_extension_number;
+               texture_extension_number++;
+               strcpy (glt->identifier, identifier);
+       }
+
 // LordHavoc: label to drop out of the loop into the setup code
 GL_LoadTexture_setup:
        // calculate power of 2 size
@@ -537,6 +560,31 @@ GL_LoadTexture_setup:
        glt->bytesperpixel = bytesperpixel;
        glt->lerped = gl_lerpimages.value != 0;
        glt->alpha = false; // updated later
+       glt->inuse = true;
+       /*
+       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
+       sprintf(cachefilename, "%s%x%x%x.texels", identifier, width3, height3, crc);
+       for (i = 0;cachefilename[i];i++)
+       {
+               if (cachefilename[i] <= ' ' || cachefilename[i] >= 127 || cachefilename[i] == '/' || cachefilename[i] == '\\' || cachefilename[i] == ':' || cachefilename[i] == '*' || cachefilename[i] == '?')
+                       cachefilename[i] = '@';
+               if (cachefilename[i] >= 'A' && cachefilename[i] <= 'Z')
+                       cachefilename[i] += 'a' - 'A';
+       }
+       cachefile = COM_LoadMallocFile(cachefilename, true);
+       if (cachefile)
+       {
+               if (cachefile[0] == 'D' && cachefile[1] == 'P' && cachefile[2] == 'C' && cachefile[3] == 'T')
+               {
+                       memcpy(glt->texels[0], cachefile + 4, width3*height3*4);
+                       qfree(cachefile);
+//                     Con_Printf("loaded cache texture %s\n", cachefilename);
+                       goto cacheloaded;
+               }
+               else
+                       qfree(cachefile);
+       }
+       */
        if (width == width3 && height == height3) // perfect match
        {
                if (bytesperpixel == 1) // 8bit
@@ -594,6 +642,19 @@ GL_LoadTexture_setup:
                        GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
                qfree(temptexels);
        }
+       /*
+       // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace)
+       Con_Printf("writing cache texture %s\n", cachefilename);
+       cachefile = qmalloc(width3*height3*4 + 4);
+       cachefile[0] = 'D';
+       cachefile[1] = 'P';
+       cachefile[2] = 'C';
+       cachefile[3] = 'T';
+       memcpy(cachefile + 4, glt->texels[0], width3*height3*4);
+       COM_WriteFile(cachefilename, cachefile, width3*height3*4 + 4);
+       qfree(cachefile);
+cacheloaded:
+       */
        if (alpha)
        {
                byte    *in = glt->texels[0] + 3;
@@ -617,22 +678,3 @@ GL_LoadTexture_setup:
 
        return glt->texnum;
 }
-
-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 89dc8c25659a3067f9f5cc7e4f13deb523d796f0..b6d2d32b103346404e4f40689f444b034c210e08 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -223,7 +223,7 @@ extern vec_t fogdensity;
 extern cvar_t gl_vertexarrays;
 extern qboolean lighthalf;
 
-extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap);
+extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap);
 
 extern cvar_t r_render;
 extern cvar_t r_upload;
diff --git a/host.c b/host.c
index 25240ec386594ed5afa6ac18ce2d68fc79cbc7d1..e179da68ed45d6084b5ca7d84a29e918f18064c7 100644 (file)
--- a/host.c
+++ b/host.c
@@ -373,7 +373,7 @@ void SV_DropClient (qboolean crash)
                // this will set the body to a dead frame, among other things
                        saveSelf = pr_global_struct->self;
                        pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
-                       PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
+                       PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing");
                        pr_global_struct->self = saveSelf;
                }
 
index f757184a937fe63f4f98eb9549f4df5f5030ed25..4783279deb7cab63c3dc2fc58ad19aff5b0707e8 100644 (file)
@@ -894,7 +894,7 @@ void Host_Color_f(void)
                pr_global_struct->time = sv.time;
                pr_globals[0] = playercolor;
                pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
-               PR_ExecuteProgram (SV_ChangeTeam);
+               PR_ExecuteProgram (SV_ChangeTeam, "");
        }
        else
        {
@@ -929,7 +929,7 @@ void Host_Kill_f (void)
        
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(sv_player);
-       PR_ExecuteProgram (pr_global_struct->ClientKill);
+       PR_ExecuteProgram (pr_global_struct->ClientKill, "QC function ClientKill is missing");
 }
 
 
@@ -1036,7 +1036,7 @@ void Host_Spawn_f (void)
                        Con_DPrintf("Calling RestoreGame\n");
                        pr_global_struct->time = sv.time;
                        pr_global_struct->self = EDICT_TO_PROG(sv_player);
-                       PR_ExecuteProgram (RestoreGame);
+                       PR_ExecuteProgram (RestoreGame, "");
                }
        }
        else
@@ -1061,12 +1061,12 @@ void Host_Spawn_f (void)
 
                pr_global_struct->time = sv.time;
                pr_global_struct->self = EDICT_TO_PROG(sv_player);
-               PR_ExecuteProgram (pr_global_struct->ClientConnect);
+               PR_ExecuteProgram (pr_global_struct->ClientConnect, "QC function ClientConnect is missing");
 
                if ((Sys_FloatTime() - host_client->netconnection->connecttime) <= sv.time)
                        Sys_Printf ("%s entered the game\n", host_client->name);
 
-               PR_ExecuteProgram (pr_global_struct->PutClientInServer);        
+               PR_ExecuteProgram (pr_global_struct->PutClientInServer, "QC function PutClientInServer is missing");
        }
 
 
@@ -1469,15 +1469,59 @@ void Host_Viewframe_f (void)
 
 void PrintFrameName (model_t *m, int frame)
 {
-       maliashdr_t     *mheader;
-       maliasframe_t   *frameinfo;
-
-       mheader = (maliashdr_t *)Mod_Extradata (m);
-       if (!mheader)
+       if (m->type != mod_alias)
                return;
-       frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame];
-       
-       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
+       switch(m->aliastype)
+       {
+       case ALIASTYPE_MDL:
+               {
+                       maliashdr_t *mheader;
+                       maliasframe_t *frameinfo;
+
+                       mheader = (maliashdr_t *)Mod_Extradata (m);
+                       if (!mheader)
+                               return;
+                       if (frame < 0 || frame >= mheader->numframes)
+                               frame = 0;
+                       frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame];
+                       
+                       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
+               }
+               break;
+       case ALIASTYPE_MD2:
+               {
+                       md2mem_t *mheader;
+                       md2memframe_t *frameinfo;
+
+                       mheader = (md2mem_t *)Mod_Extradata (m);
+                       if (!mheader)
+                               return;
+                       if (frame < 0 || frame >= mheader->num_frames)
+                               frame = 0;
+                       frameinfo = (md2memframe_t *)(mheader->ofs_frames + (int) mheader) + frame;
+                       
+                       Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
+               }
+               break;
+       case ALIASTYPE_ZYM:
+               {
+                       zymtype1header_t *mheader;
+                       zymscene_t *scene;
+
+                       mheader = (zymtype1header_t *)Mod_Extradata (m);
+                       if (!mheader)
+                               return;
+                       if (frame < 0 || frame >= mheader->numscenes)
+                               frame = 0;
+                       scene = (zymscene_t *)(mheader->lump_scenes.start + (int) mheader) + frame;
+                       
+                       Con_Printf ("frame %i: %s\n", frame, scene->name);
+               }
+               break;
+       default:
+               Con_Printf("frame %i: (unknown alias model type)\n", frame);
+               break;
+       }
 }
 
 /*
index d3cb6e782e0f8eddb5b2103401a0a8b32fb6853b..de5b65e722eebfebd6ae9a4cc86685c1207a8a6c 100644 (file)
@@ -275,12 +275,86 @@ int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits
                return 0;
 }
 
+int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
+{
+       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)
+                       return true;
+               in++;
+       }
+       return false;
+}
+
+void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, int *skintexnum)
+{
+#if 0
+       int skin_normal, skin_pants, skin_shirt, skin_glow, skin_body, temp;
+       skin_normal = loadtextureimage(va("%s_normal", basename));
+       skin_pants  = loadtextureimage(va("%s_pants" , basename));
+       skin_shirt  = loadtextureimage(va("%s_shirt" , basename));
+       skin_glow   = loadtextureimage(va("%s_glow"  , basename));
+       skin_body   = loadtextureimage(va("%s_body"  , basename));
+       if (!(skin_normal || skin_pants || skin_shirt || skin_glow || skin_body))
+               skin_body = loadtextureimage(name);
+       if (skin_normal || skin_pants || skin_shirt || skin_glow || skin_body)
+       {
+               skintexnum[0] = skin_normal;
+               skintexnum[1] = skin_pants;
+               skintexnum[2] = skin_shirt;
+               skintexnum[3] = skin_glow;
+               skintexnum[4] = skin_body;
+       }
+       else
+       {
+               Mod_FloodFillSkin(skin, width, height);
+               skin_normal = GL_SkinCheck((byte *)pskintype, width, height, 0x3FBD);
+               skin_pants = GL_SkinCheck((byte *)pskintype, width, height, 0x0040);
+               skin_shirt = GL_SkinCheck((byte *)pskintype, width, height, 0x0002);
+               skin_glow = GL_SkinCheck((byte *)pskintype, width, height, 0xC000);
+               skin_body = GL_SkinCheck((byte *)pskintype, width, height, 0x3FFF);
+               if (skin_pants || skin_shirt)
+               {
+                       byte *saveskin;
+                       saveskin = Hunk_AllocName(width*height, va("%s skin", loadname));
+                       memcpy((saveskin, byte *)pskintype, width*height);
+                       temp = (int) saveskin - (int) mheader;
+                       skintexnum[0] = skin_normal ? -temp : 0;
+                       skintexnum[1] = skin_pants ? -temp : 0;
+                       skintexnum[2] = skin_shirt ? -temp : 0;
+                       skintexnum[3] = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow", basename)); // glow
+                       skintexnum[4] = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body", basename)); // body (normal + pants + shirt, but not glow)
+               }
+               else
+               {
+                       skintexnum[0] = 0;
+                       skintexnum[1] = 0;
+                       skintexnum[2] = 0;
+                       skintexnum[3] = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow", basename)); // glow
+                       skintexnum[4] = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body", basename)); // body (normal + pants + shirt, but not glow)
+               }
+       }
+#else
+       skintexnum[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FBD, va("&%s_normal", basename)); // normal (no special colors)
+       skintexnum[1] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("&%s_pants", basename)); // pants
+       skintexnum[2] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("&%s_shirt", basename)); // shirt
+       skintexnum[3] = GL_SkinSplit(skindata, skintemp, width, height, 0xC000, va("%s_glow", basename)); // glow
+       skintexnum[4] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename)); // body (normal + pants + shirt, but not glow)
+#endif
+}
+
 /*
 ===============
 Mod_LoadAllSkins
 ===============
 */
-void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int width, int height)
+void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height)
 {
        int             i, j;
        char    name[32];
@@ -338,13 +412,8 @@ void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int width, in
                        *skinrange++ = 1; // single skin
                        skinnum++;
                        sprintf (name, "%s_%i", loadmodel->name, i);
-
-                       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)
+                       Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum);
+                       skintexnum += 5;
                        pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                }
                else
@@ -360,14 +429,9 @@ void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int width, in
                        skinnum += groupskins;
                        for (j = 0;j < groupskins;j++)
                        {
-                               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)
+                               sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
+                               Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum);
+                               skintexnum += 5;
                                pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
                        }
                }
@@ -426,7 +490,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
                Host_Error ("%s has wrong version number (%i should be %i)",
                                 mod->name, version, ALIAS_VERSION);
 
-       mod->type = ALIASTYPE_MDL;
+       mod->type = mod_alias;
+       mod->aliastype = ALIASTYPE_MDL;
 
        numframes = LittleLong(pinmodel->numframes);
        BOUNDI(numframes,0,65536);
@@ -483,7 +548,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
 
        // load the skins
        pskintype = (daliasskintype_t *)&pinmodel[1];
-       pskintype = Mod_LoadAllSkins(numskins, pskintype, skinwidth, skinheight);
+       pskintype = Mod_LoadAllSkins(mheader, numskins, pskintype, skinwidth, skinheight);
 
        // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data)
        pinstverts = (stvert_t *)pskintype;
@@ -805,6 +870,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        {
                for (j = 0;j < 3;j++)
                {
+                       strcpy(poutframe->name, pinframe->name);
                        poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
                        poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
                }
@@ -838,3 +904,164 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 
        Hunk_FreeToLowMark (start);
 }
+
+void swapintblock(int *m, int size)
+{
+       size /= 4;
+       while(size--)
+               *m++ = BigLong(*m);
+}
+
+void Mod_LoadZymoticModel (model_t *mod, void *buffer)
+{
+       int i, pbase, start, end, total, *skin, *skinrange, *texturenum;
+       char *shadername;
+       zymtype1header_t *pinmodel, *pheader;
+       zymscene_t *scene;
+       zymbone_t *bone;
+
+       start = Hunk_LowMark ();
+
+       pinmodel = (void *)buffer;
+
+       if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
+               Host_Error ("Mod_LoadZymoticModel: %s is not a zymotic model\n");
+
+       if (BigLong(pinmodel->type) != 1)
+               Host_Error ("Mod_LoadZymoticModel: only type 1 (skeletal pose) models are currently supported\n");
+
+       mod->type = mod_alias;
+       mod->aliastype = ALIASTYPE_ZYM;
+
+       pheader = Hunk_AllocName (BigLong(pinmodel->filesize), va("%s Zymotic model", loadname));
+
+       pbase = (int) pheader;
+
+       memcpy(pheader, pinmodel, BigLong(pinmodel->filesize));
+
+       // byteswap header
+       memcpy(pheader->id, pinmodel->id, 12);
+       pheader->type = BigLong(pheader->type);
+       pheader->filesize = BigLong(pheader->filesize);
+       pheader->mins[0] = BigFloat(pheader->mins[0]);
+       pheader->mins[1] = BigFloat(pheader->mins[1]);
+       pheader->mins[2] = BigFloat(pheader->mins[2]);
+       pheader->maxs[0] = BigFloat(pheader->maxs[0]);
+       pheader->maxs[1] = BigFloat(pheader->maxs[1]);
+       pheader->maxs[2] = BigFloat(pheader->maxs[2]);
+       pheader->radius = BigFloat(pheader->radius);
+       pheader->numverts = BigLong(pheader->numverts);
+       pheader->numtris = BigLong(pheader->numtris);
+       pheader->numshaders = BigLong(pheader->numshaders);
+       pheader->numbones = BigLong(pheader->numbones);
+       pheader->numscenes = BigLong(pheader->numscenes);
+
+
+       pheader->lump_scenes.start = BigLong(pheader->lump_scenes.start);pheader->lump_scenes.length = BigLong(pheader->lump_scenes.length);
+       pheader->lump_poses.start = BigLong(pheader->lump_poses.start);pheader->lump_poses.length = BigLong(pheader->lump_poses.length);
+       pheader->lump_bones.start = BigLong(pheader->lump_bones.start);pheader->lump_bones.length = BigLong(pheader->lump_bones.length);
+       pheader->lump_vertbonecounts.start = BigLong(pheader->lump_vertbonecounts.start);pheader->lump_vertbonecounts.length = BigLong(pheader->lump_vertbonecounts.length);
+       pheader->lump_verts.start = BigLong(pheader->lump_verts.start);pheader->lump_verts.length = BigLong(pheader->lump_verts.length);
+       pheader->lump_texcoords.start = BigLong(pheader->lump_texcoords.start);pheader->lump_texcoords.length = BigLong(pheader->lump_texcoords.length);
+       pheader->lump_render.start = BigLong(pheader->lump_render.start);pheader->lump_render.length = BigLong(pheader->lump_render.length);
+       pheader->lump_shaders.start = BigLong(pheader->lump_shaders.start);pheader->lump_shaders.length = BigLong(pheader->lump_shaders.length);
+       pheader->lump_trizone.start = BigLong(pheader->lump_trizone.start);pheader->lump_trizone.length = BigLong(pheader->lump_trizone.length);
+
+       mod->flags = 0; // there are no flags
+       mod->numframes = pheader->numscenes;
+       mod->synctype = ST_SYNC;
+       mod->numtris = pheader->numtris;
+
+       // FIXME: add skin support and texturing and shaders and...
+// load the skins
+       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;
+       *skinrange++ = 0;
+       *skinrange++ = 1;
+       *skin++ = 0;
+       *skin++ = 0;
+       *skin++ = 0;
+       *skin++ = 0;
+       *skin++ = 0;
+       loadmodel->numskins = 1;
+
+       // go through the lumps, swapping things
+
+//     zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
+       scene = (void *) (pheader->lump_scenes.start + pbase);
+       for (i = 0;i < pheader->numscenes;i++)
+       {
+               scene->mins[0] = BigFloat(scene->mins[0]);
+               scene->mins[1] = BigFloat(scene->mins[1]);
+               scene->mins[2] = BigFloat(scene->mins[2]);
+               scene->maxs[0] = BigFloat(scene->maxs[0]);
+               scene->maxs[1] = BigFloat(scene->maxs[1]);
+               scene->maxs[2] = BigFloat(scene->maxs[2]);
+               scene->radius = BigFloat(scene->radius);
+               scene->framerate = BigFloat(scene->framerate);
+               scene->flags = BigLong(scene->flags);
+               scene->start = BigLong(scene->start);
+               scene->length = BigLong(scene->length);
+               scene++;
+       }
+
+//     zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data
+       swapintblock((void *) (pheader->lump_poses.start + pbase), pheader->lump_poses.length);
+
+//     zymlump_t lump_bones; // zymbone_t bone[numbones];
+       bone = (void *) (pheader->lump_bones.start + pbase);
+       for (i = 0;i < pheader->numbones;i++)
+       {
+               bone->flags = BigLong(bone->flags);
+               bone->parent = BigLong(bone->parent);
+               bone++;
+       }
+
+//     zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
+       swapintblock((void *) (pheader->lump_vertbonecounts.start + pbase), pheader->lump_vertbonecounts.length);
+
+//     zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
+       swapintblock((void *) (pheader->lump_verts.start + pbase), pheader->lump_verts.length);
+
+//     zymlump_t lump_texcoords; // float texcoords[numvertices][2];
+       swapintblock((void *) (pheader->lump_texcoords.start + pbase), pheader->lump_texcoords.length);
+
+//     zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int shader, count), each run can be used with glDrawElements (each triangle is 3 int indices)
+       swapintblock((void *) (pheader->lump_render.start + pbase), pheader->lump_render.length);
+
+//     zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
+       shadername = (void *) (pheader->lump_shaders.start + pbase);
+       texturenum = (void *) shadername;
+       for (i = 0;i < pheader->numshaders;i++)
+       {
+               int j;
+               j = loadtextureimage(shadername, 0, 0, true, true);
+               shadername += 32;
+               *texturenum++ = j; // reuse shader name list for texture numbers
+       }
+
+//     zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
+       swapintblock((void *) (pheader->lump_trizone.start + pbase), pheader->lump_trizone.length);
+
+       // model bbox
+       for (i = 0;i < 3;i++)
+       {
+               mod->mins[i] = pheader->mins[i];
+               mod->maxs[i] = pheader->maxs[i];
+       }
+
+// move the complete, relocatable alias model to the cache
+       end = Hunk_LowMark ();
+       total = end - start;
+       
+       Cache_Alloc (&mod->cache, total, loadname);
+       if (!mod->cache.data)
+               return;
+       memcpy (mod->cache.data, pheader, total);
+
+       Hunk_FreeToLowMark (start);
+}
index 2b0031e200724c959cbc0e81db375628f0daad86..73e831076c7cad76ac10dbee94dbb999fbd7ab9e 100644 (file)
@@ -159,6 +159,7 @@ typedef struct
 {
        float           scale[3];       // multiply byte verts by this
        float           translate[3];   // then add this
+       char            name[16];       // LordHavoc: kept for viewthing
        trivert2        verts[1];       // variable sized
 } md2memframe_t;
 
@@ -221,3 +222,6 @@ typedef struct
 
 #define ALIASTYPE_MDL 1
 #define ALIASTYPE_MD2 2
+#define ALIASTYPE_ZYM 3
+
+#include "model_zymotic.h"
\ No newline at end of file
index 172ae413a927bad33be27b3a85d716d244023a84..2ca09612d0ff60e0feff67193c26c3778ce20d67 100644 (file)
@@ -135,7 +135,8 @@ typedef struct msurface_s
        int                     lightmaptexturenum;
        byte            styles[MAXLIGHTMAPS];
        unsigned short  cached_light[MAXLIGHTMAPS];     // values currently used in lightmap
-       int                     cached_lighthalf;                       // LordHavoc: to cause lightmap to be rerendered when lighthalf changes
+       short           cached_dlight;                          // LordHavoc: if lightmap was lit by dynamic lights, update on frame after end of effect to erase it
+       short           cached_lighthalf;                       // LordHavoc: to cause lightmap to be rerendered when lighthalf changes
        float           cached_ambient;                         // LordHavoc: rerender lightmaps when r_ambient changes
        byte            *samples;               // [numstyles*surfsize]
 } msurface_t;
index 236a5d60649be6b46d65558f05a25082fd9cd12a..65acc092ded219f785bac43cadbdaf6c2c488e6e 100644 (file)
@@ -27,10 +27,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 model_t        *loadmodel;
 char   loadname[32];   // for hunk tags
 
-void Mod_LoadSpriteModel (model_t *mod, void *buffer);
-void Mod_LoadBrushModel (model_t *mod, void *buffer);
-void Mod_LoadAliasModel (model_t *mod, void *buffer);
-void Mod_LoadQ2AliasModel (model_t *mod, void *buffer);
+extern void Mod_LoadSpriteModel (model_t *mod, void *buffer);
+extern void Mod_LoadBrushModel (model_t *mod, void *buffer);
+extern void Mod_LoadAliasModel (model_t *mod, void *buffer);
+extern void Mod_LoadQ2AliasModel (model_t *mod, void *buffer);
+extern void Mod_LoadZymoticModel (model_t *mod, void *buffer);
 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
 
 #define        MAX_MOD_KNOWN   512
@@ -194,6 +195,10 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
        case MD2IDALIASHEADER: // LordHavoc: added Quake2 model support
                Mod_LoadQ2AliasModel (mod, buf);
                break;
+
+       case (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'):
+               Mod_LoadZymoticModel(mod, buf);
+               break;
                
        case IDSPRITEHEADER:
                Mod_LoadSpriteModel (mod, buf);
index 0bb47d99be013566ef4ce6c0a703018d55ec1bd2..0488c176a985883d2bf0ed856974e2e8692c1ee7 100644 (file)
@@ -1086,7 +1086,7 @@ void ED_LoadFromFile (char *data)
                }
 
                pr_global_struct->self = EDICT_TO_PROG(ent);
-               PR_ExecuteProgram (func - pr_functions);
+               PR_ExecuteProgram (func - pr_functions, "");
        }       
 
        Con_DPrintf ("%i entities inhibited\n", inhibit);
index a608a074cd24bafe558cac5a4d363778a891525a..e70f158159ddc69e9cfca1e51d6a07fce6669c19 100644 (file)
--- a/pr_exec.c
+++ b/pr_exec.c
@@ -363,7 +363,7 @@ PR_ExecuteProgram
 #define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
 #define OPC ((eval_t *)&pr_globals[(unsigned short) st->c])
 extern cvar_t pr_boundscheck;
-void PR_ExecuteProgram (func_t fnum)
+void PR_ExecuteProgram (func_t fnum, char *errormessage)
 {
        dstatement_t    *st;
        dfunction_t     *f, *newf;
@@ -376,7 +376,7 @@ void PR_ExecuteProgram (func_t fnum)
        {
                if (pr_global_struct->self)
                        ED_Print (PROG_TO_EDICT(pr_global_struct->self));
-               Host_Error ("PR_ExecuteProgram: NULL function");
+               Host_Error ("PR_ExecuteProgram: %s", errormessage);
        }
        
        f = &pr_functions[fnum];
diff --git a/progs.h b/progs.h
index 2d39385a6e76a55a8f9231478440ed0e0044b366..278447b2e6e1c0ebd6ccc6d3bffdd3a9412f3e9e 100644 (file)
--- a/progs.h
+++ b/progs.h
@@ -110,7 +110,7 @@ extern      int                             pr_edictareasize; // LordHavoc: for bounds checking
 
 void PR_Init (void);
 
-void PR_ExecuteProgram (func_t fnum);
+void PR_ExecuteProgram (func_t fnum, char *errormessage);
 void PR_LoadProgs (void);
 
 void PR_Profile_f (void);
index 04504d212b91b1bc36b31615b56ecf6adb95005f..7d259b76bcea98c80bbedc2ff92c1e37704c9b64 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 
 cvar_t r_lightmodels = {"r_lightmodels", "1"};
+cvar_t r_modelsdonttransformnormals = {"r_modelsdonttransformnormals", "0"};
 
 void r_light_start()
 {
@@ -34,6 +35,7 @@ void r_light_shutdown()
 void R_Light_Init()
 {
        Cvar_RegisterVariable(&r_lightmodels);
+       Cvar_RegisterVariable(&r_modelsdonttransformnormals);
        R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
 }
 
@@ -81,17 +83,27 @@ R_MarkLights
 */
 void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, mnode_t *node)
 {
-       float           dist;
+       float           ndist, maxdist;
        msurface_t      *surf;
        int                     i;
 
+       if (!r_dynamic.value)
+               return;
+
+       // for comparisons to minimum acceptable light
+       maxdist = light->radius * light->radius * LIGHTSCALE;
+
+       // clamp radius to avoid exceeding 32768 entry division table
+       if (maxdist > 4194304)
+               maxdist = 4194304;
+
 loc0:
        if (node->contents < 0)
                return;
 
-       dist = PlaneDiff(lightorigin, node->plane);
+       ndist = PlaneDiff(lightorigin, node->plane);
        
-       if (dist > light->radius)
+       if (ndist > light->radius)
        {
                if (node->children[0]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
                {
@@ -100,7 +112,7 @@ loc0:
                }
                return;
        }
-       if (dist < -light->radius)
+       if (ndist < -light->radius)
        {
                if (node->children[1]->contents >= 0) // LordHavoc: save some time by not pushing another stack frame
                {
@@ -121,6 +133,69 @@ loc0:
        surf = cl.worldmodel->surfaces + node->firstsurface;
        for (i=0 ; i<node->numsurfaces ; i++, surf++)
        {
+               int d;
+               float dist, dist2, impact[3];
+               dist = ndist;
+               if (surf->flags & SURF_PLANEBACK)
+                       dist = -dist;
+
+               if (dist < -0.25f)
+                       continue;
+
+               dist2 = dist * dist;
+               if (dist2 >= maxdist)
+                       continue;
+
+               impact[0] = light->origin[0] - surf->plane->normal[0] * dist;
+               impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
+               impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
+
+               d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+               if (d < 0)
+               {
+                       dist2 += d * d;
+                       if (dist2 >= maxdist)
+                               continue;
+               }
+               else
+               {
+                       d -= surf->extents[0] + 16;
+                       if (d > 0)
+                       {
+                               dist2 += d * d;
+                               if (dist2 >= maxdist)
+                                       continue;
+                       }
+               }
+
+               d = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+               if (d < 0)
+               {
+                       dist2 += d * d;
+                       if (dist2 >= maxdist)
+                               continue;
+               }
+               else
+               {
+                       d -= surf->extents[1] + 16;
+                       if (d > 0)
+                       {
+                               dist2 += d * d;
+                               if (dist2 >= maxdist)
+                                       continue;
+                       }
+               }
+
+               if (surf->dlightframe != r_dlightframecount) // not dynamic until now
+               {
+                       surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
+                       surf->dlightframe = r_dlightframecount;
+               }
+               surf->dlightbits[bitindex] |= bit;
+
+               /*
                if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist))
                {
                        if (surf->dlightframe != r_dlightframecount) // not dynamic until now
@@ -130,6 +205,7 @@ loc0:
                        }
                        surf->dlightbits[bitindex] |= bit;
                }
+               */
        }
 
        if (node->children[0]->contents >= 0)
@@ -163,6 +239,9 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
 {
        mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
 
+       if (!r_dynamic.value)
+               return;
+
        if (!pvsleaf->compressed_vis)
        {       // no vis info, so make all visible
                R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
@@ -175,12 +254,20 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex
                mleaf_t *leaf;
                byte    *in = pvsleaf->compressed_vis;
                int             row = (model->numleafs+7)>>3;
-               float   low[3], high[3], radius;
+               float   low[3], high[3], radius, dist, maxdist;
+
+               radius = light->radius * LIGHTSCALE1;
+
+               // clamp radius to avoid exceeding 32768 entry division table
+               if (radius > 2048)
+                       radius = 2048;
 
-               radius = light->radius * 4.0f;
                low[0] = lightorigin[0] - radius;low[1] = lightorigin[1] - radius;low[2] = lightorigin[2] - radius;
                high[0] = lightorigin[0] + radius;high[1] = lightorigin[1] + radius;high[2] = lightorigin[2] + radius;
 
+               // for comparisons to minimum acceptable light
+               maxdist = radius*radius;
+
                lightframe++;
                k = 0;
                while (k < row)
@@ -202,12 +289,10 @@ 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;
@@ -223,8 +308,59 @@ 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) == ((PlaneDist(lightorigin, surf->plane)) >= surf->plane->dist))
+                                                               dist = PlaneDiff(lightorigin, surf->plane);
+                                                               if (surf->flags & SURF_PLANEBACK)
+                                                                       dist = -dist;
+                                                               // LordHavoc: make sure it is infront of the surface and not too far away
+                                                               if (dist >= -0.25f && dist < radius)
                                                                {
+                                                                       int d;
+                                                                       float dist2, impact[3];
+
+                                                                       dist2 = dist * dist;
+
+                                                                       impact[0] = light->origin[0] - surf->plane->normal[0] * dist;
+                                                                       impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
+                                                                       impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
+
+                                                                       d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+                                                                       if (d < 0)
+                                                                       {
+                                                                               dist2 += d * d;
+                                                                               if (dist2 >= maxdist)
+                                                                                       continue;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               d -= surf->extents[0] + 16;
+                                                                               if (d > 0)
+                                                                               {
+                                                                                       dist2 += d * d;
+                                                                                       if (dist2 >= maxdist)
+                                                                                               continue;
+                                                                               }
+                                                                       }
+
+                                                                       d = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+                                                                       if (d < 0)
+                                                                       {
+                                                                               dist2 += d * d;
+                                                                               if (dist2 >= maxdist)
+                                                                                       continue;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               d -= surf->extents[1] + 16;
+                                                                               if (d > 0)
+                                                                               {
+                                                                                       dist2 += d * d;
+                                                                                       if (dist2 >= maxdist)
+                                                                                               continue;
+                                                                               }
+                                                                       }
+
                                                                        if (surf->dlightframe != r_dlightframecount) // not dynamic until now
                                                                        {
                                                                                surf->dlightbits[0] = surf->dlightbits[1] = surf->dlightbits[2] = surf->dlightbits[3] = surf->dlightbits[4] = surf->dlightbits[5] = surf->dlightbits[6] = surf->dlightbits[7] = 0;
@@ -625,6 +761,7 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p)
 }
 
 extern float *aliasvert;
+extern float *modelaliasvert;
 extern float *aliasvertnorm;
 extern byte *aliasvertcolor;
 extern float modelalpha;
@@ -681,7 +818,7 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
        basecolor[0] *= mod[0];
        basecolor[1] *= mod[1];
        basecolor[2] *= mod[2];
-       if (r_lightmodels.value)
+       if (!r_lightmodels.value)
        {
                for (i = 0;i < MAX_DLIGHTS;i++)
                {
@@ -694,20 +831,28 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                                continue;
                        VectorSubtract (center, cl_dlights[i].origin, dist);
                        t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
-                       t2 = DotProduct(dist,dist) + LIGHTOFFSET;
+                       t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + 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 * 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 / LIGHTSCALE2) / t2;
-                               basecolor[0] += nearlight[nearlights].color[0] * t1;
-                               basecolor[1] += nearlight[nearlights].color[1] * t1;
-                               basecolor[2] += nearlight[nearlights].color[2] * t1;
-                               nearlights++;
+                               dist[0] = cl_dlights[i].color[0] * t1 * mod[0];
+                               dist[1] = cl_dlights[i].color[1] * t1 * mod[1];
+                               dist[2] = cl_dlights[i].color[2] * t1 * mod[2];
+                               t1 = (224.0f / LIGHTSCALE / LIGHTSCALE) / t2;
+                               basecolor[0] += dist[0] * t1;
+                               basecolor[1] += dist[1] * t1;
+                               basecolor[2] += dist[2] * t1;
                        }
                }
+               ((byte *)&color)[0] = bound(0, basecolor[0], 255);
+               ((byte *)&color)[1] = bound(0, basecolor[1], 255);
+               ((byte *)&color)[2] = bound(0, basecolor[2], 255);
+               ((byte *)&color)[3] = a;
+               for (i = 0;i < numverts;i++)
+               {
+                       *((int *)avc) = color;
+                       avc += 4;
+               }
+               return;
        }
        else
        {
@@ -722,16 +867,23 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                                continue;
                        VectorSubtract (center, cl_dlights[i].origin, dist);
                        t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
-                       t2 = DotProduct(dist,dist) + LIGHTOFFSET;
+                       t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + LIGHTOFFSET;
                        if (t2 < 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 = (224.0f / LIGHTSCALE2) / t2;
-                               basecolor[0] += dist[0] * t1;
-                               basecolor[1] += dist[1] * t1;
-                               basecolor[2] += dist[2] * t1;
+                               if (r_modelsdonttransformnormals.value)
+                                       softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin);
+                               else
+                               {
+                                       VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
+                               }
+                               nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
+                               nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
+                               nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
+//                             t1 = (128.0f / LIGHTSCALE2) / t2;
+//                             basecolor[0] += nearlight[nearlights].color[0] * t1;
+//                             basecolor[1] += nearlight[nearlights].color[1] * t1;
+//                             basecolor[2] += nearlight[nearlights].color[2] * t1;
+                               nearlights++;
                        }
                }
        }
@@ -747,7 +899,10 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                int temp;
                vec3_t v;
                float *av;
-               av = aliasvert;
+               if (r_modelsdonttransformnormals.value)
+                       av = modelaliasvert;
+               else
+                       av = aliasvert;
                if (nearlights == 1)
                {
                        for (i = 0;i < numverts;i++)
@@ -765,8 +920,8 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                                else
                                        *((int *)avc) = color;
                                avc += 4;
-                               av+=3;
-                               avn+=3;
+                               av += 3;
+                               avn += 3;
                        }
                }
                else
@@ -791,16 +946,18 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
                                                k = true;
                                        }
                                }
-                               if (k) // dodge the costly float -> int conversions
+                               if (k)
                                {
                                        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
+                               else // dodge the costly float -> int conversions
                                        *((int *)avc) = color;
                                avc += 4;
+                               av += 3;
+                               avn += 3;
                        }
                }
        }
index bd8167be7a87adfe31cf2316ad5591d7ab6de57d..509fe6440c4c98be7d2ccec158c0973aa89c2614 100644 (file)
--- a/r_light.h
+++ b/r_light.h
@@ -13,6 +13,9 @@ typedef struct
 } dlight_t;
 
 // LordHavoc: this affects the lighting scale of the whole game
-#define LIGHTOFFSET 16384.0f
-#define LIGHTSCALE 4.0f
-#define LIGHTSCALE2 4.0f
+//#define LIGHTOFFSET 16384.0f
+//#define LIGHTSCALE1 2.0f
+#define LIGHTOFFSET 4096.0f
+#define LIGHTSCALE1 1.0f
+#define LIGHTSCALE (LIGHTSCALE1*LIGHTSCALE1)
+#define LIGHTSCALE2 LIGHTSCALE
index 7f8627c96238dfd0223ef1b544f72366d0340d2e..1acfbc20ba91bc7a18b8077210a6d95d434f20d4 100644 (file)
--- a/r_part.c
+++ b/r_part.c
@@ -24,9 +24,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define ABSOLUTE_MIN_PARTICLES 512             // no fewer than this no matter what's on the command line
 
 // LordHavoc: added dust, smoke, snow, bloodcloud, and many others
-typedef enum {
-       pt_static, pt_grav, pt_blob, pt_blob2, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash
-} ptype_t;
+typedef enum
+{
+       pt_static, pt_grav, pt_blob, pt_blob2, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_flamingdebris, pt_smokingdebris, pt_flamefall
+}
+ptype_t;
 
 typedef struct particle_s
 {
@@ -37,11 +39,15 @@ typedef struct particle_s
        ptype_t         type;
        float           scale;
        short           texnum;
+       short           dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
        float           alpha; // 0-255
        float           time2; // used for various things (snow fluttering, for example)
        vec3_t          oldorg;
        vec3_t          vel2; // used for snow fluttering (base velocity, wind for instance)
-} particle_t;
+}
+particle_t;
+
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
 
 int            ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
 int            ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
@@ -51,6 +57,8 @@ int           particletexture;
 int            smokeparticletexture[8];
 int            rainparticletexture;
 int            bubbleparticletexture;
+int            explosiontexture;
+int            explosiontexturefog;
 
 particle_t     *particles;
 int                    r_numparticles;
@@ -61,12 +69,13 @@ int                 numparticles;
 particle_t     **freeparticles; // list used only in compacting particles array
 
 // LordHavoc: reduced duplicate code, and allow particle allocation system independence
-#define ALLOCPARTICLE \
+#define ALLOCPARTICLE(part) \
        if (numparticles >= r_numparticles)\
                return;\
-       p = &particles[numparticles++];
+       (part) = &particles[numparticles++];
 
 cvar_t r_particles = {"r_particles", "1"};
+cvar_t r_drawparticles = {"r_drawparticles", "1"};
 cvar_t r_dynamicparticles = {"r_dynamicparticles", "0", TRUE};
 
 byte shadebubble(float dx, float dy, vec3_t light)
@@ -191,11 +200,13 @@ void r_part_start()
 {
        particles = (particle_t *) qmalloc(r_numparticles * sizeof(particle_t));
        freeparticles = (void *) qmalloc(r_numparticles * sizeof(particle_t *));
+       numparticles = 0;
        R_InitParticleTexture ();
 }
 
 void r_part_shutdown()
 {
+       numparticles = 0;
        qfree(particles);
        qfree(freeparticles);
 }
@@ -226,118 +237,66 @@ void R_Particles_Init (void)
        Cmd_AddCommand ("pointfile", R_ReadPointFile_f);        
 
        Cvar_RegisterVariable (&r_particles);
+       Cvar_RegisterVariable (&r_drawparticles);
        Cvar_RegisterVariable (&r_dynamicparticles);
 
        R_RegisterModule("R_Particles", r_part_start, r_part_shutdown);
 }
 
-#define particle(ptype, pcolor, ptex, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\
+#define particle(ptype, pcolor, ptex, plight, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\
 {\
-       particle_t      *p;\
-       ALLOCPARTICLE\
-       p->type = (ptype);\
-       p->color = (pcolor);\
-       p->texnum = (ptex);\
-       p->scale = (pscale);\
-       p->alpha = (palpha);\
-       p->die = cl.time + (ptime);\
-       p->org[0] = (px);\
-       p->org[1] = (py);\
-       p->org[2] = (pz);\
-       p->vel[0] = (pvx);\
-       p->vel[1] = (pvy);\
-       p->vel[2] = (pvz);\
+       particle_t      *part;\
+       ALLOCPARTICLE(part)\
+       part->type = (ptype);\
+       part->color = (pcolor);\
+       part->texnum = (ptex);\
+       part->dynlight = (plight);\
+       part->scale = (pscale);\
+       part->alpha = (palpha);\
+       part->die = cl.time + (ptime);\
+       part->org[0] = (px);\
+       part->org[1] = (py);\
+       part->org[2] = (pz);\
+       part->vel[0] = (pvx);\
+       part->vel[1] = (pvy);\
+       part->vel[2] = (pvz);\
 }
-#define particle2(ptype, pcolor, ptex, pscale, palpha, ptime, pbase, poscale, pvscale)\
+#define particle2(ptype, pcolor, ptex, plight, pscale, palpha, ptime, pbase, poscale, pvscale)\
 {\
-       particle_t      *p;\
-       ALLOCPARTICLE\
-       p->type = (ptype);\
-       p->color = (pcolor);\
-       p->texnum = (ptex);\
-       p->scale = (pscale);\
-       p->alpha = (palpha);\
-       p->die = cl.time + (ptime);\
-       p->org[0] = lhrandom(-(poscale), (poscale)) + (pbase)[0];\
-       p->org[1] = lhrandom(-(poscale), (poscale)) + (pbase)[1];\
-       p->org[2] = lhrandom(-(poscale), (poscale)) + (pbase)[2];\
-       p->vel[0] = lhrandom(-(pvscale), (pvscale));\
-       p->vel[1] = lhrandom(-(pvscale), (pvscale));\
-       p->vel[2] = lhrandom(-(pvscale), (pvscale));\
+       particle_t      *part;\
+       ALLOCPARTICLE(part)\
+       part->type = (ptype);\
+       part->color = (pcolor);\
+       part->texnum = (ptex);\
+       part->dynlight = (plight);\
+       part->scale = (pscale);\
+       part->alpha = (palpha);\
+       part->die = cl.time + (ptime);\
+       part->org[0] = lhrandom(-(poscale), (poscale)) + (pbase)[0];\
+       part->org[1] = lhrandom(-(poscale), (poscale)) + (pbase)[1];\
+       part->org[2] = lhrandom(-(poscale), (poscale)) + (pbase)[2];\
+       part->vel[0] = lhrandom(-(pvscale), (pvscale));\
+       part->vel[1] = lhrandom(-(pvscale), (pvscale));\
+       part->vel[2] = lhrandom(-(pvscale), (pvscale));\
 }
-#define particle3(ptype, pcolor, ptex, pscale, palpha, ptime, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
+#define particle3(ptype, pcolor, ptex, plight, pscale, palpha, ptime, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
 {\
-       particle_t      *p;\
-       ALLOCPARTICLE\
-       p->type = (ptype);\
-       p->color = (pcolor);\
-       p->texnum = (ptex);\
-       p->scale = (pscale);\
-       p->alpha = (palpha);\
-       p->die = cl.time + (ptime);\
-       p->org[0] = lhrandom(-(pscalex), (pscalex)) + (pbase)[0];\
-       p->org[1] = lhrandom(-(pscaley), (pscaley)) + (pbase)[1];\
-       p->org[2] = lhrandom(-(pscalez), (pscalez)) + (pbase)[2];\
-       p->vel[0] = lhrandom(-(pvscalex), (pvscalex));\
-       p->vel[1] = lhrandom(-(pvscaley), (pvscaley));\
-       p->vel[2] = lhrandom(-(pvscalez), (pvscalez));\
+       particle_t      *part;\
+       ALLOCPARTICLE(part)\
+       part->type = (ptype);\
+       part->color = (pcolor);\
+       part->texnum = (ptex);\
+       part->dynlight = (plight);\
+       part->scale = (pscale);\
+       part->alpha = (palpha);\
+       part->die = cl.time + (ptime);\
+       part->org[0] = lhrandom(-(pscalex), (pscalex)) + (pbase)[0];\
+       part->org[1] = lhrandom(-(pscaley), (pscaley)) + (pbase)[1];\
+       part->org[2] = lhrandom(-(pscalez), (pscalez)) + (pbase)[2];\
+       part->vel[0] = lhrandom(-(pvscalex), (pvscalex));\
+       part->vel[1] = lhrandom(-(pvscaley), (pvscaley));\
+       part->vel[2] = lhrandom(-(pvscalez), (pvscalez));\
 }
-/*
-void particle(int type, int color, int tex, float scale, int alpha, float time, float x, float y, float z, float vx, float vy, float vz)
-{
-       particle_t      *p;
-       ALLOCPARTICLE
-
-       p->type = type;
-       p->color = color;
-       p->texnum = tex;
-       p->scale = scale;
-       p->alpha = alpha;
-       p->die = cl.time + time;
-       p->org[0] = x;
-       p->org[1] = y;
-       p->org[2] = z;
-       p->vel[0] = vx;
-       p->vel[1] = vy;
-       p->vel[2] = vz;
-}
-void particle2(int type, int color, int tex, float scale, int alpha, float time, vec3_t base, float oscale, float vscale)
-{
-       particle_t      *p;
-       ALLOCPARTICLE
-
-       p->type = type;
-       p->color = color;
-       p->texnum = tex;
-       p->scale = scale;
-       p->alpha = alpha;
-       p->die = cl.time + time;
-       p->org[0] = lhrandom(-oscale, oscale) + base[0];
-       p->org[1] = lhrandom(-oscale, oscale) + base[1];
-       p->org[2] = lhrandom(-oscale, oscale) + base[2];
-       p->vel[0] = lhrandom(-vscale, vscale);
-       p->vel[1] = lhrandom(-vscale, vscale);
-       p->vel[2] = lhrandom(-vscale, vscale);
-}
-void particle3(int type, int color, int tex, float scale, int alpha, float time, vec3_t base, float scalex, float scaley, float scalez, float vscalex, float vscaley, float vscalez)
-{
-       particle_t      *p;
-       ALLOCPARTICLE
-
-       p->type = type;
-       p->color = color;
-       p->texnum = tex;
-       p->scale = scale;
-       p->alpha = alpha;
-       p->die = cl.time + time;
-       p->org[0] = lhrandom(-scalex, scalex) + base[0];
-       p->org[1] = lhrandom(-scaley, scaley) + base[1];
-       p->org[2] = lhrandom(-scalez, scalez) + base[2];
-       p->vel[0] = lhrandom(-vscalex, vscalex);
-       p->vel[1] = lhrandom(-vscaley, vscaley);
-       p->vel[2] = lhrandom(-vscalez, vscalez);
-}
-*/
 
 /*
 ===============
@@ -383,7 +342,7 @@ void R_EntityParticles (entity_t *ent)
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               particle(pt_static, 0x6f, particletexture, 2, 255, 0, ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
+               particle(pt_static, 0x6f, particletexture, false, 2, 255, 0, ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
        }
 }
 
@@ -438,7 +397,7 @@ void R_ReadPointFile_f (void)
                        Con_Printf ("Not enough free particles\n");
                        break;
                }
-               particle(pt_static, (-c)&15, particletexture, 2, 255, 99999, org[0], org[1], org[2], 0, 0, 0);
+               particle(pt_static, (-c)&15, particletexture, false, 2, 255, 99999, org[0], org[1], org[2], 0, 0, 0);
        }
 
        fclose (f);
@@ -480,23 +439,58 @@ R_ParticleExplosion
 */
 void R_ParticleExplosion (vec3_t org, int smoke)
 {
-       int                     i;
+       int i;
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       particle(pt_smokecloud, (rand()&7) + 8, smokeparticletexture[rand()&7], 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
+//     particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
 
        i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
        if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
        {
                for (i=0 ; i<128 ; i++)
-                       particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, lhrandom(1, 2), 255, 2, org, 16, 96);
+                       particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, false, lhrandom(1, 2), 255, 2, org, 16, 96);
        }
+       else
+               R_NewExplosion(org);
+       /*
        else
        {
-               for (i = 0;i < 256;i++)
-                       particle(pt_fallfadespark, ramp3[rand()%6], particletexture, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192);
+               int j;
+//             int color;
+               float f, forg[3], fvel[3], fvel2[3];
+//             for (i = 0;i < 256;i++)
+//                     particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192);
+//             for (i = 0;i < 256;i++)
+//                     particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, org, 15, 150);
+               for (i = 0;i < 32;i++)
+               {
+                       fvel[0] = lhrandom(-150, 150);
+                       fvel[1] = lhrandom(-150, 150);
+                       fvel[2] = lhrandom(-150, 150) + 80;
+//                     particle(pt_flamefall, 106 + (rand()%6), particletexture, false, 3, 255, 5, forg[0] + lhrandom(-5, 5), forg[1] + lhrandom(-5, 5), forg[2] + lhrandom(-5, 5), fvel2[0], fvel2[1], fvel2[2]);
+                       for (j = 0;j < 64;j++)
+                       {
+                               forg[0] = lhrandom(-20, 20) + org[0];
+                               forg[1] = lhrandom(-20, 20) + org[1];
+                               forg[2] = lhrandom(-20, 20) + org[2];
+                               fvel2[0] = fvel[0] + lhrandom(-30, 30);
+                               fvel2[1] = fvel[1] + lhrandom(-30, 30);
+                               fvel2[2] = fvel[2] + lhrandom(-30, 30);
+                               f = lhrandom(0.2, 1);
+                               fvel2[0] *= f;
+                               fvel2[1] *= f;
+                               fvel2[2] *= f;
+                               particle(pt_flamefall, 106 + (rand()%6), particletexture, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]);
+                       }
+               }
+//             for (i = 0;i < 16;i++)
+//                     particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 20, 192, 99, org, 20, 0);
+//             for (i = 0;i < 50;i++)
+//                     particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, false, 3, 255, 99, org, 10, 200);
+//             for (i = 0;i < 30;i++)
+//                     particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, false, 2, 255, 99, org, 10, 100);
        }
-
+       */
 }
 
 /*
@@ -511,7 +505,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        for (i = 0;i < 512;i++)
-               particle2(pt_fade, colorStart + (i % colorLength), particletexture, 1.5, 255, 0.3, org, 8, 192);
+               particle2(pt_fade, colorStart + (i % colorLength), particletexture, false, 1.5, 255, 0.3, org, 8, 192);
 }
 
 /*
@@ -526,9 +520,9 @@ void R_BlobExplosion (vec3_t org)
        if (!r_particles.value) return; // LordHavoc: particles are optional
        
        for (i=0 ; i<512 ; i++)
-               particle3(pt_blob, 66+(rand()%6), particletexture, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
+               particle3(pt_blob, 66+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
        for (i=0 ; i<512 ; i++)
-               particle3(pt_blob2, 150+(rand()%6), particletexture, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
+               particle3(pt_blob2, 150+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128);
 }
 
 /*
@@ -549,12 +543,12 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
        color &= ~7;
        if (count & 7)
        {
-               particle2(pt_fade, color + (rand()&7), particletexture, 6, (count & 7) * 16 + (rand()&15), 1, org, 8, 15);
+               particle2(pt_fade, color + (rand()&7), particletexture, false, 6, (count & 7) * 16 + (rand()&15), 1, org, 8, 15);
                count &= ~7;
        }
        count >>= 3;
        while (count--)
-               particle2(pt_fade, color + (rand()&7), particletexture, 6, 128, 1, org, 8, 15);
+               particle2(pt_fade, color + (rand()&7), particletexture, false, 6, 128, 1, org, 8, 15);
 }
 
 // LordHavoc: added this for spawning sparks/dust (which have strong gravity)
@@ -568,20 +562,20 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count)
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
        // smoke puff
-       particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], 8, 160, 99, org[0], org[1], org[2], 0, 0, 0);
+       particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 8, 160, 99, org[0], org[1], org[2], 0, 0, 0);
        // sparks
        while(count--)
-//             particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, 1, lhrandom(0, 255), 5, org, 4, 96);
-               particle(pt_fallfadespark, ramp3[rand()%6], particletexture, 1, lhrandom(0, 255), 5, lhrandom(-4, 4) + org[0], lhrandom(-4, 4) + org[1], lhrandom(-4, 4) + org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 64);
+//             particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, org, 4, 96);
+               particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, lhrandom(-4, 4) + org[0], lhrandom(-4, 4) + org[1], lhrandom(-4, 4) + org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 64);
 }
 
 void R_BloodPuff (vec3_t org)
 {
        if (!r_particles.value) return; // LordHavoc: particles are optional
 
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], 12, 128, 99, org[0], org[1], org[2], 0, 0, 0);
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], 10, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
-       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], 8, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
+       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 12, 128, 99, org[0], org[1], org[2], 0, 0, 0);
+       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 10, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
+       particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 8, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0);
 }
 
 void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
@@ -604,9 +598,10 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
        
        while (count--)
        {
-               ALLOCPARTICLE
+               ALLOCPARTICLE(p)
 
                p->texnum = smokeparticletexture[rand()&7];
+               p->dynlight = true;
                p->scale = lhrandom(4, 6);
                p->alpha = 96 + (rand()&63);
                p->die = cl.time + 2;
@@ -635,9 +630,10 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        
        while (count--)
        {
-               ALLOCPARTICLE
+               ALLOCPARTICLE(p)
 
                p->texnum = particletexture;
+               p->dynlight = false;
                p->scale = 6;
                p->alpha = 255;
                p->die = cl.time + 1 + (rand()&15)*0.0625;
@@ -687,7 +683,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
        
        for (i=0 ; i<count ; i++)
        {
-               ALLOCPARTICLE
+               ALLOCPARTICLE(p)
 
                vel[0] = dir[0] + (rand()&31) - 16;
                vel[1] = dir[1] + (rand()&31) - 16;
@@ -702,12 +698,14 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb
                {
                        p->scale = 2;
                        p->texnum = particletexture;
+                       p->dynlight = false;
                        p->type = pt_snow;
                }
                else // 0
                {
                        p->scale = 3;
                        p->texnum = rainparticletexture;
+                       p->dynlight = true;
                        p->type = pt_rain;
                }
                p->color = colorbase + (rand()&3);
@@ -735,9 +733,10 @@ void R_LavaSplash (vec3_t org)
        for (i=-128 ; i<128 ; i+=16)
                for (j=-128 ; j<128 ; j+=16)
                {
-                       ALLOCPARTICLE
+                       ALLOCPARTICLE(p)
                
                        p->texnum = particletexture;
+                       p->dynlight = false;
                        p->scale = 10;
                        p->alpha = 128;
                        p->die = cl.time + 2 + (rand()&31) * 0.02;
@@ -774,9 +773,10 @@ void R_TeleportSplash (vec3_t org)
                for (j=-16 ; j<16 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
                        {
-                               ALLOCPARTICLE
+                               ALLOCPARTICLE(p)
                
                                p->texnum = particletexture;
+                               p->dynlight = false;
                                p->scale = 1;
                                p->alpha = lhrandom(32,128);
                                p->die = cl.time + 5;
@@ -824,7 +824,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
 
        while (t < nt)
        {
-               ALLOCPARTICLE
+               ALLOCPARTICLE(p)
                
                p->vel[0] = p->vel[1] = p->vel[2] = 0;
                p->die = cl.time + 2;
@@ -837,6 +837,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                {
                                        dec = type == 0 ? 0.01f : 0.02f;
                                        p->texnum = bubbleparticletexture;
+                                       p->dynlight = false;
                                        p->scale = lhrandom(1,2);
                                        p->alpha = 255;
                                        p->color = 254;
@@ -850,21 +851,24 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                }
                                else
                                {
-                                       dec = type == 0 ? 0.01f : 0.02f;
+                                       dec = type == 0 ? 0.02f : 0.04f;
                                        p->texnum = smokeparticletexture[rand()&7];
+                                       p->dynlight = true;
                                        p->scale = lhrandom(4, 8);
                                        p->alpha = 160; //128 + (rand()&63);
                                        p->color = 254;
                                        p->type = pt_smoke;
                                        p->die = cl.time + 10000;
                                        VectorCopy(start, p->org);
+                                       /*
                                        if (type == 0)
                                        {
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
-                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
+                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
+                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
+                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
+                                               particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64));
                                        }
+                                       */
                                }
                                break;
 
@@ -872,6 +876,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->dynlight = true;
                                p->scale = lhrandom(6,9);
                                p->alpha = 64;
                                if (r_smokecolor.value)
@@ -888,6 +893,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 4: // slight blood
                                dec = 0.025f;
                                p->texnum = smokeparticletexture[rand()&7];
+                               p->dynlight = true;
                                p->scale = lhrandom(4, 6);
                                p->alpha = type == 4 ? 192 : 255;
                                p->color = 247; //(rand()&3)+68;
@@ -904,6 +910,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                        case 5: // tracer
                                dec = 0.02f;
                                p->texnum = smokeparticletexture[rand()&7];
+                               p->dynlight = false;
                                p->scale = 4;
                                p->alpha = 64 + (rand()&31);
                                p->color = type == 3 ? 56 : 234;
@@ -915,6 +922,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 = smokeparticletexture[rand()&7];
+                               p->dynlight = false;
                                p->scale = lhrandom(3, 5);
                                p->alpha = 255;
                                p->color = 9*16 + 8 + (rand()&3);
@@ -930,6 +938,7 @@ 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[rand()&7];
+                               p->dynlight = true;
                                p->scale = lhrandom(8, 12);
                                p->alpha = 64;
                                p->color = (rand()&3)+12;
@@ -958,7 +967,7 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        VectorScale(vec, 3, vec);
        while (len--)
        {
-               particle(pt_smoke, color, particletexture, 8, 192, 99, start[0], start[1], start[2], 0, 0, 0);
+               particle(pt_smoke, color, particletexture, false, 8, 192, 99, start[0], start[1], start[2], 0, 0, 0);
                VectorAdd (start, vec, start);
        }
 }
@@ -971,8 +980,6 @@ R_DrawParticles
 */
 extern cvar_t  sv_gravity;
 
-void TraceLine (vec3_t start, vec3_t end, vec3_t impact);
-
 void R_MoveParticles (void)
 {
        particle_t              *p;
@@ -998,8 +1005,6 @@ void R_MoveParticles (void)
                        freeparticles[j++] = p;
                        continue;
                }
-               maxparticle = i;
-               activeparticles++;
 
                VectorCopy(p->org, p->oldorg);
                p->org[0] += p->vel[0]*frametime;
@@ -1089,6 +1094,7 @@ void R_MoveParticles (void)
                        a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
                        if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
                        {
+                               vec3_t normal;
                                if (a == CONTENTS_SOLID && Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents == CONTENTS_SOLID)
                                        break; // still in solid
                                p->die = cl.time + 1000;
@@ -1112,7 +1118,7 @@ void R_MoveParticles (void)
 //                                     p->vel[2] *= 0.1;
                                        break;
                                default: // CONTENTS_SOLID and any others
-                                       TraceLine(p->oldorg, p->org, v);
+                                       TraceLine(p->oldorg, p->org, v, normal);
                                        VectorCopy(v, p->org);
                                        p->texnum = smokeparticletexture[rand()&7];
                                        p->type = pt_splash;
@@ -1124,6 +1130,35 @@ void R_MoveParticles (void)
                                }
                        }
                        break;
+               case pt_flame:
+                       p->alpha -= frametime * 512;
+                       break;
+               case pt_flamingdebris:
+                       if (cl.time >= p->time2)
+                       {
+                               p->time2 = cl.time + 0.01;
+                               particle2(pt_flame, p->color, particletexture, false, 4, p->alpha, 999, p->org, 0, 50);
+                       }
+                       p->alpha -= frametime * 512;
+                       p->vel[2] -= gravity * 0.5f;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                               p->die = -1;
+                       break;
+               case pt_smokingdebris:
+                       if (cl.time >= p->time2)
+                       {
+                               p->time2 = cl.time + 0.01;
+                               particle2(pt_flame, 15, smokeparticletexture[rand()&7], false, 4, p->alpha, 999, p->org, 0, 50);
+                       }
+                       p->alpha -= frametime * 512;
+                       p->vel[2] -= gravity * 0.5f;
+                       if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+                               p->die = -1;
+                       break;
+               case pt_flamefall:
+                       p->alpha -= frametime * 512;
+                       p->vel[2] -= gravity * 0.5f;
+                       break;
                }
 
                // LordHavoc: most particles did this check anyway, consistency...
@@ -1133,6 +1168,11 @@ void R_MoveParticles (void)
                // LordHavoc: immediate removal of unnecessary particles (must be done to ensure compactor below operates properly in all cases)
                if (p->die < cl.time)
                        freeparticles[j++] = p;
+               else
+               {
+                       maxparticle = i;
+                       activeparticles++;
+               }
        }
        // fill in gaps to compact the array
        i = 0;
@@ -1150,15 +1190,18 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p);
 void R_DrawParticles (void)
 {
        particle_t              *p;
-       int                             i, r,g,b,a;
+       int                             i, r,g,b,a, dynlight;
        float                   scale, scale2, minparticledist;
        byte                    *color24;
        vec3_t                  up, right, uprightangles, forward2, up2, right2, tempcolor;
 
        // LordHavoc: early out condition
-       if (!numparticles)
+       if ((!numparticles) || (!r_drawparticles.value))
                return;
 
+       dynlight = r_dynamicparticles.value;
+       if (!r_dynamic.value)
+               dynlight = 0;
        c_particles += numparticles;
 
        VectorScale (vup, 1.5, up);
@@ -1186,7 +1229,7 @@ void R_DrawParticles (void)
                g = color24[1];
                b = color24[2];
                a = p->alpha;
-               if (r_dynamicparticles.value)
+               if (dynlight && (p->dynlight || dynlight >= 2)) // LordHavoc: only light blood and smoke
                {
                        R_CompleteLightPoint(tempcolor, p->org);
                        r = (r * (int) tempcolor[0]) >> 7;
index c713eb4041b07dcf725427c83dcdb23a6b77ed72..669b7b372463162c3a39806c16e5b35ce00a3e56 100644 (file)
--- a/render.h
+++ b/render.h
@@ -156,11 +156,15 @@ extern void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength);
 extern void R_LavaSplash (vec3_t org);
 extern void R_TeleportSplash (vec3_t org);
 
+extern void R_NewExplosion(vec3_t org);
+
 extern void R_PushDlights (void);
 extern void R_DrawWorld (void);
 //extern void R_RenderDlights (void);
 extern void R_DrawParticles (void);
 extern void R_MoveParticles (void);
+extern void R_DrawExplosions (void);
+extern void R_MoveExplosions (void);
 
 extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
 extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
index 8bf174b641a8ad049a4c5731fe0dce1ffc44c7a8..d282bcc3398440c9a6d7df6ad331742413e1f767 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -280,7 +280,7 @@ void SV_ConnectClient (int clientnum)
        else
        {
        // call the progs to get default spawn parms for the new client
-               PR_ExecuteProgram (pr_global_struct->SetNewParms);
+               PR_ExecuteProgram (pr_global_struct->SetNewParms, "QC function SetNewParms is missing");
                for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
                        client->spawn_parms[i] = (&pr_global_struct->parm1)[i];
        }
@@ -1171,7 +1171,7 @@ void SV_SaveSpawnparms (void)
 
        // call the progs to get default spawn parms for the new client
                pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
-               PR_ExecuteProgram (pr_global_struct->SetChangeParms);
+               PR_ExecuteProgram (pr_global_struct->SetChangeParms, "QC function SetChangeParms is missing");
                for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
                        host_client->spawn_parms[j] = (&pr_global_struct->parm1)[j];
        }
index 48af07c47b113b5b4093a4fc6078a38e60d077e3..73b013df452c9f366fa88a15263e4dd57bba62df 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -148,7 +148,7 @@ qboolean SV_RunThink (edict_t *ent)
        pr_global_struct->time = thinktime;
        pr_global_struct->self = EDICT_TO_PROG(ent);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
-       PR_ExecuteProgram (ent->v.think);
+       PR_ExecuteProgram (ent->v.think, "NULL think function");
        return !ent->free;
 }
 
@@ -171,14 +171,14 @@ void SV_Impact (edict_t *e1, edict_t *e2)
        {
                pr_global_struct->self = EDICT_TO_PROG(e1);
                pr_global_struct->other = EDICT_TO_PROG(e2);
-               PR_ExecuteProgram (e1->v.touch);
+               PR_ExecuteProgram (e1->v.touch, "");
        }
        
        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        {
                pr_global_struct->self = EDICT_TO_PROG(e2);
                pr_global_struct->other = EDICT_TO_PROG(e1);
-               PR_ExecuteProgram (e2->v.touch);
+               PR_ExecuteProgram (e2->v.touch, "");
        }
 
        pr_global_struct->self = old_self;
@@ -560,7 +560,7 @@ void SV_PushMove (edict_t *pusher, float movetime)
                                {
                                        pr_global_struct->self = EDICT_TO_PROG(pusher);
                                        pr_global_struct->other = EDICT_TO_PROG(check);
-                                       PR_ExecuteProgram (pusher->v.blocked);
+                                       PR_ExecuteProgram (pusher->v.blocked, "");
                                }
                                
                                // move back any entities we already moved
@@ -719,7 +719,7 @@ void SV_PushRotate (edict_t *pusher, float movetime)
                        {
                                pr_global_struct->self = EDICT_TO_PROG(pusher);
                                pr_global_struct->other = EDICT_TO_PROG(check);
-                               PR_ExecuteProgram (pusher->v.blocked);
+                               PR_ExecuteProgram (pusher->v.blocked, "");
                        }
                        
                // move back any entities we already moved
@@ -773,7 +773,7 @@ void SV_Physics_Pusher (edict_t *ent)
                pr_global_struct->time = sv.time;
                pr_global_struct->self = EDICT_TO_PROG(ent);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
-               PR_ExecuteProgram (ent->v.think);
+               PR_ExecuteProgram (ent->v.think, "NULL think function");
                if (ent->free)
                        return;
        }
@@ -1082,7 +1082,7 @@ void SV_Physics_Client (edict_t   *ent, int num)
 //     
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
-       PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
+       PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
        
 //
 // do a move
@@ -1138,7 +1138,7 @@ void SV_Physics_Client (edict_t   *ent, int num)
 
        pr_global_struct->time = sv.time;
        pr_global_struct->self = EDICT_TO_PROG(ent);
-       PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
+       PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
 }
 
 //============================================================================
@@ -1392,7 +1392,7 @@ void SV_Physics (void)
        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        pr_global_struct->time = sv.time;
-       PR_ExecuteProgram (pr_global_struct->StartFrame);
+       PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
 
 //SV_CheckAllEnts ();
 
@@ -1463,7 +1463,7 @@ void SV_Physics (void)
                pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                pr_global_struct->time = sv.time;
-               PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions));
+               PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "");
        }
 
        sv.time += host_frametime;
index 8ddff9948e7a980a1d89973871eb62bd6f3a8c26..e76f78f944f74e6d8e1d3a76275520b7f0f308ee 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -650,7 +650,7 @@ void SV_RunClients (void)
                        {
                                pr_global_struct->time = sv.time;
                                pr_global_struct->self = EDICT_TO_PROG(sv_player);
-                               PR_ExecuteProgram ((func_t)(SV_PlayerPhysicsQC - pr_functions));
+                               PR_ExecuteProgram ((func_t)(SV_PlayerPhysicsQC - pr_functions), "");
                        }
                        else
                                SV_ClientThink ();
index b8db4c359e3f52b9e9d8ca5cb52a2167e72193cd..e025c7f3ea5f1ef5ceadfd124f78a6af69af3ad0 100644 (file)
@@ -68,6 +68,18 @@ void softwaretransform_docopy (vec3_t in, vec3_t out)
        out[2] = in[2];
 }
 
+void softwareuntransform (vec3_t in, vec3_t out)
+{
+       vec3_t v;
+       float s = 1.0f / softwaretransform_scale;
+       v[0] = in[0] - softwaretransform_offset[0];
+       v[1] = in[1] - softwaretransform_offset[1];
+       v[2] = in[2] - softwaretransform_offset[2];
+       out[0] = (v[0] * softwaretransform_x[0] + v[1] * softwaretransform_x[1] + v[2] * softwaretransform_x[2]) * s;
+       out[1] = (v[0] * softwaretransform_y[0] + v[1] * softwaretransform_y[1] + v[2] * softwaretransform_y[2]) * s;
+       out[2] = (v[0] * softwaretransform_z[0] + v[1] * softwaretransform_z[1] + v[2] * softwaretransform_z[2]) * s;
+}
+
 // to save time on transforms, choose the appropriate function
 void softwaretransform_classify()
 {
index a68de7d7896b4bab2a15005c9d271dae541b32ac..b33b7c67c2609ce704d81b8b718acb8eca4b0bbc 100644 (file)
@@ -13,3 +13,4 @@ extern void softwaretransformforentity (entity_t *e);
 extern void softwaretransformidentity ();
 extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale);
 extern void (*softwaretransform) (vec3_t in, vec3_t out);
+extern void softwareuntransform (vec3_t in, vec3_t out);
index d19b1d33be2b51ac7220f885898c1aba75ee5fdf..c30a890d49855ed8e635609c4194397f1201df15 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -694,6 +694,9 @@ void AppActivate(BOOL fActive, BOOL minimize)
                                ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
                                ShowWindow(mainwindow, SW_SHOWNORMAL);
                        }
+
+                       // LordHavoc: from dabb, fix for alt-tab bug in NVidia drivers
+                       MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false);
                }
                else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
                {
diff --git a/world.c b/world.c
index ec9942e4d5f23d0b15877a4ee89f6abca378178e..a2cc7e488d1161936ca80dace52313237822e6f0 100644 (file)
--- a/world.c
+++ b/world.c
@@ -325,7 +325,7 @@ loc0:
                pr_global_struct->self = EDICT_TO_PROG(touch);
                pr_global_struct->other = EDICT_TO_PROG(ent);
                pr_global_struct->time = sv.time;
-               PR_ExecuteProgram (touch->v.touch);
+               PR_ExecuteProgram (touch->v.touch, "");
 
                pr_global_struct->self = old_self;
                pr_global_struct->other = old_other;
@@ -748,10 +748,6 @@ loc0:
                return true;            // empty
        }
 
-       // LordHavoc: this can be eliminated by validating in the loader...  but Mercury told me not to bother
-       if (num < hull->firstclipnode || num > hull->lastclipnode)
-               Sys_Error ("SV_RecursiveHullCheck: bad node number");
-
 // find the point distances
        node = hull->clipnodes + num;
        plane = hull->planes + node->planenum;