finished model/map rendering merge, model renderer has been completely removed
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 13 May 2005 03:24:13 +0000 (03:24 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 13 May 2005 03:24:13 +0000 (03:24 +0000)
model_t num_textures now lies a bit to keep things simple, it equals num_surfaces on models, even if there are multiple skins, in data_textures these extra textures really do exist even though num_textures does not count them (this was done so that UpdateAllTextureInfo won't crash trying to index later skins on the later skins themselves)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5277 d7cf8633-e32d-0410-b094-e92efae38249

gl_models.c
gl_rmain.c
gl_rsurf.c
model_alias.c
model_shared.h

index 6bd61f4..8b13789 100644 (file)
@@ -1,393 +1 @@
 
-#include "quakedef.h"
-#include "r_shadow.h"
-
-static texture_t r_aliasnotexture;
-static texture_t *R_FetchAliasSkin(const entity_render_t *ent, const surfmesh_t *mesh)
-{
-       model_t *model = ent->model;
-       if (model->numskins)
-       {
-               int s = ent->skinnum;
-               if ((unsigned int)s >= (unsigned int)model->numskins)
-                       s = 0;
-               if (model->skinscenes[s].framecount > 1)
-                       s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
-               else
-                       s = model->skinscenes[s].firstframe;
-               if (s >= mesh->num_skins)
-                       s = 0;
-               return mesh->data_skins + s;
-       }
-       else
-       {
-               memset(&r_aliasnotexture, 0, sizeof(r_aliasnotexture));
-               r_aliasnotexture.skin.base = r_texture_notexture;
-               return &r_aliasnotexture;
-       }
-}
-
-static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
-{
-       int c, fbbase, fbpants, fbshirt, doglow;
-       float tint[3], fog, ifog, colorscale, ambientcolor4f[4], diffusecolor[3], diffusenormal[3], colorbase[3], colorpants[3], colorshirt[3];
-       float *vertex3f, *normal3f;
-       vec3_t diff;
-       qbyte *bcolor;
-       rmeshstate_t m;
-       const entity_render_t *ent = calldata1;
-       msurface_t *surface = ent->model->data_surfaces + calldata2;
-       surfmesh_t *mesh = surface->groupmesh;
-       texture_t *texture;
-
-       R_Mesh_Matrix(&ent->matrix);
-
-       fog = 0;
-       if (fogenabled)
-       {
-               VectorSubtract(ent->origin, r_vieworigin, diff);
-               fog = DotProduct(diff,diff);
-               if (fog < 0.01f)
-                       fog = 0.01f;
-               fog = exp(fogdensity/fog);
-               if (fog > 1)
-                       fog = 1;
-               if (fog < 0.01f)
-                       fog = 0;
-               // fog method: darken, additive fog
-               // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
-               // 2. render fog as additive
-       }
-       ifog = 1 - fog;
-
-       VectorScale(ent->colormod, ifog, colorbase);
-       VectorClear(colorpants);
-       VectorClear(colorshirt);
-       fbbase = ent->effects & EF_FULLBRIGHT;
-       fbpants = fbbase;
-       fbshirt = fbbase;
-       if (ent->colormap >= 0)
-       {
-               // 128-224 are backwards ranges
-               c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
-               if (c >= 224)
-                       fbpants = true;
-               bcolor = (qbyte *) (&palette_complete[c]);
-               colorpants[0] = colorbase[0] * bcolor[0] * (1.0f / 255.0f);
-               colorpants[1] = colorbase[1] * bcolor[1] * (1.0f / 255.0f);
-               colorpants[2] = colorbase[2] * bcolor[2] * (1.0f / 255.0f);
-               // 128-224 are backwards ranges
-               c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
-               if (c >= 224)
-                       fbshirt = true;
-               bcolor = (qbyte *) (&palette_complete[c]);
-               colorshirt[0] = colorbase[0] * bcolor[0] * (1.0f / 255.0f);
-               colorshirt[1] = colorbase[1] * bcolor[1] * (1.0f / 255.0f);
-               colorshirt[2] = colorbase[2] * bcolor[2] * (1.0f / 255.0f);
-       }
-
-       texture = R_FetchAliasSkin(ent, mesh);
-
-       if ((ent->effects & EF_ADDITIVE))
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-       }
-       else if (texture->skin.fog || ent->alpha != 1.0)
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               GL_DepthMask(false);
-       }
-       else
-       {
-               GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_DepthMask(true);
-       }
-       GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
-       colorscale = 1.0f;
-       if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1)
-       {
-               vertex3f = mesh->data_vertex3f;
-               normal3f = mesh->data_normal3f;
-       }
-       else
-       {
-               vertex3f = varray_vertex3f;
-               Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, mesh, vertex3f);
-               normal3f = NULL;
-       }
-
-       doglow = texture->skin.glow != NULL;
-
-       memset(&m, 0, sizeof(m));
-       m.pointer_vertex = vertex3f;
-       m.pointer_texcoord[0] = mesh->data_texcoordtexture2f;
-       if (gl_combine.integer)
-       {
-               colorscale *= 0.25f;
-               m.texrgbscale[0] = 4;
-       }
-
-       m.tex[0] = R_GetTexture((ent->colormap >= 0 || !texture->skin.merged) ? texture->skin.base : texture->skin.merged);
-       VectorScale(colorbase, colorscale, tint);
-       m.pointer_color = NULL;
-       if (fbbase)
-               GL_Color(tint[0], tint[1], tint[2], ent->alpha);
-       else if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, tint[0], tint[1], tint[2], ent->alpha, false))
-       {
-               m.pointer_color = varray_color4f;
-               if (normal3f == NULL)
-               {
-                       normal3f = varray_normal3f;
-                       Mod_BuildNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, normal3f);
-               }
-               R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, mesh->num_vertices, vertex3f, normal3f, varray_color4f);
-       }
-       else
-               GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
-       if (gl_combine.integer && doglow)
-       {
-               doglow = false;
-               m.tex[1] = R_GetTexture(texture->skin.glow);
-               m.pointer_texcoord[1] = mesh->data_texcoordtexture2f;
-               m.texcombinergb[1] = GL_ADD;
-       }
-       R_Mesh_State(&m);
-       c_alias_polys += mesh->num_triangles;
-       GL_LockArrays(0, mesh->num_vertices);
-       R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
-       GL_LockArrays(0, 0);
-       m.tex[1] = 0;
-       m.pointer_texcoord[1] = NULL;
-       m.texcombinergb[1] = 0;
-
-       VectorScale(colorpants, colorscale, tint);
-       if (ent->colormap >= 0 && texture->skin.pants && VectorLength2(tint) >= 0.001)
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-               m.tex[0] = R_GetTexture(texture->skin.pants);
-               m.pointer_color = NULL;
-               if (fbpants)
-                       GL_Color(tint[0], tint[1], tint[2], ent->alpha);
-               else if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, tint[0], tint[1], tint[2], ent->alpha, false))
-               {
-                       m.pointer_color = varray_color4f;
-                       if (normal3f == NULL)
-                       {
-                               normal3f = varray_normal3f;
-                               Mod_BuildNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, normal3f);
-                       }
-                       R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, mesh->num_vertices, vertex3f, normal3f, varray_color4f);
-               }
-               else
-                       GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
-               R_Mesh_State(&m);
-               c_alias_polys += mesh->num_triangles;
-               GL_LockArrays(0, mesh->num_vertices);
-               R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
-               GL_LockArrays(0, 0);
-       }
-
-       VectorScale(colorshirt, colorscale, tint);
-       if (ent->colormap >= 0 && texture->skin.shirt && VectorLength2(tint) >= 0.001)
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-               m.tex[0] = R_GetTexture(texture->skin.shirt);
-               m.pointer_color = NULL;
-               if (fbshirt)
-                       GL_Color(tint[0], tint[1], tint[2], ent->alpha);
-               else if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, tint[0], tint[1], tint[2], ent->alpha, false))
-               {
-                       m.pointer_color = varray_color4f;
-                       if (normal3f == NULL)
-                       {
-                               normal3f = varray_normal3f;
-                               Mod_BuildNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, normal3f);
-                       }
-                       R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, mesh->num_vertices, vertex3f, normal3f, varray_color4f);
-               }
-               else
-                       GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
-               R_Mesh_State(&m);
-               c_alias_polys += mesh->num_triangles;
-               GL_LockArrays(0, mesh->num_vertices);
-               R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
-               GL_LockArrays(0, 0);
-       }
-
-       colorscale = 1;
-       m.texrgbscale[0] = 0;
-       m.pointer_color = NULL;
-
-       if (doglow)
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-               m.tex[0] = R_GetTexture(texture->skin.glow);
-               GL_Color(1, 1, 1, ent->alpha);
-               R_Mesh_State(&m);
-               c_alias_polys += mesh->num_triangles;
-               GL_LockArrays(0, mesh->num_vertices);
-               R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
-               GL_LockArrays(0, 0);
-       }
-
-       if (fog > 0)
-       {
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-               GL_DepthMask(false);
-               m.tex[0] = R_GetTexture(texture->skin.fog);
-               GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], fog * ent->alpha);
-               R_Mesh_State(&m);
-               c_alias_polys += mesh->num_triangles;
-               GL_LockArrays(0, mesh->num_vertices);
-               R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
-               GL_LockArrays(0, 0);
-       }
-}
-
-void R_Model_Alias_Draw(entity_render_t *ent)
-{
-       int surfacenum;
-       msurface_t *surface;
-       surfmesh_t *mesh;
-       if (ent->alpha < (1.0f / 64.0f))
-               return; // basically completely transparent
-
-       c_models++;
-
-       for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++)
-       {
-               mesh = surface->groupmesh;
-               if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->skin.fog)
-                       R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawAliasModelCallback, ent, surfacenum);
-               else
-                       R_DrawAliasModelCallback(ent, surfacenum);
-       }
-}
-
-void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
-{
-       int surfacenum;
-       msurface_t *surface;
-       surfmesh_t *mesh;
-       texture_t *texture;
-       float projectdistance, *vertex3f;
-       if (!(ent->flags & RENDER_SHADOW))
-               return;
-       // check the box in modelspace, it was already checked in worldspace
-       if (!BoxesOverlap(ent->model->normalmins, ent->model->normalmaxs, lightmins, lightmaxs))
-               return;
-       projectdistance = lightradius + ent->model->radius;// - sqrt(DotProduct(relativelightorigin, relativelightorigin));
-       if (projectdistance > 0.1)
-       {
-               for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++)
-               {
-                       mesh = surface->groupmesh;
-                       texture = R_FetchAliasSkin(ent, mesh);
-                       if (texture->skin.fog)
-                               continue;
-                       if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1)
-                               vertex3f = mesh->data_vertex3f;
-                       else
-                       {
-                               vertex3f = varray_vertex3f;
-                               Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, mesh, vertex3f);
-                       }
-                       // identify lit faces within the bounding box
-                       R_Shadow_PrepareShadowMark(mesh->num_triangles);
-                       R_Shadow_MarkVolumeFromBox(0, mesh->num_triangles, vertex3f, mesh->data_element3i, relativelightorigin, lightmins, lightmaxs, ent->model->normalmins, ent->model->normalmaxs);
-                       R_Shadow_VolumeFromList(mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
-               }
-       }
-}
-
-void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist)
-{
-       int c;
-       float fog, ifog, lightcolorbase[3], lightcolorpants[3], lightcolorshirt[3];
-       float *vertex3f, *svector3f, *tvector3f, *normal3f;
-       vec3_t diff;
-       qbyte *bcolor;
-       int surfacenum;
-       msurface_t *surface;
-       surfmesh_t *mesh;
-       texture_t *texture;
-
-       fog = 0;
-       if (fogenabled)
-       {
-               VectorSubtract(ent->origin, r_vieworigin, diff);
-               fog = DotProduct(diff,diff);
-               if (fog < 0.01f)
-                       fog = 0.01f;
-               fog = exp(fogdensity/fog);
-               if (fog > 1)
-                       fog = 1;
-               if (fog < 0.01f)
-                       fog = 0;
-               // fog method: darken, additive fog
-               // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
-               // 2. render fog as additive
-       }
-       ifog = 1 - fog;
-
-       VectorScale(lightcolor, ifog, lightcolorbase);
-       if (VectorLength2(lightcolorbase) < 0.001)
-               return;
-       VectorClear(lightcolorpants);
-       VectorClear(lightcolorshirt);
-       if (ent->colormap >= 0)
-       {
-               // 128-224 are backwards ranges
-               c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
-               // fullbright passes were already taken care of, so skip them in realtime lighting passes
-               if (c < 224)
-               {
-                       bcolor = (qbyte *) (&palette_complete[c]);
-                       lightcolorpants[0] = lightcolorbase[0] * bcolor[0] * (1.0f / 255.0f);
-                       lightcolorpants[1] = lightcolorbase[1] * bcolor[1] * (1.0f / 255.0f);
-                       lightcolorpants[2] = lightcolorbase[2] * bcolor[2] * (1.0f / 255.0f);
-               }
-               // 128-224 are backwards ranges
-               c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
-               // fullbright passes were already taken care of, so skip them in realtime lighting passes
-               if (c < 224)
-               {
-                       bcolor = (qbyte *) (&palette_complete[c]);
-                       lightcolorshirt[0] = lightcolorbase[0] * bcolor[0] * (1.0f / 255.0f);
-                       lightcolorshirt[1] = lightcolorbase[1] * bcolor[1] * (1.0f / 255.0f);
-                       lightcolorshirt[2] = lightcolorbase[2] * bcolor[2] * (1.0f / 255.0f);
-               }
-       }
-
-       for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++)
-       {
-               mesh = surface->groupmesh;
-               texture = R_FetchAliasSkin(ent, mesh);
-               // FIXME: transparent skins need to be lit during the transparent render
-               if (texture->skin.fog)
-                       continue;
-               if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1)
-               {
-                       vertex3f = mesh->data_vertex3f;
-                       svector3f = mesh->data_svector3f;
-                       tvector3f = mesh->data_tvector3f;
-                       normal3f = mesh->data_normal3f;
-               }
-               else
-               {
-                       vertex3f = varray_vertex3f;
-                       svector3f = varray_svector3f;
-                       tvector3f = varray_tvector3f;
-                       normal3f = varray_normal3f;
-                       Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, mesh, vertex3f);
-                       Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, svector3f, tvector3f, normal3f);
-               }
-               c_alias_polys += mesh->num_triangles;
-               R_Shadow_RenderLighting(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, vertex3f, svector3f, tvector3f, normal3f, mesh->data_texcoordtexture2f, lightcolorbase, lightcolorpants, lightcolorshirt, (ent->colormap >= 0 || !texture->skin.merged) ? texture->skin.base : texture->skin.merged, ent->colormap >= 0 ? texture->skin.pants : 0, ent->colormap >= 0 ? texture->skin.shirt : 0, texture->skin.nmap, texture->skin.gloss);
-       }
-}
-
index 834017c..4ea8d46 100644 (file)
@@ -1453,13 +1453,23 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane
 
 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
 {
-       // we don't need to set currentframe if t->animated is false because
-       // it was already set up by the texture loader for non-animating
-       if (t->animated)
+       model_t *model = ent->model;
+       int s = ent->skinnum;
+       if ((unsigned int)s >= (unsigned int)model->numskins)
+               s = 0;
+       if (s >= 1)
+               c_models++;
+       if (model->skinscenes)
        {
-               t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
-               t = t->currentframe;
+               if (model->skinscenes[s].framecount > 1)
+                       s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
+               else
+                       s = model->skinscenes[s].firstframe;
        }
+       if (s > 0)
+               t = t->currentframe = t + s * model->num_surfaces;
+       if (t->animated)
+               t = t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
        t->currentmaterialflags = t->basematerialflags;
        t->currentalpha = ent->alpha;
        if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
@@ -1480,13 +1490,41 @@ void R_UpdateAllTextureInfo(entity_render_t *ent)
                        R_UpdateTextureInfo(ent, ent->model->data_textures + i);
 }
 
