// 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);
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;
time = cl.time - cl.oldtime;
+ c_dlights = 0;
dl = cl_dlights;
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
{
qmalloctotal_alloc += size;
qmalloctotal_alloccount++;
mem = malloc(size+sizeof(unsigned int));
+ if (!mem)
+ return mem;
*mem = size;
return (void *)(mem + 1);
}
void qfree(void *mem)
{
unsigned int *m;
+ if (!mem)
+ return;
m = mem;
m--; // back up to size
qmalloctotal_free += *m; // size
{
int h;
byte *buf;
- char base[32];
+ char base[1024];
int len;
buf = NULL; // quiet compiler warning
{
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);
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++;
+ }
+}
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);
#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;
{
// 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();
}
qfree(aliasvertnorm);
qfree(aliasvertcolor);
qfree(aliasvertcolor2);
+ qfree(zymbonepose);
+ qfree(aliasvertusage);
}
void GL_Models_Init()
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;
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++;
+ }
}
}
}
*/
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;
=================
*/
-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;
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;
=================
*/
-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;
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);
}
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);
glBegin(GL_QUADS);
break;
default:
- glBegin(GL_TRIANGLE_FAN);
+ glBegin(GL_POLYGON);
points = -1; // to force a reinit on the next poly
break;
}
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);
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);
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);
extern void R_Crosshairs_Init();
extern void R_Light_Init();
extern void R_Particles_Init();
+extern void R_Explosion_Init();
void Render_Init()
{
R_Crosshairs_Init();
R_Light_Init();
R_Particles_Init();
+ R_Explosion_Init();
R_StartModules();
}
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:
// 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);
}
c_bmodels = 0;
c_sprites = 0;
c_particles = 0;
- c_dlights = 0;
-
+// c_dlights = 0;
}
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;
TIMEREPORT(time_moveparticles)
R_DrawParticles ();
TIMEREPORT(time_drawparticles)
+ R_MoveExplosions();
+ TIMEREPORT(time_moveexplosions)
+ R_DrawExplosions();
+ TIMEREPORT(time_drawexplosions)
transpolyrender();
TIMEREPORT(time_transpoly)
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
//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;
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)
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
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
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)
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;
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?
// 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;
}
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];
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))
GL_EndRendering ();
}
-// for profiling, this is seperated
+// for profiling, this is separated
void GL_Finish()
{
if (!r_render.value)
#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"};
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
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()
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);
{
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
{
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
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
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;
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;
-}
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;
// 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;
}
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
{
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");
}
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
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");
}
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;
+ }
}
/*
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];
*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
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);
}
}
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);
// 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;
{
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]);
}
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);
+}
{
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;
#define ALIASTYPE_MDL 1
#define ALIASTYPE_MD2 2
+#define ALIASTYPE_ZYM 3
+
+#include "model_zymotic.h"
\ No newline at end of file
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;
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
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);
}
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);
#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;
{
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];
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);
#include "quakedef.h"
cvar_t r_lightmodels = {"r_lightmodels", "1"};
+cvar_t r_modelsdonttransformnormals = {"r_modelsdonttransformnormals", "0"};
void r_light_start()
{
void R_Light_Init()
{
Cvar_RegisterVariable(&r_lightmodels);
+ Cvar_RegisterVariable(&r_modelsdonttransformnormals);
R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
}
*/
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
{
}
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
{
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
}
surf->dlightbits[bitindex] |= bit;
}
+ */
}
if (node->children[0]->contents >= 0)
{
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);
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)
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;
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;
}
extern float *aliasvert;
+extern float *modelaliasvert;
extern float *aliasvertnorm;
extern byte *aliasvertcolor;
extern float modelalpha;
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++)
{
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
{
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++;
}
}
}
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++)
else
*((int *)avc) = color;
avc += 4;
- av+=3;
- avn+=3;
+ av += 3;
+ avn += 3;
}
}
else
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;
}
}
}
} 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
#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
{
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};
int smokeparticletexture[8];
int rainparticletexture;
int bubbleparticletexture;
+int explosiontexture;
+int explosiontexturefog;
particle_t *particles;
int r_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)
{
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);
}
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);
-}
-*/
/*
===============
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);
}
}
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);
*/
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);
}
-
+ */
}
/*
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);
}
/*
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);
}
/*
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)
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)
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;
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;
for (i=0 ; i<count ; i++)
{
- ALLOCPARTICLE
+ ALLOCPARTICLE(p)
vel[0] = dir[0] + (rand()&31) - 16;
vel[1] = dir[1] + (rand()&31) - 16;
{
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);
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;
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;
while (t < nt)
{
- ALLOCPARTICLE
+ ALLOCPARTICLE(p)
p->vel[0] = p->vel[1] = p->vel[2] = 0;
p->die = cl.time + 2;
{
dec = type == 0 ? 0.01f : 0.02f;
p->texnum = bubbleparticletexture;
+ p->dynlight = false;
p->scale = lhrandom(1,2);
p->alpha = 255;
p->color = 254;
}
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;
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)
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;
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;
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);
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;
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);
}
}
*/
extern cvar_t sv_gravity;
-void TraceLine (vec3_t start, vec3_t end, vec3_t impact);
-
void R_MoveParticles (void)
{
particle_t *p;
freeparticles[j++] = p;
continue;
}
- maxparticle = i;
- activeparticles++;
VectorCopy(p->org, p->oldorg);
p->org[0] += p->vel[0]*frametime;
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;
// 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;
}
}
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...
// 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;
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);
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;
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);
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];
}
// 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];
}
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;
}
{
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;
{
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
{
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
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;
}
//
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
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");
}
//============================================================================
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 ();
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;
{
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 ();
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()
{
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);
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)
{
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;
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;