+ c_faces += texturenumfaces;
+ // transparent surfaces get sorted for later drawing
+ if ((t->surfaceparms & Q3SURFACEPARM_TRANS) || ent->alpha < 1 || (ent->effects & EF_ADDITIVE))
+ {
+ vec3_t facecenter, center;
+ // drawing sky transparently would be too difficult
+ if (t->surfaceparms & Q3SURFACEPARM_SKY)
+ return;
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ facecenter[0] = (face->mins[0] + face->maxs[0]) * 0.5f;
+ facecenter[1] = (face->mins[1] + face->maxs[1]) * 0.5f;
+ facecenter[2] = (face->mins[2] + face->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&ent->matrix, facecenter, center);
+ R_MeshQueue_AddTransparent(center, R_Q3BSP_DrawFace_TransparentCallback, ent, face - ent->model->brushq3.data_faces);
+ }
+ 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 (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+ return;
+ }
+ // gl_lightmaps debugging mode skips normal texturing
+ if (gl_lightmaps.integer)
+ {
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ qglDisable(GL_CULL_FACE);
+ memset(&m, 0, sizeof(m));
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.tex[0] = R_GetTexture(face->lightmaptexture);
+ m.pointer_texcoord[0] = face->data_texcoordlightmap2f;
+ if (face->lightmaptexture)
+ {
+ GL_Color(1, 1, 1, 1);
+ m.pointer_color = NULL;
+ }
+ else
+ m.pointer_color = face->data_color4f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ qglEnable(GL_CULL_FACE);
+ return;
+ }
+ // anything else is a typical wall, lightmap * texture + glow
+ if (!(ent->flags & RENDER_LIGHT))
+ {
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_Color(1, 1, 1, 1);
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ if (t->skin.glow)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ m.tex[0] = R_GetTexture(t->skin.glow);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglEnable(GL_CULL_FACE);
+ return;
+ }
+ if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+ qglDisable(GL_CULL_FACE);
+ if (r_lightmapintensity <= 0)
+ {
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_Color(0, 0, 0, 1);
+ memset(&m, 0, sizeof(m));
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else if (r_textureunits.integer >= 2 && gl_combine.integer)
+ {
+ // dualtexture combine
+ 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);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.tex[1] = R_GetTexture(face->lightmaptexture);
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_texcoord[1] = face->data_texcoordlightmap2f;
+ m.texrgbscale[1] = 2;
+ if (face->lightmaptexture)
+ {
+ GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+ m.pointer_color = NULL;
+ }
+ else if (r_lightmapintensity == 1)
+ m.pointer_color = face->data_color4f;
+ else
+ {
+ m.pointer_color = varray_color4f;
+ for (i = 0;i < face->num_vertices;i++)
+ {
+ varray_color4f[i*4+0] = face->data_color4f[i*4+0] * r_lightmapintensity;
+ varray_color4f[i*4+1] = face->data_color4f[i*4+1] * r_lightmapintensity;
+ varray_color4f[i*4+2] = face->data_color4f[i*4+2] * r_lightmapintensity;
+ varray_color4f[i*4+3] = face->data_color4f[i*4+3];
+ }
+ }
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ else
+ {
+ // single texture
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ memset(&m, 0, sizeof(m));
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.tex[0] = R_GetTexture(face->lightmaptexture);
+ m.pointer_texcoord[0] = face->data_texcoordlightmap2f;
+ if (face->lightmaptexture)
+ m.pointer_color = NULL;
+ else
+ m.pointer_color = face->data_color4f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ GL_DepthMask(false);
+ GL_Color(r_lightmapintensity, r_lightmapintensity, r_lightmapintensity, 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (r_ambient.value)
+ {
+ GL_BlendFunc(GL_ONE, GL_ONE);
+ GL_DepthMask(false);
+ GL_Color(r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), r_ambient.value * (1.0f / 128.0f), 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.base);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
+ GL_LockArrays(0, 0);
+ }
+ }
+ if (t->skin.glow)
+ {
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ GL_Color(1, 1, 1, 1);
+ memset(&m, 0, sizeof(m));
+ m.tex[0] = R_GetTexture(t->skin.glow);
+ for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
+ {
+ q3msurface_t *face = texturefacelist[texturefaceindex];
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ m.pointer_vertex = face->data_vertex3f;
+ R_Mesh_State(&m);
+ GL_LockArrays(0, face->num_vertices);
+ R_Mesh_Draw(face->num_vertices, face->num_triangles, face->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, ti, flagsmask, flags;
+ q3msurface_t *face;
+ model_t *model;
+ q3mtexture_t *t;
+ const int maxfaces = 1024;
+ int numfaces = 0;
+ q3msurface_t *facelist[1024];