-static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
+float *rsurface_vertex3f;
+float *rsurface_svector3f;
+float *rsurface_tvector3f;
+float *rsurface_normal3f;
+float *rsurface_lightmapcolor4f;
+
+void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
 {
        int i, j;
        float center[3], forward[3], right[3], up[3], v[4][3];
        matrix4x4_t matrix1, imatrix1;
+       if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
+       {
+               rsurface_vertex3f = varray_vertex3f;
+               rsurface_svector3f = NULL;
+               rsurface_tvector3f = NULL;
+               rsurface_normal3f = NULL;
+               Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
+       }
+       else
+       {
+               rsurface_vertex3f = surface->groupmesh->data_vertex3f;
+               rsurface_svector3f = surface->groupmesh->data_svector3f;
+               rsurface_tvector3f = surface->groupmesh->data_tvector3f;
+               rsurface_normal3f = surface->groupmesh->data_normal3f;
+       }
        if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
        {
+               if (!rsurface_svector3f)
+               {
+                       rsurface_svector3f = varray_svector3f;
+                       rsurface_tvector3f = varray_tvector3f;
+                       rsurface_normal3f = varray_normal3f;
+                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
+               }
                // a single autosprite surface can contain multiple sprites...
                VectorClear(forward);
                VectorClear(right);
@@ -1495,13 +1533,13 @@ static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *te
                {
                        VectorClear(center);
                        for (i = 0;i < 4;i++)
-                               VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
+                               VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
                        VectorScale(center, 0.25f, center);
                        // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
-                       Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
+                       Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
                        Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
                        for (i = 0;i < 4;i++)
-                               Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
+                               Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
                        forward[0] = modelorg[0] - center[0];
                        forward[1] = modelorg[1] - center[1];
                        VectorNormalize(forward);
@@ -1510,9 +1548,20 @@ static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *te
                        for (i = 0;i < 4;i++)
                                VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
                }
+               rsurface_vertex3f = varray_vertex3f;
+               rsurface_svector3f = NULL;
+               rsurface_tvector3f = NULL;
+               rsurface_normal3f = NULL;
        }
        else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
        {
+               if (!rsurface_svector3f)
+               {
+                       rsurface_svector3f = varray_svector3f;
+                       rsurface_tvector3f = varray_tvector3f;
+                       rsurface_normal3f = varray_normal3f;
+                       Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
+               }
                Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
                Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
                Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
@@ -1521,62 +1570,170 @@ static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *te
                {
                        VectorClear(center);
                        for (i = 0;i < 4;i++)
-                               VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
+                               VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
                        VectorScale(center, 0.25f, center);
                        // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
-                       Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
+                       Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
                        Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
                        for (i = 0;i < 4;i++)
-                               Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
+                               Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
                        for (i = 0;i < 4;i++)
                                VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
                }
+               rsurface_vertex3f = varray_vertex3f;
+               rsurface_svector3f = NULL;
+               rsurface_tvector3f = NULL;
+               rsurface_normal3f = NULL;
        }
-       else
-               memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
+       R_Mesh_VertexPointer(rsurface_vertex3f);
 }
 
