+static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *s)
+{
+ int i;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+
+ memset(&m, 0, sizeof(m));
+ m.transparent = false;
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ZERO;
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ if (lighthalf)
+ {
+ m.cr = 2;
+ m.cg = 2;
+ m.cb = 2;
+ }
+ else
+ {
+ m.cr = 1;
+ m.cg = 1;
+ m.cb = 1;
+ }
+ m.ca = 1;
+ m.tex[0] = R_GetTexture(s->currenttexture->texture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ softwaretransform(v->v, sv->v);
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ }
+ R_Mesh_Draw(&m);
+}
+
+static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *s)
+{
+ int i;
+ float diff[3], ifog;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+
+ memset(&m, 0, sizeof(m));
+ m.transparent = false;
+ m.blendfunc1 = GL_ZERO;
+ m.blendfunc2 = GL_SRC_COLOR;
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.cr = 1;
+ if (lighthalf)
+ m.cr *= 2.0f;
+ m.cg = m.cr;
+ m.cb = m.cr;
+ m.ca = 1;
+ m.tex[0] = R_GetTexture(s->lightmaptexture);
+ m.texcoords[0] = &s->mesh.vertex->uv[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ if (fogenabled)
+ {
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ VectorSubtract(sv->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] = m.cr * ifog;
+ sv->c[1] = m.cg * ifog;
+ sv->c[2] = m.cb * ifog;
+ sv->c[3] = m.ca;
+ }
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ VectorSubtract(v->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] = m.cr * ifog;
+ sv->c[1] = m.cg * ifog;
+ sv->c[2] = m.cb * ifog;
+ sv->c[3] = m.ca;
+ }
+ }
+ }
+ else
+ {
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ softwaretransform(v->v, sv->v);
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ }
+ }
+ R_Mesh_Draw(&m);
+}
+
+static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *s)
+{
+ int i, size3;
+ float c[3], base[3], scale, diff[3], ifog;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+ byte *lm;
+
+ size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3;
+
+ base[0] = base[1] = base[2] = r_ambient.value * (1.0f / 128.0f);
+
+ memset(&m, 0, sizeof(m));
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ {
+ m.transparent = true;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE;
+ }
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
+ {
+ m.transparent = true;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ }
+ else
+ {
+ m.transparent = false;
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ZERO;
+ }
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ m.tex[0] = R_GetTexture(s->currenttexture->texture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ VectorCopy(base, c);
+ if (s->styles[0] != 255)
+ {
+ lm = s->samples + v->lightmapoffset;
+ scale = d_lightstylevalue[s->styles[0]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (s->styles[1] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[s->styles[1]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (s->styles[2] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[s->styles[2]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (s->styles[3] != 255)
+ {
+ lm += size3;
+ scale = d_lightstylevalue[s->styles[3]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ }
+ }
+ }
+ }
+ sv->c[0] = c[0];
+ sv->c[1] = c[1];
+ sv->c[2] = c[2];
+ sv->c[3] = currentrenderentity->alpha;
+ }
+ if (s->dlightframe == r_framecount)
+ RSurf_Light(s->dlightbits, m.numverts);
+ if (fogenabled)
+ {
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ VectorSubtract(sv->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] *= ifog;
+ sv->c[1] *= ifog;
+ sv->c[2] *= ifog;
+ }
+ }
+ R_Mesh_Draw(&m);
+}
+
+static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *s)
+{
+ int i;
+ float diff[3], ifog;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+
+ memset(&m, 0, sizeof(m));
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ {
+ m.transparent = true;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE;
+ }
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
+ {
+ m.transparent = true;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ }
+ else
+ {
+ m.transparent = false;
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ZERO;
+ }
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ m.tex[0] = R_GetTexture(s->currenttexture->texture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ if (fogenabled)
+ {
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ VectorSubtract(sv->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] = ifog;
+ sv->c[1] = ifog;
+ sv->c[2] = ifog;
+ sv->c[3] = currentrenderentity->alpha;
+ }
+ }
+ else
+ {
+ m.cr = m.cg = m.cb = 1;
+ m.ca = currentrenderentity->alpha;
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ softwaretransform(v->v, sv->v);
+ }
+ R_Mesh_Draw(&m);
+}
+
+static void RSurfShader_Wall_Pass_Light(msurface_t *s)
+{
+ int i;
+ float diff[3], ifog;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+
+ memset(&m, 0, sizeof(m));
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ m.transparent = true;
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
+ m.transparent = true;
+ else
+ m.transparent = false;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE;
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ m.tex[0] = R_GetTexture(s->currenttexture->texture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ sv->c[0] = 0;
+ sv->c[1] = 0;
+ sv->c[2] = 0;
+ sv->c[3] = currentrenderentity->alpha;
+ }
+ if (RSurf_Light(s->dlightbits, m.numverts))
+ {
+ if (fogenabled)
+ {
+ for (i = 0, sv = svert;i < m.numverts;i++, sv++)
+ {
+ VectorSubtract(sv->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] *= ifog;
+ sv->c[1] *= ifog;
+ sv->c[2] *= ifog;
+ }
+ }
+ R_Mesh_Draw(&m);
+ }
+}
+
+static void RSurfShader_Wall_Pass_Glow(msurface_t *s)
+{
+ int i;
+ float diff[3], ifog;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+
+ memset(&m, 0, sizeof(m));
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ m.transparent = true;
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
+ m.transparent = true;
+ else
+ m.transparent = false;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE;
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.cr = 1;
+ m.cg = 1;
+ m.cb = 1;
+ m.ca = currentrenderentity->alpha;
+ m.tex[0] = R_GetTexture(s->currenttexture->glowtexture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ if (fogenabled)
+ {
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ VectorSubtract(sv->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] = m.cr * ifog;
+ sv->c[1] = m.cg * ifog;
+ sv->c[2] = m.cb * ifog;
+ sv->c[3] = m.ca;
+ }
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ VectorSubtract(v->v, r_origin, diff);
+ ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
+ sv->c[0] = m.cr * ifog;
+ sv->c[1] = m.cg * ifog;
+ sv->c[2] = m.cb * ifog;
+ sv->c[3] = m.ca;
+ }
+ }
+ }
+ else
+ {
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ softwaretransform(v->v, sv->v);
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ }
+ }
+ R_Mesh_Draw(&m);
+}
+
+static void RSurfShader_Wall_Pass_Fog(msurface_t *s)
+{
+ int i;
+ surfvertex_t *v;
+ surfvert_t *sv;
+ rmeshinfo_t m;
+ vec3_t diff;
+
+ memset(&m, 0, sizeof(m));
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ m.transparent = true;
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
+ m.transparent = true;
+ else
+ m.transparent = false;
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE;
+ m.numtriangles = s->mesh.numtriangles;
+ m.numverts = s->mesh.numverts;
+ m.index = s->mesh.index;
+ m.color = &svert[0].c[0];
+ m.colorstep = sizeof(surfvert_t);
+ m.tex[0] = R_GetTexture(s->currenttexture->fogtexture);
+ m.texcoords[0] = &s->mesh.vertex->st[0];
+ m.texcoordstep[0] = sizeof(surfvertex_t);
+ if (softwaretransform_complexity)
+ {
+ m.vertex = &svert[0].v[0];
+ m.vertexstep = sizeof(surfvert_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ softwaretransform(v->v, sv->v);
+ VectorSubtract(sv->v, r_origin, diff);
+ sv->c[0] = fogcolor[0];
+ sv->c[1] = fogcolor[1];
+ sv->c[2] = fogcolor[2];
+ sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
+ }
+ }
+ else
+ {
+ m.vertex = &s->mesh.vertex->v[0];
+ m.vertexstep = sizeof(surfvertex_t);
+ for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
+ {
+ VectorSubtract(v->v, r_origin, diff);
+ sv->c[0] = fogcolor[0];
+ sv->c[1] = fogcolor[1];
+ sv->c[2] = fogcolor[2];
+ sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
+ }
+ }
+ R_Mesh_Draw(&m);
+}
+
+static int RSurfShader_Wall_Fullbright(int stage, msurface_t *s)
+{
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseFullbright(s);
+ return false;
+ case 1:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int RSurfShader_Wall_Vertex(int stage, msurface_t *s)
+{
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseVertex(s);
+ return false;
+ case 1:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int RSurfShader_Wall_Lightmap(int stage, msurface_t *s)
+{
+ if (r_vertexsurfaces.integer)
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseVertex(s);
+ return false;
+ case 1:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ else if (r_multitexture.integer)
+ {
+ if (r_dlightmap.integer)
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseMTex(s);
+ return false;
+ case 1:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ else
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseMTex(s);
+ return false;
+ case 1:
+ if (s->dlightframe == r_framecount)
+ RSurfShader_Wall_Pass_Light(s);
+ return false;
+ case 2:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ }
+ else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE))
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseVertex(s);
+ return false;
+ case 1:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ else
+ {
+ if (r_dlightmap.integer)
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseTexture(s);
+ return false;
+ case 1:
+ RSurfShader_Wall_Pass_BaseLightmap(s);
+ return false;
+ case 2:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ else
+ {
+ switch(stage)
+ {
+ case 0:
+ RSurfShader_Wall_Pass_BaseTexture(s);
+ return false;
+ case 1:
+ RSurfShader_Wall_Pass_BaseLightmap(s);
+ return false;
+ case 2:
+ if (s->dlightframe == r_framecount)
+ RSurfShader_Wall_Pass_Light(s);
+ return false;
+ case 3:
+ if (s->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(s);
+ return false;
+ default:
+ return true;
+ }
+ }
+ }
+}
+
+static int RSurfShader_Wall_Fog(int stage, msurface_t *s)
+{
+ if (stage == 0 && fogenabled)
+ {
+ RSurfShader_Wall_Pass_Fog(s);
+ return false;
+ }
+ else
+ return true;
+}
+
+/*
+=============================================================
+
+ WORLD MODEL
+
+=============================================================
+*/
+
+static void RSurf_Callback(void *data, void *junk)
+{
+ ((msurface_t *)data)->visframe = r_framecount;
+}
+
+static void R_SolidWorldNode (void)
+{
+ if (r_viewleaf->contents != CONTENTS_SOLID)
+ {
+ int portalstack;
+ mportal_t *p, *pstack[8192];
+ msurface_t *surf, **mark, **endmark;
+ mleaf_t *leaf;
+ tinyplane_t plane;
+ // LordHavoc: portal-passage worldnode; follows portals leading
+ // outward from viewleaf, if a portal leads offscreen it is not
+ // followed, in indoor maps this can often cull a great deal of
+ // geometry away when pvs data is not present (useful with pvs as well)
+
+ leaf = r_viewleaf;
+ leaf->worldnodeframe = r_framecount;
+ portalstack = 0;
+ loc0:
+ c_leafs++;
+
+ leaf->visframe = r_framecount;
+
+ if (leaf->nummarksurfaces)
+ {
+ mark = leaf->firstmarksurface;
+ endmark = mark + leaf->nummarksurfaces;
+ if (r_ser.integer)
+ {
+ do