implemented deformvertexes (previously autosprite/autosprite2 had been
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 25 May 2007 08:03:48 +0000 (08:03 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 25 May 2007 08:03:48 +0000 (08:03 +0000)
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

gl_rmain.c
model_brush.h
model_shared.c
model_shared.h

index f9566ab..8e46d7b 100644 (file)
@@ -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)
index b17ba53..a401906 100644 (file)
@@ -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;
index fd17265..371d135 100644 (file)
@@ -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;
index 59fe742..571dcc6 100644 (file)
@@ -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;