-// any sort of deformvertices call is *VERY* rare, so this must be optimized
-// to skip deformvertices quickly!
-#if 1
-#define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f)
-#else
-static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
+void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, qboolean lightmodel, qboolean vertexlight, qboolean applycolor, qboolean applyfog)
 {
-       if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+       int i;
+       float f;
+       float *v, *c, *c2;
+       vec3_t diff;
+       if (lightmodel)
        {
-               RSurf_DeformVertices(ent, texture, surface, modelorg);
-               return varray_vertex3f;
+               vec4_t ambientcolor4f;
+               vec3_t diffusecolor;
+               vec3_t diffusenormal;
+               if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r, g, b, a, false))
+               {
+                       rsurface_lightmapcolor4f = varray_color4f;
+                       if (rsurface_normal3f == NULL)
+                       {
+                               rsurface_normal3f = varray_normal3f;
+                               Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f);
+                       }
+                       R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
+                       r = 1;
+                       g = 1;
+                       b = 1;
+                       a = 1;
+                       applycolor = false;
+               }
+               else
+               {
+                       r = ambientcolor4f[0];
+                       g = ambientcolor4f[1];
+                       b = ambientcolor4f[2];
+                       a = ambientcolor4f[3];
+                       rsurface_lightmapcolor4f = NULL;
+               }
+       }
+       else if (vertexlight)
+       {
+               if (surface->lightmapinfo)
+               {
+                       rsurface_lightmapcolor4f = varray_color4f;
+                       for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
+                       {
+                               const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
+                               float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
+                               VectorScale(lm, scale, c);
+                               if (surface->lightmapinfo->styles[1] != 255)
+                               {
+                                       int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
+                                       lm += size3;
+                                       scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
+                                       VectorMA(c, scale, lm, c);
+                                       if (surface->lightmapinfo->styles[2] != 255)
+                                       {
+                                               lm += size3;
+                                               scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
+                                               VectorMA(c, scale, lm, c);
+                                               if (surface->lightmapinfo->styles[3] != 255)
+                                               {
+                                                       lm += size3;
+                                                       scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
+                                                       VectorMA(c, scale, lm, c);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else
+                       rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
        }
        else
-               return surface->groupmesh->data_vertex3f;
+               rsurface_lightmapcolor4f = NULL;
+       if (applyfog)
+       {
+               if (rsurface_lightmapcolor4f)
+               {
+                       for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
+                       {
+                               VectorSubtract(v, modelorg, diff);
+                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
+                               c2[0] = c[0] * f;
+                               c2[1] = c[1] * f;
+                               c2[2] = c[2] * f;
+                               c2[3] = c[3];
+                       }
+               }
+               else
+               {
+                       for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
+                       {
+                               VectorSubtract(v, modelorg, diff);
+                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
+                               c2[0] = f;
+                               c2[1] = f;
+                               c2[2] = f;
+                               c2[3] = 1;
+                       }
+               }
+               rsurface_lightmapcolor4f = varray_color4f;
+       }
+       if (applycolor && rsurface_lightmapcolor4f)
+       {
+               for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
+               {
+                       c2[0] = c[0] * r;
+                       c2[1] = c[1] * g;
+                       c2[2] = c[2] * b;
+                       c2[3] = c[3] * a;
+               }
+       }
+       R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
+       GL_Color(r, g, b, a);
 }
-#endif
+
 
 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
 {
        int i;
        int texturesurfaceindex;
-       const float *v, *vertex3f;
+       const float *v;
        float *c;
        float diff[3];
+       float colorpants[3], colorshirt[3];
        float f, r, g, b, a, base, colorscale;
        const msurface_t *surface;
        qboolean dolightmap;
-       qboolean dobase;
        qboolean doambient;
        qboolean dodetail;
        qboolean doglow;
        qboolean dofogpass;
        qboolean fogallpasses;
        qboolean waterscrolling;
-       surfmesh_t *groupmesh;
-       rtexture_t *lightmaptexture;
+       qboolean dopants;
+       qboolean doshirt;
+       qboolean dofullbrightpants;
+       qboolean dofullbrightshirt;
+       qboolean applycolor;
+       qboolean lightmodel = false;
+       rtexture_t *basetexture;
        rmeshstate_t m;
        texture = texture->currentframe;
        if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
                return;
        c_faces += texturenumsurfaces;
+       // FIXME: identify models using a better check than ent->model->shadowmesh
+       if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
+               lightmodel = true;
        // gl_lightmaps debugging mode skips normal texturing
        if (gl_lightmaps.integer)
        {
@@ -1592,8 +1749,8 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        surface = texturesurfacelist[texturesurfaceindex];
                        R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
                        R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                       R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f);
-                       R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
+                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                       RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmodel, !surface->lightmaptexture, false, false);
                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                        GL_LockArrays(0, 0);
@@ -1646,7 +1803,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
                                surface = texturesurfacelist[texturesurfaceindex];
-                               R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                                GL_LockArrays(0, 0);
@@ -1679,7 +1836,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                {
                        surface = texturesurfacelist[texturesurfaceindex];
-                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
+                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                        R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
                        R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
@@ -1694,585 +1851,295 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
        else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
        {
                // normal surface (wall or water)
-               dobase = true;
                dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
                doambient = r_ambient.value >= (1/64.0f);
                dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
                doglow = texture->skin.glow != NULL;
                dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
                fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
-               if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+               if (ent->colormap >= 0)
+               {
+                       int b;
+                       qbyte *bcolor;
+                       basetexture = texture->skin.base;
+                       dopants = texture->skin.pants != NULL;
+                       doshirt = texture->skin.shirt != NULL;
+                       // 128-224 are backwards ranges
+                       b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
+                       dofullbrightpants = b >= 224;
+                       bcolor = (qbyte *) (&palette_complete[b]);
+                       VectorScale(bcolor, (1.0f / 255.0f), colorpants);
+                       // 128-224 are backwards ranges
+                       b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
+                       dofullbrightshirt = b >= 224;
+                       bcolor = (qbyte *) (&palette_complete[b]);
+                       VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
+               }
+               else
                {
-                       if (dobase && dolightmap && gl_combine.integer)
+                       basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
+                       dopants = false;
+                       doshirt = false;
+                       //dofullbrightshirt = false;
+                       //dofullbrightpants = false;
+               }
+               if (dolightmap && gl_combine.integer)
+               {
+                       memset(&m, 0, sizeof(m));
+                       m.tex[1] = R_GetTexture(basetexture);
+                       if (waterscrolling)
+                               m.texmatrix[1] = r_waterscrollmatrix;
+                       m.texrgbscale[1] = 2;
+                       m.pointer_color = varray_color4f;
+                       R_Mesh_State(&m);
+                       colorscale = 1;
+                       r = ent->colormod[0] * colorscale;
+                       g = ent->colormod[1] * colorscale;
+                       b = ent->colormod[2] * colorscale;
+                       a = texture->currentalpha;
+                       base = r_ambient.value * (1.0f / 64.0f);
+                       // q3bsp has no lightmap updates, so the lightstylevalue that
+                       // would normally be baked into the lightmaptexture must be
+                       // applied to the color
+                       if (ent->model->brushq3.data_lightmaps)
+                       {
+                               float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+                               r *= scale;
+                               g *= scale;
+                               b *= scale;
+                       }
+                       applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+                               R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
+                               if (surface->lightmaptexture)
+                                       R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+                               else
+                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                               RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, !surface->lightmaptexture, applycolor, fogallpasses);
+                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                               GL_LockArrays(0, 0);
+                       }
+               }
+               else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+               {
+                       // single texture
+                       GL_BlendFunc(GL_ONE, GL_ZERO);
+                       GL_DepthMask(true);
+                       GL_Color(1, 1, 1, 1);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
+                               if (surface->lightmaptexture)
+                               {
+                                       R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
+                                       R_Mesh_ColorPointer(NULL);
+                               }
+                               else //if (r == 1 && g == 1 && b == 1)
+                               {
+                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
+                                       R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
+                               }
+                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                               GL_LockArrays(0, 0);
+                       }
+                       GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+                       GL_DepthMask(false);
+                       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(basetexture);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       R_Mesh_State(&m);
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                               GL_LockArrays(0, 0);
+                       }
+               }
+               else
+               {
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(basetexture);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       m.pointer_color = varray_color4f;
+                       colorscale = 1;
+                       if (gl_combine.integer)
+                       {
+                               m.texrgbscale[0] = 4;
+                               colorscale *= 0.25f;
+                       }
+                       R_Mesh_State(&m);
+                       r = ent->colormod[0] * colorscale;
+                       g = ent->colormod[1] * colorscale;
+                       b = ent->colormod[2] * colorscale;
+                       a = texture->currentalpha;
+                       if (dolightmap)
                        {
-                               dobase = false;
-                               memset(&m, 0, sizeof(m));
-                               m.tex[1] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[1] = r_waterscrollmatrix;
-                               m.texrgbscale[1] = 2;
-                               m.pointer_color = varray_color4f;
-                               R_Mesh_State(&m);
-                               colorscale = 1;
-                               r = ent->colormod[0] * colorscale;
-                               g = ent->colormod[1] * colorscale;
-                               b = ent->colormod[2] * colorscale;
-                               a = texture->currentalpha;
-                               base = r_ambient.value * (1.0f / 64.0f);
                                // q3bsp has no lightmap updates, so the lightstylevalue that
                                // would normally be baked into the lightmaptexture must be
                                // applied to the color
-                               if (ent->model->brushq1.lightdata)
+                               if (ent->model->brushq3.data_lightmaps)
                                {
                                        float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
                                        r *= scale;
                                        g *= scale;
                                        b *= scale;
                                }
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_VertexPointer(vertex3f);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                       R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       if (surface->lightmaptexture)
-                                       {
-                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                               if (fogallpasses)
-                                               {
-                                                       R_Mesh_ColorPointer(varray_color4f);
-                                                       for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                                       {
-                                                               VectorSubtract(v, modelorg, diff);
-                                                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                               c[0] = f * r;
-                                                               c[1] = f * g;
-                                                               c[2] = f * b;
-                                                               c[3] = a;
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       R_Mesh_ColorPointer(NULL);
-                                                       GL_Color(r, g, b, a);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               R_Mesh_ColorPointer(varray_color4f);
-                                               if (!surface->lightmaptexture)
-                                               {
-                                                       for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
-                                                       {
-                                                               c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
-                                                               c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
-                                                               c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
-                                                               c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                                       }
-                                                       if (fogallpasses)
-                                                       {
-                                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                                               {
-                                                                       VectorSubtract(v, modelorg, diff);
-                                                                       f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                                       VectorScale(c, f, c);
-                                                               }
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       R_Mesh_ColorPointer(NULL);
-                                                       GL_Color(0, 0, 0, a);
-                                               }
-                                       }
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
                                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                                        GL_LockArrays(0, 0);
                                }
                        }
-                       if (dobase)
+                       else
                        {
-                               dobase = false;
-                               memset(&m, 0, sizeof(m));
-                               m.tex[0] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[0] = r_waterscrollmatrix;
-                               m.pointer_color = varray_color4f;
-                               colorscale = 1;
-                               if (gl_combine.integer)
-                               {
-                                       m.texrgbscale[0] = 4;
-                                       colorscale *= 0.25f;
-                               }
-                               R_Mesh_State(&m);
-                               r = ent->colormod[0] * colorscale;
-                               g = ent->colormod[1] * colorscale;
-                               b = ent->colormod[2] * colorscale;
-                               a = texture->currentalpha;
-                               if (dolightmap)
-                               {
-                                       // q3bsp has no lightmap updates, so the lightstylevalue that
-                                       // would normally be baked into the lightmaptexture must be
-                                       // applied to the color
-                                       if (!ent->model->brushq1.lightdata)
-                                       {
-                                               float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
-                                               r *= scale;
-                                               g *= scale;
-                                               b *= scale;
-                                       }
-                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                       {
-                                               surface = texturesurfacelist[texturesurfaceindex];
-                                               vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                               R_Mesh_VertexPointer(vertex3f);
-                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                               {
-                                                       c[0] = 0;
-                                                       c[1] = 0;
-                                                       c[2] = 0;
-                                                       if (!surface->lightmapinfo)
-                                                               VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c);
-                                                       else //if (surface->lightmapinfo)
-                                                       {
-                                                               const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
-                                                               float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
-                                                               VectorMA(c, scale, lm, c);
-                                                               if (surface->lightmapinfo->styles[1] != 255)
-                                                               {
-                                                                       int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
-                                                                       lm += size3;
-                                                                       scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
-                                                                       VectorMA(c, scale, lm, c);
-                                                                       if (surface->lightmapinfo->styles[2] != 255)
-                                                                       {
-                                                                               lm += size3;
-                                                                               scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
-                                                                               VectorMA(c, scale, lm, c);
-                                                                               if (surface->lightmapinfo->styles[3] != 255)
-                                                                               {
-                                                                                       lm += size3;
-                                                                                       scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
-                                                                                       VectorMA(c, scale, lm, c);
-                                                                               }
-                                                                       }
-                                                               }
-                                                       }
-                                                       c[0] *= r;
-                                                       c[1] *= g;
-                                                       c[2] *= b;
-                                                       if (fogallpasses)
-                                                       {
-                                                               VectorSubtract(v, modelorg, diff);
-                                                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                               VectorScale(c, f, c);
-                                                       }
-                                                       if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                                               c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                                       else
-                                                               c[3] = a;
-                                               }
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
-                                       }
-                               }
-                               else
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
-                                       if (fogallpasses)
-                                       {
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                                       R_Mesh_VertexPointer(vertex3f);
-                                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                                       if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                                       {
-                                                               R_Mesh_ColorPointer(varray_color4f);
-                                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                                               {
-                                                                       VectorSubtract(v, modelorg, diff);
-                                                                       f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                                       c[0] = r * f;
-                                                                       c[1] = g * f;
-                                                                       c[2] = b * f;
-                                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               R_Mesh_ColorPointer(varray_color4f);
-                                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                                               {
-                                                                       VectorSubtract(v, modelorg, diff);
-                                                                       f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                                       c[0] = r * f;
-                                                                       c[1] = g * f;
-                                                                       c[2] = b * f;
-                                                                       c[3] = a;
-                                                               }
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                                       R_Mesh_VertexPointer(vertex3f);
-                                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                                       if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                                       {
-                                                               R_Mesh_ColorPointer(varray_color4f);
-                                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                                               {
-                                                                       c[0] = r;
-                                                                       c[1] = g;
-                                                                       c[2] = b;
-                                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               R_Mesh_ColorPointer(NULL);
-                                                               GL_Color(r, g, b, a);
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-                                       }
+                                       surface = texturesurfacelist[texturesurfaceindex];
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                                       GL_LockArrays(0, 0);
                                }
                        }
                }
-               else
+               if (dopants)
                {
-                       if (!dolightmap && dobase)
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(texture->skin.pants);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       m.pointer_color = varray_color4f;
+                       colorscale = 1;
+                       if (gl_combine.integer)
+                       {
+                               m.texrgbscale[0] = 4;
+                               colorscale *= 0.25f;
+                       }
+                       R_Mesh_State(&m);
+                       r = ent->colormod[0] * colorpants[0] * colorscale;
+                       g = ent->colormod[1] * colorpants[1] * colorscale;
+                       b = ent->colormod[2] * colorpants[2] * colorscale;
+                       a = texture->currentalpha;
+                       if (dolightmap && !dofullbrightpants)
                        {
-                               dolightmap = false;
-                               dobase = false;
-                               GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
-                               memset(&m, 0, sizeof(m));
-                               m.tex[0] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[0] = r_waterscrollmatrix;
-                               R_Mesh_State(&m);
+                               // q3bsp has no lightmap updates, so the lightstylevalue that
+                               // would normally be baked into the lightmaptexture must be
+                               // applied to the color
+                               if (ent->model->brushq3.data_lightmaps)
+                               {
+                                       float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+                                       r *= scale;
+                                       g *= scale;
+                                       b *= scale;
+                               }
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                        R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
                                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                                        GL_LockArrays(0, 0);
                                }
                        }
-                       if (r_lightmapintensity <= 0 && dolightmap && dobase)
+                       else
                        {
-                               dolightmap = false;
-                               dobase = false;
-                               GL_Color(0, 0, 0, 1);
-                               memset(&m, 0, sizeof(m));
-                               R_Mesh_State(&m);
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
                                for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
                                        surface = texturesurfacelist[texturesurfaceindex];
-                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
                                        GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                        R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                                        GL_LockArrays(0, 0);
                                }
                        }
-                       if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
+               }
+               if (doshirt)
+               {
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(texture->skin.shirt);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       m.pointer_color = varray_color4f;
+                       colorscale = 1;
+                       if (gl_combine.integer)
                        {
-                               // dualtexture combine
-                               GL_BlendFunc(GL_ONE, GL_ZERO);
-                               GL_DepthMask(true);
-                               dolightmap = false;
-                               dobase = false;
-                               memset(&m, 0, sizeof(m));
-                               m.tex[1] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[1] = r_waterscrollmatrix;
-                               m.texrgbscale[1] = 2;
-                               R_Mesh_State(&m);
-                               r = ent->colormod[0] * r_lightmapintensity;
-                               g = ent->colormod[1] * r_lightmapintensity;
-                               b = ent->colormod[2] * r_lightmapintensity;
-                               GL_Color(r, g, b, 1);
-                               if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
-                               {
-                                       R_Mesh_VertexPointer(varray_vertex3f);
-                                       if (r == 1 && g == 1 && b == 1)
-                                       {
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       RSurf_DeformVertices(ent, texture, surface, modelorg);
-                                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                                       R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
-                                                       if (surface->lightmaptexture)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                                               R_Mesh_ColorPointer(NULL);
-                                                       }
-                                                       else //if (r == 1 && g == 1 && b == 1)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                               R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       RSurf_DeformVertices(ent, texture, surface, modelorg);
-                                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                                       R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
-                                                       if (surface->lightmaptexture)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                                               R_Mesh_ColorPointer(NULL);
-                                                       }
-                                                       else
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                               R_Mesh_ColorPointer(varray_color4f);
-                                                               for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
-                                                               {
-                                                                       c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
-                                                                       c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
-                                                                       c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
-                                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
-                                                               }
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-                                       }
-                               }
-                               else
-                               {
-                                       if (r == 1 && g == 1 && b == 1)
-                                       {
-#if 0
-                                               // experimental direct state calls for measuring
-                                               // R_Mesh_ call overhead, do not use!
-                                               R_Mesh_VertexPointer(varray_vertex3f);
-                                               R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]);
-                                               R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]);
-                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                               R_Mesh_ColorPointer(varray_color4f);
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f);
-                                                       qglClientActiveTexture(GL_TEXTURE0_ARB);
-                                                       qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f);
-                                                       qglClientActiveTexture(GL_TEXTURE1_ARB);
-                                                       qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f);
-                                                       if (surface->lightmaptexture)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                                               qglDisableClientState(GL_COLOR_ARRAY);
-                                                               qglColor4f(r, g, b, 1);
-                                                       }
-                                                       else //if (r == 1 && g == 1 && b == 1)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                               qglEnableClientState(GL_COLOR_ARRAY);
-                                                               qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f);
-                                                       }
-                                                       qglLockArraysEXT(0, surface->num_vertices);
-                                                       qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       qglUnlockArraysEXT();
-                                               }
-#else
-                                               groupmesh = NULL;
-                                               lightmaptexture = NULL;
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       if (groupmesh != surface->groupmesh)
-                                                       {
-                                                               groupmesh = surface->groupmesh;
-                                                               R_Mesh_VertexPointer(groupmesh->data_vertex3f);
-                                                               R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
-                                                               R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f);
-                                                               if (!lightmaptexture)
-                                                                       R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
-                                                       }
-                                                       if (lightmaptexture != surface->lightmaptexture)
-                                                       {
-                                                               lightmaptexture = surface->lightmaptexture;
-                                                               if (lightmaptexture)
-                                                               {
-                                                                       R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
-                                                                       R_Mesh_ColorPointer(NULL);
-                                                               }
-                                                               else //if (r == 1 && g == 1 && b == 1)
-                                                               {
-                                                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                                       R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
-                                                               }
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-#endif
-                                       }
-                                       else
-                                       {
-                                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                               {
-                                                       surface = texturesurfacelist[texturesurfaceindex];
-                                                       R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
-                                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                                       R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
-                                                       if (surface->lightmaptexture)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                                               R_Mesh_ColorPointer(NULL);
-                                                       }
-                                                       else
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                               R_Mesh_ColorPointer(varray_color4f);
-                                                               for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
-                                                               {
-                                                                       c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
-                                                                       c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
-                                                                       c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
-                                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
-                                                               }
-                                                       }
-                                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                                       GL_LockArrays(0, 0);
-                                               }
-                                       }
-                               }
+                               m.texrgbscale[0] = 4;
+                               colorscale *= 0.25f;
                        }
