-}
-
-void R_UpdateAllTextureInfo(entity_render_t *ent)
-{
- int i;
- if (ent->model)
- for (i = 0;i < ent->model->num_textures;i++)
- R_UpdateTextureInfo(ent, ent->model->data_textures + i);
-}
-
-int rsurface_array_size = 0;
-float *rsurface_array_modelvertex3f = NULL;
-float *rsurface_array_modelsvector3f = NULL;
-float *rsurface_array_modeltvector3f = NULL;
-float *rsurface_array_modelnormal3f = NULL;
-float *rsurface_array_deformedvertex3f = NULL;
-float *rsurface_array_deformedsvector3f = NULL;
-float *rsurface_array_deformedtvector3f = NULL;
-float *rsurface_array_deformednormal3f = NULL;
-float *rsurface_array_color4f = NULL;
-float *rsurface_array_texcoord3f = NULL;
-
-void R_Mesh_ResizeArrays(int newvertices)
-{
- float *base;
- if (rsurface_array_size >= newvertices)
- return;
- if (rsurface_array_modelvertex3f)
- Mem_Free(rsurface_array_modelvertex3f);
- rsurface_array_size = (newvertices + 1023) & ~1023;
- base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
- rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
- rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
- rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
- rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
- rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
- rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
- rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
- rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
- rsurface_array_texcoord3f = base + rsurface_array_size * 24;
- rsurface_array_color4f = base + rsurface_array_size * 27;
-}
-
-float *rsurface_modelvertex3f;
-int rsurface_modelvertex3f_bufferobject;
-size_t rsurface_modelvertex3f_bufferoffset;
-float *rsurface_modelsvector3f;
-int rsurface_modelsvector3f_bufferobject;
-size_t rsurface_modelsvector3f_bufferoffset;
-float *rsurface_modeltvector3f;
-int rsurface_modeltvector3f_bufferobject;
-size_t rsurface_modeltvector3f_bufferoffset;
-float *rsurface_modelnormal3f;
-int rsurface_modelnormal3f_bufferobject;
-size_t rsurface_modelnormal3f_bufferoffset;
-float *rsurface_vertex3f;
-int rsurface_vertex3f_bufferobject;
-size_t rsurface_vertex3f_bufferoffset;
-float *rsurface_svector3f;
-int rsurface_svector3f_bufferobject;
-size_t rsurface_svector3f_bufferoffset;
-float *rsurface_tvector3f;
-int rsurface_tvector3f_bufferobject;
-size_t rsurface_tvector3f_bufferoffset;
-float *rsurface_normal3f;
-int rsurface_normal3f_bufferobject;
-size_t rsurface_normal3f_bufferoffset;
-float *rsurface_lightmapcolor4f;
-int rsurface_lightmapcolor4f_bufferobject;
-size_t rsurface_lightmapcolor4f_bufferoffset;
-vec3_t rsurface_modelorg;
-qboolean rsurface_generatedvertex;
-const entity_render_t *rsurface_entity;
-const model_t *rsurface_model;
-texture_t *rsurface_texture;
-qboolean rsurface_uselightmaptexture;
-rsurfmode_t rsurface_mode;
-int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
-
-void RSurf_CleanUp(void)
-{
- CHECKGLERROR
- if (rsurface_mode == RSURFMODE_GLSL)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- GL_AlphaTest(false);
- rsurface_mode = RSURFMODE_NONE;
- rsurface_uselightmaptexture = false;
- rsurface_texture = NULL;
-}
-
-void RSurf_ActiveWorldEntity(void)
-{
- RSurf_CleanUp();
- rsurface_entity = r_refdef.worldentity;
- rsurface_model = r_refdef.worldmodel;
- if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
- R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
- R_Mesh_Matrix(&identitymatrix);
- VectorCopy(r_view.origin, rsurface_modelorg);
- rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
- rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
- rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
- rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
- rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
- rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
- rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
- rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
- rsurface_generatedvertex = false;
- 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;
-}
-
-void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
-{
- RSurf_CleanUp();
- rsurface_entity = ent;
- rsurface_model = ent->model;
- if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
- R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
- R_Mesh_Matrix(&ent->matrix);
- Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
- if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
- {
- if (wanttangents)
- {
- rsurface_modelvertex3f = rsurface_array_modelvertex3f;
- rsurface_modelsvector3f = rsurface_array_modelsvector3f;
- rsurface_modeltvector3f = rsurface_array_modeltvector3f;
- rsurface_modelnormal3f = rsurface_array_modelnormal3f;
- Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
- }
- else if (wantnormals)
- {
- rsurface_modelvertex3f = rsurface_array_modelvertex3f;
- rsurface_modelsvector3f = NULL;
- rsurface_modeltvector3f = NULL;
- rsurface_modelnormal3f = rsurface_array_modelnormal3f;
- Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
- }
- else
- {
- rsurface_modelvertex3f = rsurface_array_modelvertex3f;
- rsurface_modelsvector3f = NULL;
- rsurface_modeltvector3f = NULL;
- rsurface_modelnormal3f = NULL;
- Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->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 = rsurface_model->surfmesh.data_vertex3f;
- rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
- rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
- rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
- rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
- rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
- rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
- rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
- rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
- rsurface_generatedvertex = false;
- }
- 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;
-}
-
-void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
-{
- // 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)
+}
+
+void R_UpdateAllTextureInfo(entity_render_t *ent)
+{
+ int i;
+ if (ent->model)
+ for (i = 0;i < ent->model->num_texturesperskin;i++)
+ R_UpdateTextureInfo(ent, ent->model->data_textures + i);
+}
+
+rsurfacestate_t rsurface;
+
+void R_Mesh_ResizeArrays(int newvertices)
+{
+ float *base;
+ if (rsurface.array_size >= newvertices)
+ return;
+ if (rsurface.array_modelvertex3f)
+ Mem_Free(rsurface.array_modelvertex3f);
+ rsurface.array_size = (newvertices + 1023) & ~1023;
+ base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
+ rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
+ rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
+ rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
+ rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
+ rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
+ rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
+ rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
+ rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
+ rsurface.array_texcoord3f = base + rsurface.array_size * 24;
+ rsurface.array_color4f = base + rsurface.array_size * 27;
+ rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
+}
+
+void RSurf_CleanUp(void)
+{
+ CHECKGLERROR
+ if (rsurface.mode == RSURFMODE_GLSL)
+ {
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+ GL_AlphaTest(false);
+ rsurface.mode = RSURFMODE_NONE;
+ rsurface.uselightmaptexture = false;
+ rsurface.texture = NULL;
+}
+
+void RSurf_ActiveWorldEntity(void)
+{
+ model_t *model = r_refdef.worldmodel;
+ RSurf_CleanUp();
+ if (rsurface.array_size < model->surfmesh.num_vertices)
+ R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
+ rsurface.matrix = identitymatrix;
+ rsurface.inversematrix = identitymatrix;
+ R_Mesh_Matrix(&identitymatrix);
+ VectorCopy(r_view.origin, rsurface.modelorg);
+ VectorSet(rsurface.modellight_ambient, 0, 0, 0);
+ VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
+ VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
+ VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
+ VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
+ rsurface.frameblend[0].frame = 0;
+ rsurface.frameblend[0].lerp = 1;
+ rsurface.frameblend[1].frame = 0;
+ rsurface.frameblend[1].lerp = 0;
+ rsurface.frameblend[2].frame = 0;
+ rsurface.frameblend[2].lerp = 0;
+ rsurface.frameblend[3].frame = 0;
+ rsurface.frameblend[3].lerp = 0;
+ 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.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.generatedvertex = false;
+ 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;
+}
+
+void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
+{
+ model_t *model = ent->model;
+ RSurf_CleanUp();
+ if (rsurface.array_size < model->surfmesh.num_vertices)
+ R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
+ rsurface.matrix = ent->matrix;
+ rsurface.inversematrix = ent->inversematrix;
+ R_Mesh_Matrix(&rsurface.matrix);
+ Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
+ VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
+ VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
+ VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
+ VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
+ VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
+ rsurface.frameblend[0] = ent->frameblend[0];
+ rsurface.frameblend[1] = ent->frameblend[1];
+ rsurface.frameblend[2] = ent->frameblend[2];
+ rsurface.frameblend[3] = ent->frameblend[3];
+ if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
+ {
+ if (wanttangents)
+ {
+ rsurface.modelvertex3f = rsurface.array_modelvertex3f;
+ rsurface.modelsvector3f = rsurface.array_modelsvector3f;
+ rsurface.modeltvector3f = rsurface.array_modeltvector3f;
+ rsurface.modelnormal3f = rsurface.array_modelnormal3f;
+ Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
+ }
+ else if (wantnormals)
+ {
+ rsurface.modelvertex3f = rsurface.array_modelvertex3f;
+ rsurface.modelsvector3f = NULL;
+ rsurface.modeltvector3f = NULL;
+ rsurface.modelnormal3f = rsurface.array_modelnormal3f;
+ Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
+ }
+ else
+ {
+ 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;
+ }
+ }
+ // generate texcoords based on the chosen texcoord source
+ switch(rsurface.texture->tcgen.tcgen)