+ t = surface->texture;
+ if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
+ Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ }
+ else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
+ {
+ t = surface->texture->currentframe;
+ // FIXME: transparent surfaces need to be lit later
+ if ((t->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
+ {
+ if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale);
+ if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);
+ }
+ }
+ }
+ }
+}
+
+#if 0
+void R_Q3BSP_DrawFaceList(entity_render_t *ent, texture_t *t, int texturenumsurfaces, msurface_t **texturesurfacelist)
+{
+ int i, texturesurfaceindex;
+ vec3_t tempcenter, center, modelorg;
+ msurface_t *surface;
+ qboolean dolightmap;
+ qboolean dobase;
+ qboolean doambient;
+ qboolean dodetail;
+ qboolean doglow;
+ qboolean dofog;
+ rmeshstate_t m;
+ Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+ c_faces += texturenumsurfaces;
+ // gl_lightmaps debugging mode skips normal texturing
+ if (gl_lightmaps.integer)
+ {
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ qglDisable(GL_CULL_FACE);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ if (surface->lightmaptexture)
+ {
+ GL_Color(1, 1, 1, 1);
+ m.pointer_color = NULL;
+ }
+ else
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ qglEnable(GL_CULL_FACE);
+ return;
+ }
+ // transparent surfaces get sorted for later drawing
+ if ((t->surfaceparms & Q3SURFACEPARM_TRANS) || ent->alpha < 1 || (ent->effects & EF_ADDITIVE))
+ {
+ // drawing sky transparently would be too difficult
+ if (t->surfaceparms & Q3SURFACEPARM_SKY)
+ return;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&ent->matrix, tempcenter, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces);
+ }
+ return;
+ }
+ // sky surfaces draw sky if needed and render themselves as a depth mask
+ if (t->surfaceparms & Q3SURFACEPARM_SKY)
+ {
+ if (skyrendernow)
+ {
+ skyrendernow = false;
+ if (skyrendermasked)
+ R_Sky();
+ }
+ if (!r_q3bsp_renderskydepth.integer)
+ return;
+
+ R_Mesh_Matrix(&ent->matrix);
+
+ GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
+ if (skyrendermasked)
+ {
+ // depth-only (masking)
+ GL_ColorMask(0,0,0,0);
+ // just to make sure that braindead drivers don't draw anything
+ // despite that colormask...
+ GL_BlendFunc(GL_ZERO, GL_ONE);
+ }
+ else
+ {
+ // fog sky
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ }
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ return;
+ }
+ // anything else is a typical wall, lightmap * texture + glow
+ dolightmap = (ent->flags & RENDER_LIGHT);
+ dobase = true;
+ doambient = r_ambient.value > 0;
+ dodetail = t->skin.detail != NULL && r_detailtextures.integer;
+ doglow = t->skin.glow != NULL;
+ dofog = fogenabled;
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ if (!dolightmap && dobase)
+ {
+ dolightmap = false;
+ dobase = false;
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (r_lightmapintensity <= 0 && dolightmap && dobase)
+ {
+ dolightmap = false;
+ dobase = false;
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_Color(0, 0, 0, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
+ {
+ // dualtexture combine
+ dolightmap = false;
+ dobase = false;
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
+ m.pointer_color = NULL;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ if (!surface->lightmaptexture)
+ continue;
+ m.tex[1] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
+ m.texrgbscale[1] = 2;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ if (r_lightmapintensity == 1 && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ if (surface->lightmaptexture)
+ continue;
+ m.tex[1] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
+ m.texrgbscale[1] = 2;
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ if (surface->lightmaptexture)
+ continue;
+ m.tex[1] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
+ m.texrgbscale[1] = 2;
+ m.pointer_color = varray_color4f;
+ for (i = 0;i < surface->mesh.num_vertices;i++)
+ {
+ varray_color4f[i*4+0] = surface->mesh.data_lightmapcolor4f[i*4+0] * ent->colormod[0] * r_lightmapintensity;
+ varray_color4f[i*4+1] = surface->mesh.data_lightmapcolor4f[i*4+1] * ent->colormod[1] * r_lightmapintensity;
+ varray_color4f[i*4+2] = surface->mesh.data_lightmapcolor4f[i*4+2] * ent->colormod[2] * r_lightmapintensity;
+ varray_color4f[i*4+3] = surface->mesh.data_lightmapcolor4f[i*4+3];
+ }
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ }
+ // single texture
+ if (dolightmap)
+ {
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ memset(&m, 0, sizeof(m));
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.tex[0] = R_GetTexture(surface->lightmaptexture);
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
+ if (surface->lightmaptexture)
+ m.pointer_color = NULL;
+ else
+ m.pointer_color = surface->mesh.data_lightmapcolor4f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dobase)
+ {
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (doambient)
+ {
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (doglow)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.glow);
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (dofog)
+ {
+ float modelorg[3];
+ Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.fog);
+ m.pointer_color = varray_color4f;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ surface = texturesurfacelist[texturesurfaceindex];
+ if (m.tex[0])
+ m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
+ m.pointer_vertex = surface->mesh.data_vertex3f;
+ R_Mesh_State(&m);
+ RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, 1, surface->mesh.num_vertices, modelorg);
+ GL_LockArrays(0, surface->mesh.num_vertices);
+ R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);
+}
+
+void R_Q3BSP_DrawFaces(entity_render_t *ent, int skyfaces)
+{
+ int i, j, f, flagsmask, flags;
+ msurface_t *surface;
+ model_t *model = ent->model;
+ texture_t *t;
+ const int maxfaces = 1024;
+ int numsurfaces = 0;
+ msurface_t *surfacelist[1024];
+ R_Mesh_Matrix(&ent->matrix);
+ flagsmask = Q3SURFACEFLAG_NODRAW | Q3SURFACEFLAG_SKY;
+ if (skyfaces)
+ flags = Q3SURFACEFLAG_SKY;
+ else
+ flags = 0;
+ t = NULL;
+ f = 0;
+ numsurfaces = 0;
+ for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+ {
+ if (ent != r_refdef.worldentity || r_worldsurfacevisible[j])
+ {
+ surface = model->brush.data_surfaces + j;
+ if (t != surface->texture)
+ {
+ if (numsurfaces)
+ {
+ R_Q3BSP_DrawFaceList(ent, t, numsurfaces, surfacelist);
+ numsurfaces = 0;
+ }
+ t = surface->texture;
+ f = t->surfaceflags & flagsmask;
+ }
+ if (f == flags)
+ {
+ if (!surface->mesh.num_triangles)
+ continue;
+ if (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+ {
+ // drawing sky transparently would be too difficult
+ if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
+ {
+ vec3_t tempcenter, center;
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&ent->matrix, tempcenter, center);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces);
+ }
+ }
+ else
+ surfacelist[numsurfaces++] = surface;
+ if (numsurfaces >= maxfaces)
+ {
+ R_Q3BSP_DrawFaceList(ent, t, numsurfaces, surfacelist);
+ numsurfaces = 0;
+ }