-                       // single texture
-                       if (dolightmap)
+                       R_Mesh_State(&m);
+                       r = ent->colormod[0] * colorshirt[0] * colorscale;
+                       g = ent->colormod[1] * colorshirt[1] * colorscale;
+                       b = ent->colormod[2] * colorshirt[2] * colorscale;
+                       a = texture->currentalpha;
+                       if (dolightmap && !dofullbrightshirt)
                        {
-                               GL_BlendFunc(GL_ONE, GL_ZERO);
-                               GL_DepthMask(true);
-                               GL_Color(1, 1, 1, 1);
-                               memset(&m, 0, sizeof(m));
-                               R_Mesh_State(&m);
-                               if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                               // q3bsp has no lightmap updates, so the lightstylevalue that
+                               // would normally be baked into the lightmaptexture must be
+                               // applied to the color
+                               if (ent->model->brushq3.data_lightmaps)
                                {
-                                       R_Mesh_VertexPointer(varray_vertex3f);
-                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                       {
-                                               surface = texturesurfacelist[texturesurfaceindex];
-                                               RSurf_DeformVertices(ent, texture, surface, modelorg);
-                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
-                                               if (surface->lightmaptexture)
-                                               {
-                                                       R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
-                                                       R_Mesh_ColorPointer(NULL);
-                                               }
-                                               else //if (r == 1 && g == 1 && b == 1)
-                                               {
-                                                       R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                       R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
-                                               }
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
-                                       }
+                                       float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
+                                       r *= scale;
+                                       g *= scale;
+                                       b *= scale;
                                }
-                               else
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
-                                       groupmesh = NULL;
-                                       lightmaptexture = NULL;
-                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                       {
-                                               surface = texturesurfacelist[texturesurfaceindex];
-                                               if (groupmesh != surface->groupmesh)
-                                               {
-                                                       groupmesh = surface->groupmesh;
-                                                       R_Mesh_VertexPointer(groupmesh->data_vertex3f);
-                                                       R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
-                                                       if (!lightmaptexture)
-                                                               R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
-                                               }
-                                               if (lightmaptexture != surface->lightmaptexture)
-                                               {
-                                                       lightmaptexture = surface->lightmaptexture;
-                                                       if (lightmaptexture)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
-                                                               R_Mesh_ColorPointer(NULL);
-                                                       }
-                                                       else //if (r == 1 && g == 1 && b == 1)
-                                                       {
-                                                               R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
-                                                               R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
-                                                       }
-                                               }
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
-                                       }
+                                       surface = texturesurfacelist[texturesurfaceindex];
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
+                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                                       GL_LockArrays(0, 0);
                                }
                        }
