From: havoc Date: Fri, 25 May 2007 08:03:48 +0000 (+0000) Subject: implemented deformvertexes (previously autosprite/autosprite2 had been X-Git-Tag: xonotic-v0.1.0preview~3092 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=8faf3f3afe212ca98defd31285143d94757c06f4;ds=sidebyside implemented deformvertexes (previously autosprite/autosprite2 had been supported as a special case, but now all deformvertexes modes work) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7368 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_rmain.c b/gl_rmain.c index f9566ab0..8e46d7be 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -3625,19 +3625,32 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}}; void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist) { + int deformindex; int texturesurfaceindex; int i, j; float amplitude; float animpos; + float scale; const float *v1, *in_tc; float *out_tc; + float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3]; + float waveparms[4]; + q3shaderinfo_deform_t *deform; // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself if (rsurface.generatedvertex) { - if (rsurface.texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - generatetangents = true; - if (generatetangents || rsurface.texture->tcgen == Q3TCGEN_ENVIRONMENT) + if (rsurface.texture->tcgen == Q3TCGEN_ENVIRONMENT) generatenormals = true; + for (i = 0;i < Q3MAXDEFORMS;i++) + { + if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE) + { + generatetangents = true; + generatenormals = true; + } + if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE) + generatenormals = true; + } if (generatenormals && !rsurface.modelnormal3f) { rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f; @@ -3656,46 +3669,116 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer); } } - // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface.deform* arrays from whatever the rsurface.model* array pointers point to (may be static model data or generated data for an animated model) - if (rsurface.texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - { - int texturesurfaceindex; - float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3]; - Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward); - Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright); - Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup); - VectorNormalize(newforward); - VectorNormalize(newright); - VectorNormalize(newup); - // make deformed versions of only the model vertices used by the specified surfaces - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + rsurface.vertex3f = rsurface.modelvertex3f; + rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject; + rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset; + rsurface.svector3f = rsurface.modelsvector3f; + rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject; + rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset; + rsurface.tvector3f = rsurface.modeltvector3f; + rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject; + rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset; + rsurface.normal3f = rsurface.modelnormal3f; + rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject; + rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset; + // if vertices are deformed (sprite flares and things in maps, possibly + // water waves, bulges and other deformations), generate them into + // rsurface.deform* arrays from whatever the rsurface.* arrays point to + // (may be static model data or generated data for an animated model, or + // the previous deform pass) + for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++) + { + switch (deform->deform) { - const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; - // a single autosprite surface can contain multiple sprites... - for (j = 0;j < surface->num_vertices - 3;j += 4) + default: + case Q3DEFORM_PROJECTIONSHADOW: + case Q3DEFORM_TEXT0: + case Q3DEFORM_TEXT1: + case Q3DEFORM_TEXT2: + case Q3DEFORM_TEXT3: + case Q3DEFORM_TEXT4: + case Q3DEFORM_TEXT5: + case Q3DEFORM_TEXT6: + case Q3DEFORM_TEXT7: + case Q3DEFORM_NONE: + break; + case Q3DEFORM_AUTOSPRITE: + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward); + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright); + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup); + VectorNormalize(newforward); + VectorNormalize(newright); + VectorNormalize(newup); + // make deformed versions of only the model vertices used by the specified surfaces + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { - VectorClear(center); - for (i = 0;i < 4;i++) - VectorAdd(center, (rsurface.modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); - VectorScale(center, 0.25f, center); - if (rsurface.texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2) + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + // a single autosprite surface can contain multiple sprites... + for (j = 0;j < surface->num_vertices - 3;j += 4) { - const float *v1, *v2; - float f, l; - struct + VectorClear(center); + for (i = 0;i < 4;i++) + VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); + VectorScale(center, 0.25f, center); + VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward); + VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right); + VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up); + for (i = 0;i < 4;i++) { - float length2; - int quadedge; + VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v); + VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3); } - shortest[2]; + } + Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer); + Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer); + } + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; + rsurface.svector3f = rsurface.array_deformedsvector3f; + rsurface.svector3f_bufferobject = 0; + rsurface.svector3f_bufferoffset = 0; + rsurface.tvector3f = rsurface.array_deformedtvector3f; + rsurface.tvector3f_bufferobject = 0; + rsurface.tvector3f_bufferoffset = 0; + rsurface.normal3f = rsurface.array_deformednormal3f; + rsurface.normal3f_bufferobject = 0; + rsurface.normal3f_bufferoffset = 0; + break; + case Q3DEFORM_AUTOSPRITE2: + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward); + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright); + Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup); + VectorNormalize(newforward); + VectorNormalize(newright); + VectorNormalize(newup); + // make deformed versions of only the model vertices used by the specified surfaces + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + const float *v1, *v2; + float f, l; + struct + { + float length2; + int quadedge; + } + shortest[2]; + // a single autosprite surface can contain multiple sprites... + for (j = 0;j < surface->num_vertices - 3;j += 4) + { + VectorClear(center); + for (i = 0;i < 4;i++) + VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); + VectorScale(center, 0.25f, center); shortest[0].quadedge = shortest[1].quadedge = 0; shortest[0].length2 = shortest[1].length2 = 0; // find the two shortest edges, then use them to define the // axis vectors for rotating around the central axis for (i = 0;i < 6;i++) { - v1 = rsurface.modelvertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]); - v2 = rsurface.modelvertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]); + v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]); + v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]); l = VectorDistance2(v1, v2); if (shortest[0].length2 > l || i == 0) { @@ -3712,12 +3795,12 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta // this calculates the midpoints *2 (not bothering to average) of the two shortest edges, and subtracts one from the other to get the up vector for (i = 0;i < 3;i++) { - right[i] = rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i] - + rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]; - up[i] = rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i] - + rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i] - - rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i] - - rsurface.modelvertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i]; + right[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i] + + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i]; + up[i] = rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][0]) + i] + + rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[1].quadedge][1]) + i] + - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][0]) + i] + - rsurface.vertex3f[3 * (surface->num_firstvertex + quadedges[shortest[0].quadedge][1]) + i]; } // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector) VectorSubtract(rsurface.modelorg, center, forward); @@ -3738,53 +3821,114 @@ void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generateta l = DotProduct(newright, center) - DotProduct(right, center); for (i = 0;i < 4;i++) { - v1 = rsurface.modelvertex3f + 3 * (surface->num_firstvertex + j + i); + v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i); f = DotProduct(right, v1) - DotProduct(newright, v1) + l; VectorMA(v1, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3); } } - else + Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer); + Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer); + } + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; + rsurface.svector3f = rsurface.array_deformedsvector3f; + rsurface.svector3f_bufferobject = 0; + rsurface.svector3f_bufferoffset = 0; + rsurface.tvector3f = rsurface.array_deformedtvector3f; + rsurface.tvector3f_bufferobject = 0; + rsurface.tvector3f_bufferoffset = 0; + rsurface.normal3f = rsurface.array_deformednormal3f; + rsurface.normal3f_bufferobject = 0; + rsurface.normal3f_bufferoffset = 0; + break; + case Q3DEFORM_NORMAL: + // deform the normals to make reflections wavey + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (j = 0;j < surface->num_vertices;j++) { - VectorCopy((rsurface.modelnormal3f + 3 * surface->num_firstvertex) + j*3, forward); - VectorCopy((rsurface.modelsvector3f + 3 * surface->num_firstvertex) + j*3, right); - VectorCopy((rsurface.modeltvector3f + 3 * surface->num_firstvertex) + j*3, up); - for (i = 0;i < 4;i++) + float vertex[3]; + float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3; + VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex); + VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal); + normal[0] += deform->deform_parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->deform_parms[1]); + normal[1] += deform->deform_parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->deform_parms[1]); + normal[2] += deform->deform_parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->deform_parms[1]); + VectorNormalize(normal); + } + Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer); + } + rsurface.svector3f = rsurface.array_deformedsvector3f; + rsurface.svector3f_bufferobject = 0; + rsurface.svector3f_bufferoffset = 0; + rsurface.tvector3f = rsurface.array_deformedtvector3f; + rsurface.tvector3f_bufferobject = 0; + rsurface.tvector3f_bufferoffset = 0; + rsurface.normal3f = rsurface.array_deformednormal3f; + rsurface.normal3f_bufferobject = 0; + rsurface.normal3f_bufferoffset = 0; + break; + case Q3DEFORM_WAVE: + // deform vertex array to make wavey water and flags and such + waveparms[0] = deform->deform_waveparms[0]; + waveparms[1] = deform->deform_waveparms[1]; + waveparms[2] = deform->deform_waveparms[2]; + waveparms[3] = deform->deform_waveparms[3]; + // this is how a divisor of vertex influence on deformation + animpos = deform->deform_parms[0] ? 1.0f / deform->deform_parms[0] : 100.0f; + scale = R_EvaluateQ3WaveFunc(deform->deform_wavefunc, waveparms); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (j = 0;j < surface->num_vertices;j++) + { + float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3; + VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex); + // if the wavefunc depends on time, evaluate it per-vertex + if (waveparms[3]) { - VectorSubtract((rsurface.modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v); - VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3); + waveparms[2] = deform->deform_waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos; + scale = R_EvaluateQ3WaveFunc(deform->deform_wavefunc, waveparms); } + VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex); } } - Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.modelvertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer); - Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer); + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; + break; + case Q3DEFORM_BULGE: + // deform vertex array to make the surface have moving bulges + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (j = 0;j < surface->num_vertices;j++) + { + scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->deform_parms[0] + r_refdef.time * deform->deform_parms[2])) * deform->deform_parms[1]; + VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j)); + } + } + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; + break; + case Q3DEFORM_MOVE: + // deform vertex array + scale = R_EvaluateQ3WaveFunc(deform->deform_wavefunc, deform->deform_waveparms); + VectorScale(deform->deform_parms, scale, waveparms); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + const msurface_t *surface = texturesurfacelist[texturesurfaceindex]; + for (j = 0;j < surface->num_vertices;j++) + VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j)); + } + rsurface.vertex3f = rsurface.array_deformedvertex3f; + rsurface.vertex3f_bufferobject = 0; + rsurface.vertex3f_bufferoffset = 0; + break; } - rsurface.vertex3f = rsurface.array_deformedvertex3f; - rsurface.vertex3f_bufferobject = 0; - rsurface.vertex3f_bufferoffset = 0; - rsurface.svector3f = rsurface.array_deformedsvector3f; - rsurface.svector3f_bufferobject = 0; - rsurface.svector3f_bufferoffset = 0; - rsurface.tvector3f = rsurface.array_deformedtvector3f; - rsurface.tvector3f_bufferobject = 0; - rsurface.tvector3f_bufferoffset = 0; - rsurface.normal3f = rsurface.array_deformednormal3f; - rsurface.normal3f_bufferobject = 0; - rsurface.normal3f_bufferoffset = 0; - } - else - { - rsurface.vertex3f = rsurface.modelvertex3f; - rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject; - rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset; - rsurface.svector3f = rsurface.modelsvector3f; - rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject; - rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset; - rsurface.tvector3f = rsurface.modeltvector3f; - rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject; - rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset; - rsurface.normal3f = rsurface.modelnormal3f; - rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject; - rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset; } // generate texcoords based on the chosen texcoord source switch(rsurface.texture->tcgen) diff --git a/model_brush.h b/model_brush.h index b17ba53d..a4019060 100644 --- a/model_brush.h +++ b/model_brush.h @@ -648,12 +648,6 @@ q3dpvs_t; #define Q3SURFACEPARM_LIGHTGRID 1073741824 #define Q3SURFACEPARM_ANTIPORTAL 2147483648u -// various flags from shaders, used for special effects not otherwise classified -#define Q3TEXTUREFLAG_TWOSIDED 1 -#define Q3TEXTUREFLAG_AUTOSPRITE 2 -#define Q3TEXTUREFLAG_AUTOSPRITE2 4 -#define Q3TEXTUREFLAG_NOPICMIP 16 - typedef struct q3mbrush_s { struct colbrushf_s *colbrushf; diff --git a/model_shared.c b/model_shared.c index fd172653..371d135e 100644 --- a/model_shared.c +++ b/model_shared.c @@ -1176,6 +1176,8 @@ void Mod_LoadQ3Shaders(void) if (!COM_ParseToken_QuakeC(&text, true)) break; } + for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++) + parameter[j][0] = 0; if (developer.integer >= 100) { Con_Printf("%s %i: ", shader->name, shader->numlayers - 1); @@ -1271,8 +1273,8 @@ void Mod_LoadQ3Shaders(void) { layer->rgbgen = Q3RGBGEN_WAVE; layer->rgbgen_wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]); - for (i = 0;i < numparameters - 3 && i < Q3RGBGEN_MAXPARMS;i++) - layer->rgbgen_parms[i] = atof(parameter[i+3]); + for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++) + layer->rgbgen_waveparms[i] = atof(parameter[i+3]); } else Con_DPrintf("%s parsing warning: unknown rgbgen %s\n", search->filenames[fileindex], parameter[1]); } @@ -1293,8 +1295,8 @@ void Mod_LoadQ3Shaders(void) { layer->alphagen = Q3RGBGEN_WAVE; layer->alphagen_wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]); - for (i = 0;i < numparameters - 3 && i < Q3ALPHAGEN_MAXPARMS;i++) - layer->alphagen_parms[i] = atof(parameter[i+3]); + for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++) + layer->alphagen_waveparms[i] = atof(parameter[i+3]); } else Con_DPrintf("%s parsing warning: unknown alphagen %s\n", search->filenames[fileindex], parameter[1]); } @@ -1340,8 +1342,8 @@ void Mod_LoadQ3Shaders(void) { layer->tcmod[tcmodindex] = Q3TCMOD_STRETCH; layer->tcmod_wavefunc[tcmodindex] = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]); - for (i = 0;i < numparameters - 3 && i < Q3TCMOD_MAXPARMS;i++) - layer->tcmod_parms[tcmodindex][i] = atof(parameter[i+3]); + for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++) + layer->tcmod_waveparms[tcmodindex][i] = atof(parameter[i+3]); } else if (!strcasecmp(parameter[1], "transform")) layer->tcmod[tcmodindex] = Q3TCMOD_TRANSFORM; else if (!strcasecmp(parameter[1], "turb")) layer->tcmod[tcmodindex] = Q3TCMOD_TURBULENT; @@ -1382,6 +1384,8 @@ void Mod_LoadQ3Shaders(void) if (!COM_ParseToken_QuakeC(&text, true)) break; } + for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++) + parameter[j][0] = 0; if (fileindex == 0 && !strcasecmp(com_token, "}")) break; if (developer.integer >= 100) @@ -1486,10 +1490,42 @@ void Mod_LoadQ3Shaders(void) shader->textureflags |= Q3TEXTUREFLAG_NOPICMIP; else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2) { - if (!strcasecmp(parameter[1], "autosprite") && numparameters == 2) - shader->textureflags |= Q3TEXTUREFLAG_AUTOSPRITE; - if (!strcasecmp(parameter[1], "autosprite2") && numparameters == 2) - shader->textureflags |= Q3TEXTUREFLAG_AUTOSPRITE2; + int i, deformindex; + for (deformindex = 0;deformindex < Q3MAXDEFORMS;deformindex++) + if (!shader->deforms[deformindex].deform) + break; + if (deformindex < Q3MAXDEFORMS) + { + for (i = 0;i < numparameters - 2 && i < Q3DEFORM_MAXPARMS;i++) + shader->deforms[deformindex].deform_parms[i] = atof(parameter[i+2]); + if (!strcasecmp(parameter[1], "projectionshadow")) shader->deforms[deformindex].deform = Q3DEFORM_PROJECTIONSHADOW; + else if (!strcasecmp(parameter[1], "autosprite" )) shader->deforms[deformindex].deform = Q3DEFORM_AUTOSPRITE; + else if (!strcasecmp(parameter[1], "autosprite2" )) shader->deforms[deformindex].deform = Q3DEFORM_AUTOSPRITE2; + else if (!strcasecmp(parameter[1], "text0" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT0; + else if (!strcasecmp(parameter[1], "text1" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT1; + else if (!strcasecmp(parameter[1], "text2" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT2; + else if (!strcasecmp(parameter[1], "text3" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT3; + else if (!strcasecmp(parameter[1], "text4" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT4; + else if (!strcasecmp(parameter[1], "text5" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT5; + else if (!strcasecmp(parameter[1], "text6" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT6; + else if (!strcasecmp(parameter[1], "text7" )) shader->deforms[deformindex].deform = Q3DEFORM_TEXT7; + else if (!strcasecmp(parameter[1], "bulge" )) shader->deforms[deformindex].deform = Q3DEFORM_BULGE; + else if (!strcasecmp(parameter[1], "normal" )) shader->deforms[deformindex].deform = Q3DEFORM_NORMAL; + else if (!strcasecmp(parameter[1], "wave" )) + { + shader->deforms[deformindex].deform = Q3DEFORM_WAVE; + shader->deforms[deformindex].deform_wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[3]); + for (i = 0;i < numparameters - 4 && i < Q3WAVEPARMS;i++) + shader->deforms[deformindex].deform_waveparms[i] = atof(parameter[i+4]); + } + else if (!strcasecmp(parameter[1], "move" )) + { + shader->deforms[deformindex].deform = Q3DEFORM_MOVE; + shader->deforms[deformindex].deform_wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[5]); + for (i = 0;i < numparameters - 6 && i < Q3WAVEPARMS;i++) + shader->deforms[deformindex].deform_waveparms[i] = atof(parameter[i+6]); + } + } } } // identify if this is a blended terrain shader or similar @@ -1563,8 +1599,6 @@ qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qbool texture->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_NOSHADOW; if (shader->textureflags & Q3TEXTUREFLAG_TWOSIDED) texture->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE; - if (shader->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - texture->basematerialflags |= MATERIALFLAG_NOSHADOW; texture->customblendfunc[0] = GL_ONE; texture->customblendfunc[1] = GL_ZERO; if (shader->numlayers > 0) @@ -1610,16 +1644,19 @@ nothing GL_ZERO GL_ONE { // copy over many shader->primarylayer parameters texture->rgbgen = shader->primarylayer->rgbgen; + memcpy(texture->rgbgen_parms , shader->primarylayer->rgbgen_parms , sizeof(texture->rgbgen_parms)); texture->rgbgen_wavefunc = shader->primarylayer->rgbgen_wavefunc; + memcpy(texture->rgbgen_waveparms , shader->primarylayer->rgbgen_waveparms , sizeof(texture->rgbgen_waveparms)); texture->alphagen = shader->primarylayer->alphagen; + memcpy(texture->alphagen_parms , shader->primarylayer->alphagen_parms , sizeof(texture->alphagen_parms)); texture->alphagen_wavefunc = shader->primarylayer->alphagen_wavefunc; + memcpy(texture->alphagen_waveparms, shader->primarylayer->alphagen_waveparms, sizeof(texture->alphagen_waveparms)); texture->tcgen = shader->primarylayer->tcgen; - memcpy(texture->tcmod , shader->primarylayer->tcmod , sizeof(texture->tcmod)); - memcpy(texture->rgbgen_parms , shader->primarylayer->rgbgen_parms , sizeof(texture->rgbgen_parms)); - memcpy(texture->alphagen_parms, shader->primarylayer->alphagen_parms, sizeof(texture->alphagen_parms)); - memcpy(texture->tcgen_parms , shader->primarylayer->tcgen_parms , sizeof(texture->tcgen_parms)); - memcpy(texture->tcmod_parms , shader->primarylayer->tcmod_parms , sizeof(texture->tcmod_parms)); - memcpy(texture->tcmod_wavefunc, shader->primarylayer->tcmod_wavefunc, sizeof(texture->tcmod_wavefunc)); + memcpy(texture->tcgen_parms , shader->primarylayer->tcgen_parms , sizeof(texture->tcgen_parms)); + memcpy(texture->tcmod , shader->primarylayer->tcmod , sizeof(texture->tcmod)); + memcpy(texture->tcmod_parms , shader->primarylayer->tcmod_parms , sizeof(texture->tcmod_parms)); + memcpy(texture->tcmod_wavefunc , shader->primarylayer->tcmod_wavefunc , sizeof(texture->tcmod_wavefunc)); + memcpy(texture->tcmod_waveparms , shader->primarylayer->tcmod_waveparms , sizeof(texture->tcmod_waveparms)); // load the textures texture->numskinframes = shader->primarylayer->numframes; texture->skinframerate = shader->primarylayer->framerate; @@ -1652,6 +1689,7 @@ nothing GL_ZERO GL_ONE } } } + memcpy(texture->deforms, shader->deforms, sizeof(texture->deforms)); } else if (!strcmp(texture->name, "noshader")) texture->surfaceparms = 0; diff --git a/model_shared.h b/model_shared.h index 59fe7424..571dcc65 100644 --- a/model_shared.h +++ b/model_shared.h @@ -182,14 +182,22 @@ typedef struct shadowmesh_s } shadowmesh_t; +// various flags from shaders, used for special effects not otherwise classified +// TODO: support these features more directly +#define Q3TEXTUREFLAG_TWOSIDED 1 +#define Q3TEXTUREFLAG_NOPICMIP 16 + #define Q3PATHLENGTH 64 #define TEXTURE_MAXFRAMES 64 +#define Q3WAVEPARMS 4 +#define Q3DEFORM_MAXPARMS 3 #define Q3SHADER_MAXLAYERS 8 #define Q3RGBGEN_MAXPARMS 3 #define Q3ALPHAGEN_MAXPARMS 1 #define Q3TCGEN_MAXPARMS 6 #define Q3TCMOD_MAXPARMS 6 #define Q3MAXTCMODS 4 +#define Q3MAXDEFORMS 4 typedef enum q3wavefunc_e { @@ -204,6 +212,28 @@ typedef enum q3wavefunc_e } q3wavefunc_t; +typedef enum q3deform_e +{ + Q3DEFORM_NONE, + Q3DEFORM_PROJECTIONSHADOW, + Q3DEFORM_AUTOSPRITE, + Q3DEFORM_AUTOSPRITE2, + Q3DEFORM_TEXT0, + Q3DEFORM_TEXT1, + Q3DEFORM_TEXT2, + Q3DEFORM_TEXT3, + Q3DEFORM_TEXT4, + Q3DEFORM_TEXT5, + Q3DEFORM_TEXT6, + Q3DEFORM_TEXT7, + Q3DEFORM_BULGE, + Q3DEFORM_WAVE, + Q3DEFORM_NORMAL, + Q3DEFORM_MOVE, + Q3DEFORM_COUNT +} +q3deform_t; + typedef enum q3rgbgen_e { Q3RGBGEN_IDENTITY, @@ -269,19 +299,31 @@ typedef struct q3shaderinfo_layer_s char texturename[TEXTURE_MAXFRAMES][Q3PATHLENGTH]; int blendfunc[2]; q3rgbgen_t rgbgen; - q3alphagen_t alphagen; - q3tcgen_t tcgen; - q3tcmod_t tcmod[Q3MAXTCMODS]; float rgbgen_parms[Q3RGBGEN_MAXPARMS]; q3wavefunc_t rgbgen_wavefunc; + float rgbgen_waveparms[Q3WAVEPARMS]; + q3alphagen_t alphagen; float alphagen_parms[Q3ALPHAGEN_MAXPARMS]; q3wavefunc_t alphagen_wavefunc; + float alphagen_waveparms[Q3WAVEPARMS]; + q3tcgen_t tcgen; float tcgen_parms[Q3TCGEN_MAXPARMS]; + q3tcmod_t tcmod[Q3MAXTCMODS]; float tcmod_parms[Q3MAXTCMODS][Q3TCMOD_MAXPARMS]; q3wavefunc_t tcmod_wavefunc[Q3MAXTCMODS]; + float tcmod_waveparms[Q3MAXTCMODS][Q3WAVEPARMS]; } q3shaderinfo_layer_t; +typedef struct q3shaderinfo_deform_s +{ + q3deform_t deform; + float deform_parms[Q3DEFORM_MAXPARMS]; + q3wavefunc_t deform_wavefunc; + float deform_waveparms[Q3WAVEPARMS]; +} +q3shaderinfo_deform_t; + typedef struct q3shaderinfo_s { char name[Q3PATHLENGTH]; @@ -294,6 +336,7 @@ typedef struct q3shaderinfo_s q3shaderinfo_layer_t *primarylayer, *backgroundlayer; q3shaderinfo_layer_t layers[Q3SHADER_MAXLAYERS]; char skyboxname[Q3PATHLENGTH]; + q3shaderinfo_deform_t deforms[Q3MAXDEFORMS]; } q3shaderinfo_t; @@ -372,17 +415,25 @@ typedef struct texture_s matrix4x4_t currenttexmatrix; // various q3 shader features + q3shaderinfo_deform_t deforms[Q3MAXDEFORMS]; + q3deform_t deform; + float deform_parms[Q3DEFORM_MAXPARMS]; + q3wavefunc_t deform_wavefunc; + float deform_waveparms[Q3WAVEPARMS]; q3rgbgen_t rgbgen; - q3alphagen_t alphagen; - q3tcgen_t tcgen; - q3tcmod_t tcmod[Q3MAXTCMODS]; float rgbgen_parms[Q3RGBGEN_MAXPARMS]; q3wavefunc_t rgbgen_wavefunc; + float rgbgen_waveparms[Q3WAVEPARMS]; + q3alphagen_t alphagen; float alphagen_parms[Q3ALPHAGEN_MAXPARMS]; q3wavefunc_t alphagen_wavefunc; + float alphagen_waveparms[Q3WAVEPARMS]; + q3tcgen_t tcgen; float tcgen_parms[Q3TCGEN_MAXPARMS]; + q3tcmod_t tcmod[Q3MAXTCMODS]; float tcmod_parms[Q3MAXTCMODS][Q3TCMOD_MAXPARMS]; q3wavefunc_t tcmod_wavefunc[Q3MAXTCMODS]; + float tcmod_waveparms[Q3MAXTCMODS][Q3WAVEPARMS]; qboolean colormapping; rtexture_t *basetexture;