+ rsurface.modelvertex3f = rsurface.array_modelvertex3f;
+ rsurface.modelsvector3f = NULL;
+ rsurface.modeltvector3f = NULL;
+ rsurface.modelnormal3f = NULL;
+ Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
+ }
+ rsurface.modelvertex3f_bufferobject = 0;
+ rsurface.modelvertex3f_bufferoffset = 0;
+ rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.modelsvector3f_bufferoffset = 0;
+ rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.modeltvector3f_bufferoffset = 0;
+ rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.modelnormal3f_bufferoffset = 0;
+ rsurface.generatedvertex = true;
+ }
+ else
+ {
+ rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
+ rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
+ rsurface.modelsvector3f = model->surfmesh.data_svector3f;
+ rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
+ rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
+ rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
+ rsurface.modelnormal3f = model->surfmesh.data_normal3f;
+ rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
+ rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
+ rsurface.generatedvertex = false;
+ }
+ rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
+ rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
+ rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
+ rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
+ rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
+ rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
+ rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
+ rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
+ rsurface.modelelement3i = model->surfmesh.data_element3i;
+ rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
+ rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
+ rsurface.modelnum_vertices = model->surfmesh.num_vertices;
+ rsurface.modelnum_triangles = model->surfmesh.num_triangles;
+ rsurface.modelsurfaces = model->data_surfaces;
+ 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;
+ rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
+}
+
+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->tcgen.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;
+ rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
+ rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
+ Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
+ }
+ if (generatetangents && !rsurface.modelsvector3f)
+ {
+ rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
+ rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
+ rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
+ rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
+ rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
+ rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
+ 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);
+ }
+ }
+ 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)
+ {
+ 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++)
+ {
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ // 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);
+ 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++)
+ {
+ 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);
+ }
+ }
+ 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;
+ vec3_t start, end;
+ float f, l;
+ struct
+ {
+ float length2;
+ const float *v1;
+ const float *v2;
+ }
+ shortest[2];
+ memset(shortest, 0, sizeof(shortest));
+ // 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);
+ // 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.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
+ v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
+ Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
+ Debug_PolygonEnd();
+#endif
+ l = VectorDistance2(v1, v2);
+ // this length bias tries to make sense of square polygons, assuming they are meant to be upright
+ if (v1[2] != v2[2])
+ l += (1.0f / 1024.0f);
+ if (shortest[0].length2 > l || i == 0)
+ {
+ shortest[1] = shortest[0];
+ shortest[0].length2 = l;
+ shortest[0].v1 = v1;
+ shortest[0].v2 = v2;
+ }
+ else if (shortest[1].length2 > l || i == 1)
+ {
+ shortest[1].length2 = l;
+ shortest[1].v1 = v1;
+ shortest[1].v2 = v2;
+ }
+ }
+ VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
+ VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
+ Debug_PolygonEnd();
+#endif
+ // this calculates the right vector from the shortest edge
+ // and the up vector from the edge midpoints
+ VectorSubtract(shortest[0].v1, shortest[0].v2, right);
+ VectorNormalize(right);
+ VectorSubtract(end, start, up);
+ VectorNormalize(up);
+ // 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);
+ Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
+ VectorNegate(forward, forward);
+ VectorReflect(forward, 0, up, forward);
+ VectorNormalize(forward);
+ CrossProduct(up, forward, newright);
+ VectorNormalize(newright);
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
+ Debug_PolygonEnd();
+#endif
+#if 0
+ Debug_PolygonBegin(NULL, 0, false, 0);
+ Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
+ Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
+ Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
+ Debug_PolygonEnd();
+#endif
+ // rotate the quad around the up axis vector, this is made
+ // especially easy by the fact we know the quad is flat,
+ // so we only have to subtract the center position and
+ // measure distance along the right vector, and then
+ // multiply that by the newright vector and add back the
+ // center position
+ // we also need to subtract the old position to undo the
+ // displacement from the center, which we do with a
+ // DotProduct, the subtraction/addition of center is also
+ // optimized into DotProducts here
+ l = DotProduct(right, center);
+ for (i = 0;i < 4;i++)
+ {
+ v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
+ f = DotProduct(right, v1) - l;
+ VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
+ }
+ }
+ 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++)
+ {
+ 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->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
+ normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
+ normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * 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->waveparms[0];
+ waveparms[1] = deform->waveparms[1];
+ waveparms[2] = deform->waveparms[2];
+ waveparms[3] = deform->waveparms[3];
+ // this is how a divisor of vertex influence on deformation
+ animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
+ scale = R_EvaluateQ3WaveFunc(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])
+ {
+ waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
+ scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
+ }
+ VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
+ }
+ }
+ 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->parms[0] + r_refdef.time * deform->parms[2])) * 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->wavefunc, deform->waveparms);
+ VectorScale(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;