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