-                       if (dobase)
+                       else
                        {
-                               GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
-                               GL_DepthMask(false);
-                               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(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[0] = r_waterscrollmatrix;
-                               R_Mesh_State(&m);
-                               if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
-                               {
-                                       R_Mesh_VertexPointer(varray_vertex3f);
-                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                       {
-                                               surface = texturesurfacelist[texturesurfaceindex];
-                                               RSurf_DeformVertices(ent, texture, surface, modelorg);
-                                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
-                                       }
-                               }
-                               else
+                               applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                                {
-                                       groupmesh = NULL;
-                                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                                       {
-                                               surface = texturesurfacelist[texturesurfaceindex];
-                                               if (groupmesh != surface->groupmesh)
-                                               {
-                                                       groupmesh = surface->groupmesh;
-                                                       R_Mesh_VertexPointer(groupmesh->data_vertex3f);
-                                                       R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f);
-                                               }
-                                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                               GL_LockArrays(0, 0);
-                                       }
+                                       surface = texturesurfacelist[texturesurfaceindex];
+                                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                                       RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                                       GL_LockArrays(0, 0);
                                }
                        }
                }
@@ -2298,28 +2165,13 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        g = ent->colormod[1] * colorscale * base;
                        b = ent->colormod[2] * colorscale * base;
                        a = texture->currentalpha;
