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 8a46d76..2189396 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 56d77ab..1abbfd2 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 a3baf19..a1e0a2e 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 ad55254..da25caf 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 8b2d282..a496b1b 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 2631e35..2f53d5c 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 92fa54c..24a08cd 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 6ab30c4..9084da3 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 0e59395..23b7047 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 8afef82..e7c19f3 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 89dc8c2..b6d2d32 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 25240ec..e179da6 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 f757184..4783279 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 d3cb6e7..de5b65e 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 2b0031e..73e8310 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 172ae41..2ca0961 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 236a5d6..65acc09 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 0bb47d9..0488c17 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 a608a07..e70f158 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 2d39385..278447b 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 04504d2..7d259b7 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 bd8167b..509fe64 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 7f8627c..1acfbc2 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 c713eb4..669b7b3 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 8bf174b..d282bcc 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 48af07c..73b013d 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 8ddff99..e76f78f 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 b8db4c3..e025c7f 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 a68de7d..b33b7c6 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 d19b1d3..c30a890 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 ec9942e..a2cc7e4 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;