+                       applycolor = r != 1 || g != 1 || b != 1 || a != 1;
                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
                                surface = texturesurfacelist[texturesurfaceindex];
-                               vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                               R_Mesh_VertexPointer(vertex3f);
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                               {
-                                       c[0] = r;
-                                       c[1] = g;
-                                       c[2] = b;
-                                       if (fogallpasses)
-                                       {
-                                               VectorSubtract(v, modelorg, diff);
-                                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                               VectorScale(c, f, c);
-                                       }
-                                       if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                               c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                       else
-                                               c[3] = a;
-                               }
+                               RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
                                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
                                GL_LockArrays(0, 0);
@@ -2336,7 +2188,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
                                surface = texturesurfacelist[texturesurfaceindex];
-                               R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
                                GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
                                R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
@@ -2359,72 +2211,16 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        g = ent->colormod[1] * colorscale;
                        b = ent->colormod[2] * colorscale;
                        a = texture->currentalpha;
-                       if (fogallpasses)
-                       {
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                               {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_VertexPointer(vertex3f);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       R_Mesh_ColorPointer(varray_color4f);
-                                       if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                       {
-                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                               {
-                                                       VectorSubtract(v, modelorg, diff);
-                                                       f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                       c[0] = f * r;
-                                                       c[1] = f * g;
-                                                       c[2] = f * b;
-                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                               {
-                                                       VectorSubtract(v, modelorg, diff);
-                                                       f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                                       c[0] = f * r;
-                                                       c[1] = f * g;
-                                                       c[2] = f * b;
-                                                       c[3] = a;
-                                               }
-                                       }
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
-                               }
-                       }
-                       else
+                       applycolor = r != 1 || g != 1 || b != 1 || a != 1;
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                               {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                                       R_Mesh_VertexPointer(vertex3f);
-                                       R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
-                                       if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
-                                       {
-                                               R_Mesh_ColorPointer(varray_color4f);
-                                               for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
-                                               {
-                                                       c[0] = r;
-                                                       c[1] = g;
-                                                       c[2] = b;
-                                                       c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               R_Mesh_ColorPointer(NULL);
-                                               GL_Color(r, g, b, a);
-                                       }
-                                       GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
-                                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                                       GL_LockArrays(0, 0);
-                               }
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                               R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
+                               RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
+                               GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+                               R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                               GL_LockArrays(0, 0);
                        }
                }
                if (dofogpass)
@@ -2440,7 +2236,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        // were darkened by fog already, and we should not add fog color
                        // (because the background was not darkened, there is no fog color
                        // that was lost behind it).
-                       if (!fogallpasses)
+                       if (fogallpasses)
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                        else
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -2454,17 +2250,17 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                        g = fogcolor[1];
                        b = fogcolor[2];
                        a = texture->currentalpha;
+                       applycolor = r != 1 || g != 1 || b != 1 || a != 1;
                        for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
                        {
                                surface = texturesurfacelist[texturesurfaceindex];
-                               vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
-                               R_Mesh_VertexPointer(vertex3f);
+                               RSurf_SetVertexPointer(ent, texture, surface, modelorg);
                                R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
                                R_Mesh_ColorPointer(varray_color4f);
                                //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
                                if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
                                {
-                                       for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
+                                       for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
                                        {
                                                VectorSubtract(v, modelorg, diff);
                                                f = exp(fogdensity/DotProduct(diff, diff));
@@ -2476,7 +2272,7 @@ static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *text
                                }
                                else
                                {
-                                       for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
+                                       for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
                                        {
                                                VectorSubtract(v, modelorg, diff);
                                                f = exp(fogdensity/DotProduct(diff, diff));
index 839cf24..c55d890 100644 (file)
@@ -656,26 +656,75 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa
        *outnumsurfacespointer = info.outnumsurfaces;
 }
 
+extern float *rsurface_vertex3f;
+extern float *rsurface_svector3f;
+extern float *rsurface_tvector3f;
+extern float *rsurface_normal3f;
+extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg);
+
 void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
 {
        model_t *model = ent->model;
        msurface_t *surface;
        int surfacelistindex;
-       if (r_drawcollisionbrushes.integer < 2)
+       float projectdistance = lightradius + model->radius + r_shadow_projectdistance.value;
+       vec3_t modelorg;
+       texture_t *texture;
+       // check the box in modelspace, it was already checked in worldspace
+       if (!BoxesOverlap(ent->model->normalmins, ent->model->normalmaxs, lightmins, lightmaxs))
+               return;
+       if (r_drawcollisionbrushes.integer >= 2)
+               return;
+       if (!r_shadow_compilingrtlight)
+               R_UpdateAllTextureInfo(ent);
+       if (model->brush.shadowmesh)
        {
                R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
-               if (!r_shadow_compilingrtlight)
-                       R_UpdateAllTextureInfo(ent);
+               if (r_shadow_compilingrtlight)
+               {
+                       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+                       {
+                               surface = model->data_surfaces + surfacelist[surfacelistindex];
+                               texture = surface->texture;
+                               if ((texture->basematerialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
+                                       continue;
+                               if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                                       continue;
+                               R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
+                       }
+               }
+               else
+               {
+                       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+                       {
+                               surface = model->data_surfaces + surfacelist[surfacelistindex];
+                               texture = surface->texture->currentframe;
+                               if ((texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
+                                       continue;
+                               if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                                       continue;
+                               R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
+                       }
+               }
+               R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + projectdistance, numshadowmark, shadowmarklist);
+       }
+       else
+       {
+               projectdistance = lightradius + ent->model->radius;
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
                for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
                {
                        surface = model->data_surfaces + surfacelist[surfacelistindex];
-                       if ((surface->texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
+                       // FIXME: get current skin
+                       texture = surface->texture;//R_FetchAliasSkin(ent, surface->groupmesh);
+                       if (texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT) || !surface->num_triangles)
                                continue;
-                       if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
-                               continue;
-                       R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
+                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                       // identify lit faces within the bounding box
+                       R_Shadow_PrepareShadowMark(surface->groupmesh->num_triangles);
+                       R_Shadow_MarkVolumeFromBox(surface->num_firsttriangle, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
+                       R_Shadow_VolumeFromList(surface->groupmesh->num_vertices, surface->groupmesh->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i, surface->groupmesh->data_neighbor3i, relativelightorigin, projectdistance, numshadowmark, shadowmarklist);
                }
-               R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist);
        }
 }
 
@@ -683,58 +732,64 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces,
 {
        model_t *model = ent->model;
        msurface_t *surface;
-       texture_t *t;
+       texture_t *texture;
        int surfacelistindex;
-       if (r_drawcollisionbrushes.integer < 2)
+       vec3_t modelorg;
+       if (r_drawcollisionbrushes.integer >= 2)
+               return;
+       if (r_shadow_compilingrtlight)
        {
-               R_Mesh_Matrix(&ent->matrix);
-               if (!r_shadow_compilingrtlight)
-                       R_UpdateAllTextureInfo(ent);
+               // if compiling an rtlight, capture the meshes
+               int tri;
+               int *e;
+               float *lightmins, *lightmaxs, *v[3], *vertex3f;
                for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
                {
                        surface = model->data_surfaces + surfacelist[surfacelistindex];
-                       if (surface->texture->basematerialflags & MATERIALFLAG_NODRAW || !surface->num_triangles)
+                       texture = surface->texture;
+                       if ((texture->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) != MATERIALFLAG_WALL || !surface->num_triangles)
                                continue;
-                       if (r_shadow_compilingrtlight)
+                       e = surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle;
+                       vertex3f = surface->groupmesh->data_vertex3f;
+                       lightmins = r_shadow_compilingrtlight->cullmins;
+                       lightmaxs = r_shadow_compilingrtlight->cullmaxs;
+                       for (tri = 0;tri < surface->num_triangles;tri++, e += 3)
                        {
-                               // if compiling an rtlight, capture the mesh
-                               t = surface->texture;
-                               if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
-                               {
-#if 1
-                                       int tri;
-                                       int *e;
-                                       float *lightmins, *lightmaxs, *v[3], *vertex3f;
-                                       e = surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle;
-                                       vertex3f = surface->groupmesh->data_vertex3f;
-                                       lightmins = r_shadow_compilingrtlight->cullmins;
-                                       lightmaxs = r_shadow_compilingrtlight->cullmaxs;
-                                       for (tri = 0;tri < surface->num_triangles;tri++, e += 3)
-                                       {
-                                               v[0] = vertex3f + e[0] * 3;
-                                               v[1] = vertex3f + e[1] * 3;
-                                               v[2] = vertex3f + e[2] * 3;
-                                               if (PointInfrontOfTriangle(r_shadow_compilingrtlight->shadoworigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
-                                                       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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, 1, e);
-                                       }
-#else
-                                       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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-#endif
-                               }
+                               v[0] = vertex3f + e[0] * 3;
+                               v[1] = vertex3f + e[1] * 3;
+                               v[2] = vertex3f + e[2] * 3;
+                               if (PointInfrontOfTriangle(r_shadow_compilingrtlight->shadoworigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                       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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, 1, e);
                        }
-                       else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
+               }
+       }
+       else
+       {
+               R_UpdateAllTextureInfo(ent);
+               Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+               for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+               {
+                       if (ent == r_refdef.worldentity && !r_worldsurfacevisible[surfacelist[surfacelistindex]])
+                               continue;
+                       surface = model->data_surfaces + surfacelist[surfacelistindex];
+                       texture = surface->texture->currentframe;
+                       // FIXME: transparent surfaces need to be lit later
+                       if ((texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) != MATERIALFLAG_WALL || !surface->num_triangles)
+                               continue;
+                       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                               qglDisable(GL_CULL_FACE);
+                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                       if (!rsurface_svector3f)
                        {
-                               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->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, lightcolor, vec3_origin, vec3_origin, t->skin.base, NULL, NULL, t->skin.nmap, t->skin.gloss);
-                                       if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
-                                               qglEnable(GL_CULL_FACE);
-                               }
+                               rsurface_svector3f = varray_svector3f;
+                               rsurface_tvector3f = varray_tvector3f;
+                               rsurface_normal3f = varray_normal3f;
+                               Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f);
                        }
+                       // FIXME: add colormapping
+                       R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), rsurface_vertex3f, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, surface->groupmesh->data_texcoordtexture2f, lightcolor, vec3_origin, vec3_origin, texture->skin.base, NULL, NULL, texture->skin.nmap, texture->skin.gloss);
+                       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                               qglEnable(GL_CULL_FACE);
                }
        }
 }
index 8334f3e..15f97cb 100644 (file)
@@ -185,7 +185,7 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co
        float segmentmins[3], segmentmaxs[3];
        msurface_t *surface;
        surfmesh_t *mesh;
-       colbrushf_t *thisbrush_start, *thisbrush_end;
+       colbrushf_t *thisbrush_start = NULL, *thisbrush_end = NULL;
        matrix4x4_t startmatrix, endmatrix;
        memset(trace, 0, sizeof(*trace));
        trace->fraction = 1;
@@ -361,6 +361,11 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *skin, skinframe_t *skinfr
        }
 
        skin->skin = *skinframe;
+       skin->currentframe = skin;
+       skin->basematerialflags = MATERIALFLAG_WALL;
+       if (skin->skin.fog)
+               skin->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
+       skin->currentmaterialflags = skin->basematerialflags;
 }
 
 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
@@ -414,9 +419,9 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi
 
 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", loadmodel->name, VALUE, MIN, MAX);
 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
-extern void R_Model_Alias_Draw(entity_render_t *ent);
-extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs);
-extern void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist);
+extern void R_Q1BSP_Draw(entity_render_t *ent);
+extern void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs);
+extern void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist);
 void Mod_IDP0_Load(model_t *mod, void *buffer)
 {
        int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
@@ -451,18 +456,23 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->DrawSky = NULL;
-       loadmodel->Draw = R_Model_Alias_Draw;
-       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
-       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->Draw = R_Q1BSP_Draw;
+       loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+       loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
 
        loadmodel->num_surfaces = 1;
+       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
        loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
        loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->surfacelist = (void *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        for (i = 0;i < loadmodel->num_surfaces;i++)
+       {
+               loadmodel->surfacelist[i] = i;
                loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       }
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,65536);
@@ -616,13 +626,15 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        Mem_Free(vertremap);
 
        // load the skins
-       if ((skinfiles = Mod_LoadSkinFiles()))
+       skinfiles = Mod_LoadSkinFiles();
+       totalskins = loadmodel->numskins;
+       loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
+       loadmodel->num_textures = loadmodel->num_surfaces;
+       loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+       if (skinfiles)
        {
-               loadmodel->meshlist[0]->num_skins = totalskins = loadmodel->numskins;
-               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->meshlist[0]->data_skins, skinfiles, "default", "");
+               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
                Mod_FreeSkinFiles(skinfiles);
-               loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
                for (i = 0;i < loadmodel->numskins;i++)
                {
                        loadmodel->skinscenes[i].firstframe = i;
@@ -633,9 +645,6 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        }
        else
        {
-               loadmodel->meshlist[0]->num_skins = totalskins;
-               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t));
-               loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
                totalskins = 0;
                datapointer = startskins;
                for (i = 0;i < loadmodel->numskins;i++)
@@ -680,7 +689,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                                        sprintf (name, "%s_%i", loadmodel->name, i);
                                if (!Mod_LoadSkinFrame(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, true))
                                        Mod_LoadSkinFrame_Internal(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, r_fullbrights.integer, (qbyte *)datapointer, skinwidth, skinheight);
-                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, &tempskinframe);
                                datapointer += skinwidth * skinheight;
                                totalskins++;
                        }
@@ -695,13 +704,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                        memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
                        Mem_Free(tempskinscenes);
 
-                       tempaliasskins = loadmodel->meshlist[0]->data_skins;
-                       loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(texture_t));
-                       memcpy(loadmodel->meshlist[0]->data_skins, tempaliasskins, totalskins * sizeof(texture_t));
+                       tempaliasskins = loadmodel->data_textures;
+                       loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
+                       memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
                        Mem_Free(tempaliasskins);
 
                        // store the info about the new skin
-                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe);
+                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, &tempskinframe);
                        strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name);
                        loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
                        loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
@@ -709,16 +718,14 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                        loadmodel->skinscenes[loadmodel->numskins].loop = true;
 
                        //increase skin counts
-                       loadmodel->meshlist[0]->num_skins++;
                        loadmodel->numskins++;
                        totalskins++;
                }
        }
 
        surface = loadmodel->data_surfaces;
+       surface->texture = loadmodel->data_textures;
        surface->groupmesh = loadmodel->meshlist[0];
-       // FIXME: need to store data_skins in msurface_t, not surfmesh_t
-       surface->texture = surface->groupmesh->data_skins;
        surface->num_firsttriangle = 0;
        surface->num_triangles = surface->groupmesh->num_triangles;
        surface->num_firstvertex = 0;
@@ -770,9 +777,9 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->DrawSky = NULL;
-       loadmodel->Draw = R_Model_Alias_Draw;
-       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
-       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->Draw = R_Q1BSP_Draw;
+       loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+       loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
 
        if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
@@ -797,12 +804,17 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
                Host_Error ("%s is not a valid model", loadmodel->name);
 
        loadmodel->num_surfaces = 1;
+       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
        loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
        loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->surfacelist = (void *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        for (i = 0;i < loadmodel->num_surfaces;i++)
+       {
+               loadmodel->surfacelist[i] = i;
                loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       }
 
        loadmodel->numskins = LittleLong(pinmodel->num_skins);
        numxyz = LittleLong(pinmodel->num_xyz);
@@ -817,26 +829,27 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 
        // load the skins
        inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
-       if ((skinfiles = Mod_LoadSkinFiles()))
+       skinfiles = Mod_LoadSkinFiles();
+       if (skinfiles)
        {
-               loadmodel->meshlist[0]->num_skins = loadmodel->numskins;
-               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->meshlist[0]->data_skins, skinfiles, "default", "");
+               loadmodel->num_textures = loadmodel->num_surfaces;
+               loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
                Mod_FreeSkinFiles(skinfiles);
        }
        else if (loadmodel->numskins)
        {
                // skins found (most likely not a player model)
-               loadmodel->meshlist[0]->num_skins = loadmodel->numskins;
-               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t));
+               loadmodel->num_textures = loadmodel->num_surfaces;
+               loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
                for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
                {
                        if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
-                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, &tempskinframe);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, &tempskinframe);
                        else
                        {
                                Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
-                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, NULL);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, NULL);
                        }
                }
        }
@@ -844,9 +857,9 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
        {
                // no skins (most likely a player model)
                loadmodel->numskins = 1;
-               loadmodel->meshlist[0]->num_skins = loadmodel->numskins;
-               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins, NULL);
+               loadmodel->num_textures = loadmodel->num_surfaces;
+               loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
        }
 
        loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
@@ -969,8 +982,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 
        surface = loadmodel->data_surfaces;
        surface->groupmesh = loadmodel->meshlist[0];
-       // FIXME: need to store data_skins in msurface_t, not surfmesh_t
-       surface->texture = surface->groupmesh->data_skins;
+       surface->texture = loadmodel->data_textures;
        surface->num_firsttriangle = 0;
        surface->num_triangles = surface->groupmesh->num_triangles;
        surface->num_firstvertex = 0;
@@ -1004,9 +1016,9 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->DrawSky = NULL;
-       loadmodel->Draw = R_Model_Alias_Draw;
-       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
-       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->Draw = R_Q1BSP_Draw;
+       loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+       loadmodel->DrawLight = R_Q1BSP_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
        loadmodel->flags = LittleLong(pinmodel->flags);
        loadmodel->synctype = ST_RAND;
@@ -1054,22 +1066,27 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
        }
 
        // load meshes
+       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
        loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       loadmodel->num_textures = loadmodel->num_surfaces;
+       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
        loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->surfacelist = (void *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       loadmodel->data_textures = (void *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
        for (i = 0;i < loadmodel->num_surfaces;i++)
-               mesh = loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       {
+               loadmodel->surfacelist[i] = i;
+               loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       }
        for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end)))
        {
                if (memcmp(pinmesh->identifier, "IDP3", 4))
                        Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)\n");
                mesh = loadmodel->meshlist[i];
-               mesh->num_skins = loadmodel->numskins;
                mesh->num_morphframes = LittleLong(pinmesh->num_frames);
                mesh->num_vertices = LittleLong(pinmesh->num_vertices);
                mesh->num_triangles = LittleLong(pinmesh->num_triangles);
-               mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(texture_t));
                mesh->data_element3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
                mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
                mesh->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
@@ -1093,15 +1110,14 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
                Mod_Alias_Mesh_CompileFrameZero(mesh);
 
                if (LittleLong(pinmesh->num_shaders) >= 1)
-                       Mod_BuildAliasSkinsFromSkinFiles(mesh->data_skins, skinfiles, pinmesh->name, ((md3shader_t *)((qbyte *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
+                       Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((qbyte *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
                else
-                       for (j = 0;j < mesh->num_skins;j++)
-                               Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, NULL);
+                       for (j = 0;j < loadmodel->numskins;j++)
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
                surface = loadmodel->data_surfaces + i;
                surface->groupmesh = mesh;
-               // FIXME: need to store data_skins in msurface_t, not surfmesh_t
-               surface->texture = mesh->data_skins;
+               surface->texture = loadmodel->data_textures + i;
                surface->num_firsttriangle = 0;
                surface->num_triangles = mesh->num_triangles;
                surface->num_firstvertex = 0;
@@ -1135,9 +1151,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->DrawSky = NULL;
-       loadmodel->Draw = R_Model_Alias_Draw;
-       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
-       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->Draw = R_Q1BSP_Draw;
+       loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+       loadmodel->DrawLight = R_Q1BSP_DrawLight;
        //loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; // FIXME: implement collisions
        loadmodel->flags = 0; // there are no flags on zym models
        loadmodel->synctype = ST_RAND;
@@ -1291,12 +1307,19 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
        //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
        //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
 
+       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
        loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       loadmodel->num_textures = loadmodel->num_surfaces;
+       data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
        loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->surfacelist = (void *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       loadmodel->data_textures = (void *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
        for (i = 0;i < loadmodel->num_surfaces;i++)
-               mesh = loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       {
+               loadmodel->surfacelist[i] = i;
+               loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+       }
 
        //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
        //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
@@ -1314,9 +1337,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
                        Host_Error("%s corrupt renderlist (wrong size)\n", loadmodel->name);
                mesh = loadmodel->meshlist[i];
-               mesh->num_skins = loadmodel->numskins;
                mesh->num_triangles = count;
-               mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(texture_t));
                mesh->data_element3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
                mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
                outelements = mesh->data_element3i;
@@ -1383,15 +1404,14 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                // name as the section name
                shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
                if (shadername[0])
-                       Mod_BuildAliasSkinsFromSkinFiles(mesh->data_skins, skinfiles, shadername, shadername);
+                       Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
                else
-                       for (j = 0;j < mesh->num_skins;j++)
-                               Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, NULL);
+                       for (j = 0;j < loadmodel->numskins;j++)
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
                surface = loadmodel->data_surfaces + i;
                surface->groupmesh = mesh;
-               // FIXME: need to store data_skins in msurface_t, not surfmesh_t
-               surface->texture = mesh->data_skins;
+               surface->texture = loadmodel->data_textures + i;
                surface->num_firsttriangle = 0;
                surface->num_triangles = mesh->num_triangles;
                surface->num_firstvertex = 0;
index 614ac4c..5004a97 100644 (file)
@@ -99,9 +99,6 @@ typedef struct surfmesh_s
        float *data_texcoorddetail2f; // float[verts*2] texcoords for detail texture
        float *data_lightmapcolor4f;
        int *data_lightmapoffsets; // index into surface's lightmap samples for vertex lighting
-       // if a model these will be a skin list to choose from
-       int num_skins;
-       struct texture_s *data_skins;
        // morph blending, these are zero if model is skeletal or static
        int num_morphframes;
        float *data_morphvertex3f;