the merging of alias and bsp model rendering begins... purely cosmetic changes in...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 11 May 2005 18:22:48 +0000 (18:22 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 11 May 2005 18:22:48 +0000 (18:22 +0000)
merged model_alias_t into model_t and removed alias prefixes from those fields
merged model_brush_t surface and texture stuff into model_t (num_surfaces, num_textures, etc)
made alias model code use model_t data_surfaces instead of alias meshes

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

14 files changed:
gl_models.c
gl_rmain.c
gl_rsurf.c
model_alias.c
model_alias.h
model_brush.c
model_brush.h
model_shared.c
model_shared.h
portals.c
pr_cmds.c
prvm_cmds.c
r_shadow.c
render.h

index 850e90d..6bd61f4 100644 (file)
@@ -3,7 +3,7 @@
 #include "r_shadow.h"
 
 static texture_t r_aliasnotexture;
-static texture_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh)
+static texture_t *R_FetchAliasSkin(const entity_render_t *ent, const surfmesh_t *mesh)
 {
        model_t *model = ent->model;
        if (model->numskins)
@@ -36,7 +36,8 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
        qbyte *bcolor;
        rmeshstate_t m;
        const entity_render_t *ent = calldata1;
-       aliasmesh_t *mesh = ent->model->alias.aliasdata_meshes + calldata2;
+       msurface_t *surface = ent->model->data_surfaces + calldata2;
+       surfmesh_t *mesh = surface->groupmesh;
        texture_t *texture;
 
        R_Mesh_Matrix(&ent->matrix);
@@ -106,8 +107,8 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
        colorscale = 1.0f;
        if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1)
        {
-               vertex3f = mesh->data_basevertex3f;
-               normal3f = mesh->data_basenormal3f;
+               vertex3f = mesh->data_vertex3f;
+               normal3f = mesh->data_normal3f;
        }
        else
        {
@@ -120,7 +121,7 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
 
        memset(&m, 0, sizeof(m));
        m.pointer_vertex = vertex3f;
-       m.pointer_texcoord[0] = mesh->data_texcoord2f;
+       m.pointer_texcoord[0] = mesh->data_texcoordtexture2f;
        if (gl_combine.integer)
        {
                colorscale *= 0.25f;
@@ -148,7 +149,7 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
        {
                doglow = false;
                m.tex[1] = R_GetTexture(texture->skin.glow);
-               m.pointer_texcoord[1] = mesh->data_texcoord2f;
+               m.pointer_texcoord[1] = mesh->data_texcoordtexture2f;
                m.texcombinergb[1] = GL_ADD;
        }
        R_Mesh_State(&m);
@@ -249,26 +250,29 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
 
 void R_Model_Alias_Draw(entity_render_t *ent)
 {
-       int meshnum;
-       aliasmesh_t *mesh;
+       int surfacenum;
+       msurface_t *surface;
+       surfmesh_t *mesh;
        if (ent->alpha < (1.0f / 64.0f))
                return; // basically completely transparent
 
        c_models++;
 
-       for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++)
+       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, meshnum);
+                       R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawAliasModelCallback, ent, surfacenum);
                else
-                       R_DrawAliasModelCallback(ent, meshnum);
+                       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 meshnum;
-       aliasmesh_t *mesh;
+       int surfacenum;
+       msurface_t *surface;
+       surfmesh_t *mesh;
        texture_t *texture;
        float projectdistance, *vertex3f;
        if (!(ent->flags & RENDER_SHADOW))
@@ -279,13 +283,14 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor
        projectdistance = lightradius + ent->model->radius;// - sqrt(DotProduct(relativelightorigin, relativelightorigin));
        if (projectdistance > 0.1)
        {
-               for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++)
+               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_basevertex3f;
+                               vertex3f = mesh->data_vertex3f;
                        else
                        {
                                vertex3f = varray_vertex3f;
@@ -301,12 +306,14 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor
 
 void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist)
 {
-       int c, meshnum;
+       int c;
        float fog, ifog, lightcolorbase[3], lightcolorpants[3], lightcolorshirt[3];
        float *vertex3f, *svector3f, *tvector3f, *normal3f;
        vec3_t diff;
        qbyte *bcolor;
-       aliasmesh_t *mesh;
+       int surfacenum;
+       msurface_t *surface;
+       surfmesh_t *mesh;
        texture_t *texture;
 
        fog = 0;
@@ -356,18 +363,19 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsur
                }
        }
 
-       for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++)
+       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_basevertex3f;
-                       svector3f = mesh->data_basesvector3f;
-                       tvector3f = mesh->data_basetvector3f;
-                       normal3f = mesh->data_basenormal3f;
+                       vertex3f = mesh->data_vertex3f;
+                       svector3f = mesh->data_svector3f;
+                       tvector3f = mesh->data_tvector3f;
+                       normal3f = mesh->data_normal3f;
                }
                else
                {
@@ -376,10 +384,10 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsur
                        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_texcoord2f, mesh->data_element3i, svector3f, tvector3f, normal3f);
+                       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_texcoord2f, 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);
+               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 f82c64b..834017c 100644 (file)
@@ -107,6 +107,8 @@ cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
 
 cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"};
 
+cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
+
 rtexturepool_t *r_main_texturepool;
 rtexture_t *r_bloom_texture_screen;
 rtexture_t *r_bloom_texture_bloom;
@@ -512,6 +514,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable(&r_bloom_resolution);
        Cvar_RegisterVariable(&r_bloom_power);
        Cvar_RegisterVariable(&developer_texturelogging);
+       Cvar_RegisterVariable(&gl_lightmaps);
        if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
                Cvar_SetValue("r_fullbrights", 0);
        R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
@@ -1007,6 +1010,8 @@ static void R_BlendView(void)
 
 void R_RenderScene(void);
 
+matrix4x4_t r_waterscrollmatrix;
+
 /*
 ================
 R_RenderView
@@ -1083,6 +1088,8 @@ void R_RenderScene(void)
 
        GL_SetupView_Orientation_FromEntity(&r_view_matrix);
 
+       Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
+
        R_SkyStartFrame();
 
        R_WorldVisibility();
@@ -1444,4 +1451,1193 @@ 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)
+       {
+               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;
+       }
+       t->currentmaterialflags = t->basematerialflags;
+       t->currentalpha = ent->alpha;
+       if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
+               t->currentalpha *= r_wateralpha.value;
+       if (!(ent->flags & RENDER_LIGHT))
+               t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
+       if (ent->effects & EF_ADDITIVE)
+               t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
+       else if (t->currentalpha < 1)
+               t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
+}
+
+void R_UpdateAllTextureInfo(entity_render_t *ent)
+{
+       int i;
+       if (ent->model)
+               for (i = 0;i < ent->model->num_textures;i++)
+                       R_UpdateTextureInfo(ent, ent->model->data_textures + i);
+}
+
+static void RSurf_DeformVertices(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 (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
+       {
+               // a single autosprite surface can contain multiple sprites...
+               VectorClear(forward);
+               VectorClear(right);
+               VectorSet(up, 0, 0, 1);
+               for (j = 0;j < surface->num_vertices - 3;j += 4)
+               {
+                       VectorClear(center);
+                       for (i = 0;i < 4;i++)
+                               VectorAdd(center, (surface->groupmesh->data_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_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]);
+                       forward[0] = modelorg[0] - center[0];
+                       forward[1] = modelorg[1] - center[1];
+                       VectorNormalize(forward);
+                       right[0] = forward[1];
+                       right[1] = -forward[0];
+                       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);
+               }
+       }
+       else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
+       {
+               Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
+               Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
+               Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
+               // a single autosprite surface can contain multiple sprites...
+               for (j = 0;j < surface->num_vertices - 3;j += 4)
+               {
+                       VectorClear(center);
+                       for (i = 0;i < 4;i++)
+                               VectorAdd(center, (surface->groupmesh->data_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_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]);
+                       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);
+               }
+       }
+       else
+               memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
+}
+
+// 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)
+{
+       if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+       {
+               RSurf_DeformVertices(ent, texture, surface, modelorg);
+               return varray_vertex3f;
+       }
+       else
+               return surface->groupmesh->data_vertex3f;
+}
+#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;
+       float *c;
+       float diff[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;
+       rmeshstate_t m;
+       texture = texture->currentframe;
+       if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
+               return;
+       c_faces += texturenumsurfaces;
+       // gl_lightmaps debugging mode skips normal texturing
+       if (gl_lightmaps.integer)
+       {
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+               GL_DepthMask(true);
+               GL_DepthTest(true);
+               qglDisable(GL_CULL_FACE);
+               GL_Color(1, 1, 1, 1);
+               memset(&m, 0, sizeof(m));
+               R_Mesh_State(&m);
+               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+               {
+                       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);
+                       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);
+               }
+               qglEnable(GL_CULL_FACE);
+               return;
+       }
+       GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+       GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
+       if (texture->currentmaterialflags & MATERIALFLAG_ADD)
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+       else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       else
+               GL_BlendFunc(GL_ONE, GL_ZERO);
+       // water waterscrolling in texture matrix
+       waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
+       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglDisable(GL_CULL_FACE);
+       if (texture->currentmaterialflags & MATERIALFLAG_SKY)
+       {
+               if (skyrendernow)
+               {
+                       skyrendernow = false;
+                       if (skyrendermasked)
+                               R_Sky();
+               }
+               // LordHavoc: HalfLife maps have freaky skypolys...
+               //if (!ent->model->brush.ishlbsp)
+               {
+                       R_Mesh_Matrix(&ent->matrix);
+                       GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
+                       if (skyrendermasked)
+                       {
+                               // depth-only (masking)
+                               GL_ColorMask(0,0,0,0);
+                               // just to make sure that braindead drivers don't draw anything
+                               // despite that colormask...
+                               GL_BlendFunc(GL_ZERO, GL_ONE);
+                       }
+                       else
+                       {
+                               // fog sky
+                               GL_BlendFunc(GL_ONE, GL_ZERO);
+                       }
+                       GL_DepthMask(true);
+                       GL_DepthTest(true);
+                       memset(&m, 0, sizeof(m));
+                       R_Mesh_State(&m);
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
+                               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_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
+               }
+       }
+       else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
+       {
+               // NVIDIA Geforce3 distortion texture shader on water
+               float args[4] = {0.05f,0,0,0.04f};
+               memset(&m, 0, sizeof(m));
+               m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
+               m.tex[1] = R_GetTexture(texture->skin.base);
+               m.texcombinergb[0] = GL_REPLACE;
+               m.texcombinergb[1] = GL_REPLACE;
+               Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
+               m.texmatrix[1] = r_waterscrollmatrix;
+               R_Mesh_State(&m);
+
+               GL_Color(1, 1, 1, texture->currentalpha);
+               GL_ActiveTexture(0);
+               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+               GL_ActiveTexture(1);
+               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
+               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
+               qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
+               qglEnable(GL_TEXTURE_SHADER_NV);
+
+               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+               {
+                       surface = texturesurfacelist[texturesurfaceindex];
+                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
+                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+                       GL_LockArrays(0, 0);
+               }
+
+               qglDisable(GL_TEXTURE_SHADER_NV);
+               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+               GL_ActiveTexture(0);
+       }
+       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 (dobase && dolightmap && gl_combine.integer)
+                       {
+                               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)
+                               {
+                                       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_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);
+                                               }
+                                       }
+                                       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)
+                       {
+                               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
+                               {
+                                       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);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else
+               {
+                       if (!dolightmap && dobase)
+                       {
+                               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);
+                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                               {
+                                       surface = texturesurfacelist[texturesurfaceindex];
+                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
+                               }
+                       }
+                       if (r_lightmapintensity <= 0 && dolightmap && dobase)
+                       {
+                               dolightmap = false;
+                               dobase = false;
+                               GL_Color(0, 0, 0, 1);
+                               memset(&m, 0, sizeof(m));
+                               R_Mesh_State(&m);
+                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                               {
+                                       surface = texturesurfacelist[texturesurfaceindex];
+                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
+                               }
+                       }
+                       if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
+                       {
+                               // 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);
+                                               }
+                                       }
+                               }
+                       }
+                       // single texture
+                       if (dolightmap)
+                       {
+                               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))
+                               {
+                                       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);
+                                       }
+                               }
+                               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);
+                                                       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);
+                                       }
+                               }
+                       }
+                       if (dobase)
+                       {
+                               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
+                               {
+                                       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);
+                                       }
+                               }
+                       }
+               }
+               if (doambient)
+               {
+                       doambient = false;
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       GL_DepthMask(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);
+                       base = r_ambient.value * (1.0f / 64.0f);
+                       r = ent->colormod[0] * colorscale * base;
+                       g = ent->colormod[1] * colorscale * base;
+                       b = ent->colormod[2] * colorscale * base;
+                       a = texture->currentalpha;
+                       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] = 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;
+                               }
+                               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 (dodetail)
+               {
+                       GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+                       GL_DepthMask(false);
+                       GL_Color(1, 1, 1, 1);
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(texture->skin.detail);
+                       R_Mesh_State(&m);
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               R_Mesh_VertexPointer(RSurf_GetVertexPointer(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));
+                               GL_LockArrays(0, 0);
+                       }
+               }
+               if (doglow)
+               {
+                       // if glow was not already done using multitexture, do it now.
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       GL_DepthMask(false);
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(texture->skin.glow);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       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;
+                       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
+                       {
+                               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);
+                               }
+                       }
+               }
+               if (dofogpass)
+               {
+                       // if this is opaque use alpha blend which will darken the earlier
+                       // passes cheaply.
+                       //
+                       // if this is an alpha blended material, all the earlier passes
+                       // were darkened by fog already, so we only need to add the fog
+                       // color ontop through the fog mask texture
+                       //
+                       // if this is an additive blended material, all the earlier passes
+                       // 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)
+                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       else
+                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       GL_DepthMask(false);
+                       memset(&m, 0, sizeof(m));
+                       m.tex[0] = R_GetTexture(texture->skin.fog);
+                       if (waterscrolling)
+                               m.texmatrix[0] = r_waterscrollmatrix;
+                       R_Mesh_State(&m);
+                       r = fogcolor[0];
+                       g = fogcolor[1];
+                       b = fogcolor[2];
+                       a = texture->currentalpha;
+                       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);
+                               //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)
+                                       {
+                                               VectorSubtract(v, modelorg, diff);
+                                               f = exp(fogdensity/DotProduct(diff, diff));
+                                               c[0] = r;
+                                               c[1] = g;
+                                               c[2] = b;
+                                               c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * 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 = exp(fogdensity/DotProduct(diff, diff));
+                                               c[0] = r;
+                                               c[1] = g;
+                                               c[2] = b;
+                                               c[3] = f * 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);
+                       }
+               }
+       }
+       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglEnable(GL_CULL_FACE);
+}
+
+static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
+{
+       const entity_render_t *ent = calldata1;
+       const msurface_t *surface = ent->model->data_surfaces + calldata2;
+       vec3_t modelorg;
+       texture_t *texture;
+
+       texture = surface->texture;
+       if (texture->basematerialflags & MATERIALFLAG_SKY)
+               return; // transparent sky is too difficult
+       R_UpdateTextureInfo(ent, texture);
+
+       R_Mesh_Matrix(&ent->matrix);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+       R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
+}
+
+void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
+{
+       int texturesurfaceindex;
+       const msurface_t *surface;
+       vec3_t tempcenter, center;
+       if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+       {
+               // drawing sky transparently would be too difficult
+               if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
+               {
+                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+                       {
+                               surface = texturesurfacelist[texturesurfaceindex];
+                               tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+                               tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+                               tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+                               Matrix4x4_Transform(&ent->matrix, tempcenter, center);
+                               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
+                       }
+               }
+       }
+       else
+               R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
+}
+
+extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
+void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
+{
+       int i, j, f, flagsmask;
+       msurface_t *surface, **surfacechain;
+       texture_t *t, *texture;
+       model_t *model = ent->model;
+       vec3_t modelorg;
+       const int maxsurfacelist = 1024;
+       int numsurfacelist = 0;
+       const msurface_t *surfacelist[1024];
+       if (model == NULL)
+               return;
+       R_Mesh_Matrix(&ent->matrix);
+       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
+
+       // update light styles
+       if (!skysurfaces && model->brushq1.light_styleupdatechains)
+       {
+               for (i = 0;i < model->brushq1.light_styles;i++)
+               {
+                       if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
+                       {
+                               model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
+                               if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
+                                       for (;(surface = *surfacechain);surfacechain++)
+                                               surface->cached_dlight = true;
+                       }
+               }
+       }
+
+       R_UpdateAllTextureInfo(ent);
+       flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
+       f = 0;
+       t = NULL;
+       texture = NULL;
+       numsurfacelist = 0;
+       if (ent == r_refdef.worldentity)
+       {
+               for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+               {
+                       if (!r_worldsurfacevisible[j])
+                               continue;
+                       if (t != surface->texture)
+                       {
+                               if (numsurfacelist)
+                               {
+                                       R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
+                                       numsurfacelist = 0;
+                               }
+                               t = surface->texture;
+                               f = t->currentmaterialflags & flagsmask;
+                               texture = t->currentframe;
+                       }
+                       if (f && surface->num_triangles)
+                       {
+                               // if lightmap parameters changed, rebuild lightmap texture
+                               if (surface->cached_dlight && surface->lightmapinfo->samples)
+                                       R_BuildLightMap(ent, surface);
+                               // add face to draw list
+                               surfacelist[numsurfacelist++] = surface;
+                               if (numsurfacelist >= maxsurfacelist)
+                               {
+                                       R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
+                                       numsurfacelist = 0;
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+               {
+                       if (t != surface->texture)
+                       {
+                               if (numsurfacelist)
+                               {
+                                       R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
+                                       numsurfacelist = 0;
+                               }
+                               t = surface->texture;
+                               f = t->currentmaterialflags & flagsmask;
+                               texture = t->currentframe;
+                       }
+                       if (f && surface->num_triangles)
+                       {
+                               // if lightmap parameters changed, rebuild lightmap texture
+                               if (surface->cached_dlight && surface->lightmapinfo->samples)
+                                       R_BuildLightMap(ent, surface);
+                               // add face to draw list
+                               surfacelist[numsurfacelist++] = surface;
+                               if (numsurfacelist >= maxsurfacelist)
+                               {
+                                       R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
+                                       numsurfacelist = 0;
+                               }
+                       }
+               }
+       }
+       if (numsurfacelist)
+               R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
+}
 
index 3f61cf9..839cf24 100644 (file)
@@ -33,7 +33,6 @@ cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
 cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"};
 cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"};
 cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"};
-cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
 
 // flag arrays used for visibility checking on world model
 // (all other entities have no per-surface/per-leaf visibility checks)
@@ -41,7 +40,7 @@ cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
 qbyte r_pvsbits[(32768+7)>>3];
 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
 qbyte r_worldleafvisible[32768];
-// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_surfaces
+// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces
 qbyte r_worldsurfacevisible[262144];
 
 /*
@@ -51,7 +50,7 @@ R_BuildLightMap
 Combine and scale multiple lightmaps into the 8.8 format in blocklights
 ===============
 */
-static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
+void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
 {
        int smax, tmax, i, j, size, size3, maps, stride, l;
        unsigned int *bl, scale;
@@ -169,7 +168,7 @@ loc0:
                impact[2] = origin[2] - node->plane->normal[2] * ndist;
        }
 
-       for (surface = model->brush.data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++)
+       for (surface = model->data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++)
        {
                if (surface->lightmapinfo->stainsamples)
                {
@@ -296,1198 +295,6 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int
 =============================================================
 */
 
-static void RSurf_DeformVertices(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 (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
-       {
-               // a single autosprite surface can contain multiple sprites...
-               VectorClear(forward);
-               VectorClear(right);
-               VectorSet(up, 0, 0, 1);
-               for (j = 0;j < surface->num_vertices - 3;j += 4)
-               {
-                       VectorClear(center);
-                       for (i = 0;i < 4;i++)
-                               VectorAdd(center, (surface->groupmesh->data_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_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]);
-                       forward[0] = modelorg[0] - center[0];
-                       forward[1] = modelorg[1] - center[1];
-                       VectorNormalize(forward);
-                       right[0] = forward[1];
-                       right[1] = -forward[0];
-                       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);
-               }
-       }
-       else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
-       {
-               Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
-               Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
-               Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
-               // a single autosprite surface can contain multiple sprites...
-               for (j = 0;j < surface->num_vertices - 3;j += 4)
-               {
-                       VectorClear(center);
-                       for (i = 0;i < 4;i++)
-                               VectorAdd(center, (surface->groupmesh->data_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_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]);
-                       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);
-               }
-       }
-       else
-               memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
-}
-
-// 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)
-{
-       if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
-       {
-               RSurf_DeformVertices(ent, texture, surface, modelorg);
-               return varray_vertex3f;
-       }
-       else
-               return surface->groupmesh->data_vertex3f;
-}
-#endif
-
-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)
-       {
-               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;
-       }
-       t->currentmaterialflags = t->basematerialflags;
-       t->currentalpha = ent->alpha;
-       if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
-               t->currentalpha *= r_wateralpha.value;
-       if (!(ent->flags & RENDER_LIGHT))
-               t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
-       if (ent->effects & EF_ADDITIVE)
-               t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
-       else if (t->currentalpha < 1)
-               t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
-}
-
-matrix4x4_t r_surf_waterscrollmatrix;
-
-void R_UpdateAllTextureInfo(entity_render_t *ent)
-{
-       int i;
-       Matrix4x4_CreateTranslate(&r_surf_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
-       if (ent->model)
-               for (i = 0;i < ent->model->brush.num_textures;i++)
-                       R_UpdateTextureInfo(ent, ent->model->brush.data_textures + i);
-}
-
-static void R_DrawSurfaceList(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;
-       float *c;
-       float diff[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;
-       rmeshstate_t m;
-       texture = texture->currentframe;
-       if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
-               return;
-       c_faces += texturenumsurfaces;
-       // gl_lightmaps debugging mode skips normal texturing
-       if (gl_lightmaps.integer)
-       {
-               GL_BlendFunc(GL_ONE, GL_ZERO);
-               GL_DepthMask(true);
-               GL_DepthTest(true);
-               qglDisable(GL_CULL_FACE);
-               GL_Color(1, 1, 1, 1);
-               memset(&m, 0, sizeof(m));
-               R_Mesh_State(&m);
-               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-               {
-                       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);
-                       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);
-               }
-               qglEnable(GL_CULL_FACE);
-               return;
-       }
-       GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
-       GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
-       if (texture->currentmaterialflags & MATERIALFLAG_ADD)
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-       else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       else
-               GL_BlendFunc(GL_ONE, GL_ZERO);
-       // water waterscrolling in texture matrix
-       waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
-       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
-               qglDisable(GL_CULL_FACE);
-       if (texture->currentmaterialflags & MATERIALFLAG_SKY)
-       {
-               if (skyrendernow)
-               {
-                       skyrendernow = false;
-                       if (skyrendermasked)
-                               R_Sky();
-               }
-               // LordHavoc: HalfLife maps have freaky skypolys...
-               //if (!ent->model->brush.ishlbsp)
-               {
-                       R_Mesh_Matrix(&ent->matrix);
-                       GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
-                       if (skyrendermasked)
-                       {
-                               // depth-only (masking)
-                               GL_ColorMask(0,0,0,0);
-                               // just to make sure that braindead drivers don't draw anything
-                               // despite that colormask...
-                               GL_BlendFunc(GL_ZERO, GL_ONE);
-                       }
-                       else
-                       {
-                               // fog sky
-                               GL_BlendFunc(GL_ONE, GL_ZERO);
-                       }
-                       GL_DepthMask(true);
-                       GL_DepthTest(true);
-                       memset(&m, 0, sizeof(m));
-                       R_Mesh_State(&m);
-                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                       {
-                               surface = texturesurfacelist[texturesurfaceindex];
-                               R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
-                               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_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
-               }
-       }
-       else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
-       {
-               // NVIDIA Geforce3 distortion texture shader on water
-               float args[4] = {0.05f,0,0,0.04f};
-               memset(&m, 0, sizeof(m));
-               m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
-               m.tex[1] = R_GetTexture(texture->skin.base);
-               m.texcombinergb[0] = GL_REPLACE;
-               m.texcombinergb[1] = GL_REPLACE;
-               Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
-               m.texmatrix[1] = r_surf_waterscrollmatrix;
-               R_Mesh_State(&m);
-
-               GL_Color(1, 1, 1, texture->currentalpha);
-               GL_ActiveTexture(0);
-               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
-               GL_ActiveTexture(1);
-               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
-               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
-               qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
-               qglEnable(GL_TEXTURE_SHADER_NV);
-
-               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-               {
-                       surface = texturesurfacelist[texturesurfaceindex];
-                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
-                       R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
-                       GL_LockArrays(0, 0);
-               }
-
-               qglDisable(GL_TEXTURE_SHADER_NV);
-               qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
-               GL_ActiveTexture(0);
-       }
-       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 (dobase && dolightmap && gl_combine.integer)
-                       {
-                               dobase = false;
-                               memset(&m, 0, sizeof(m));
-                               m.tex[1] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[1] = r_surf_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)
-                               {
-                                       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_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);
-                                               }
-                                       }
-                                       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)
-                       {
-                               dobase = false;
-                               memset(&m, 0, sizeof(m));
-                               m.tex[0] = R_GetTexture(texture->skin.base);
-                               if (waterscrolling)
-                                       m.texmatrix[0] = r_surf_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
-                               {
-                                       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);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               else
-               {
-                       if (!dolightmap && dobase)
-                       {
-                               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_surf_waterscrollmatrix;
-                               R_Mesh_State(&m);
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                               {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
-                               }
-                       }
-                       if (r_lightmapintensity <= 0 && dolightmap && dobase)
-                       {
-                               dolightmap = false;
-                               dobase = false;
-                               GL_Color(0, 0, 0, 1);
-                               memset(&m, 0, sizeof(m));
-                               R_Mesh_State(&m);
-                               for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                               {
-                                       surface = texturesurfacelist[texturesurfaceindex];
-                                       R_Mesh_VertexPointer(RSurf_GetVertexPointer(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);
-                               }
-                       }
-                       if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
-                       {
-                               // 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_surf_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);
-                                               }
-                                       }
-                               }
-                       }
-                       // single texture
-                       if (dolightmap)
-                       {
-                               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))
-                               {
-                                       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);
-                                       }
-                               }
-                               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);
-                                                       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);
-                                       }
-                               }
-                       }
-                       if (dobase)
-                       {
-                               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_surf_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
-                               {
-                                       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);
-                                       }
-                               }
-                       }
-               }
-               if (doambient)
-               {
-                       doambient = false;
-                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-                       GL_DepthMask(false);
-                       memset(&m, 0, sizeof(m));
-                       m.tex[0] = R_GetTexture(texture->skin.base);
-                       if (waterscrolling)
-                               m.texmatrix[0] = r_surf_waterscrollmatrix;
-                       m.pointer_color = varray_color4f;
-                       colorscale = 1;
-                       if (gl_combine.integer)
-                       {
-                               m.texrgbscale[0] = 4;
-                               colorscale *= 0.25f;
-                       }
-                       R_Mesh_State(&m);
-                       base = r_ambient.value * (1.0f / 64.0f);
-                       r = ent->colormod[0] * colorscale * base;
-                       g = ent->colormod[1] * colorscale * base;
-                       b = ent->colormod[2] * colorscale * base;
-                       a = texture->currentalpha;
-                       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] = 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;
-                               }
-                               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 (dodetail)
-               {
-                       GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
-                       GL_DepthMask(false);
-                       GL_Color(1, 1, 1, 1);
-                       memset(&m, 0, sizeof(m));
-                       m.tex[0] = R_GetTexture(texture->skin.detail);
-                       R_Mesh_State(&m);
-                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                       {
-                               surface = texturesurfacelist[texturesurfaceindex];
-                               R_Mesh_VertexPointer(RSurf_GetVertexPointer(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));
-                               GL_LockArrays(0, 0);
-                       }
-               }
-               if (doglow)
-               {
-                       // if glow was not already done using multitexture, do it now.
-                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-                       GL_DepthMask(false);
-                       memset(&m, 0, sizeof(m));
-                       m.tex[0] = R_GetTexture(texture->skin.glow);
-                       if (waterscrolling)
-                               m.texmatrix[0] = r_surf_waterscrollmatrix;
-                       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;
-                       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
-                       {
-                               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);
-                               }
-                       }
-               }
-               if (dofogpass)
-               {
-                       // if this is opaque use alpha blend which will darken the earlier
-                       // passes cheaply.
-                       //
-                       // if this is an alpha blended material, all the earlier passes
-                       // were darkened by fog already, so we only need to add the fog
-                       // color ontop through the fog mask texture
-                       //
-                       // if this is an additive blended material, all the earlier passes
-                       // 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)
-                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-                       else
-                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                       GL_DepthMask(false);
-                       memset(&m, 0, sizeof(m));
-                       m.tex[0] = R_GetTexture(texture->skin.fog);
-                       if (waterscrolling)
-                               m.texmatrix[0] = r_surf_waterscrollmatrix;
-                       R_Mesh_State(&m);
-                       r = fogcolor[0];
-                       g = fogcolor[1];
-                       b = fogcolor[2];
-                       a = texture->currentalpha;
-                       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);
-                               //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)
-                                       {
-                                               VectorSubtract(v, modelorg, diff);
-                                               f = exp(fogdensity/DotProduct(diff, diff));
-                                               c[0] = r;
-                                               c[1] = g;
-                                               c[2] = b;
-                                               c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * 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 = exp(fogdensity/DotProduct(diff, diff));
-                                               c[0] = r;
-                                               c[1] = g;
-                                               c[2] = b;
-                                               c[3] = f * 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);
-                       }
-               }
-       }
-       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
-               qglEnable(GL_CULL_FACE);
-}
-
-static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
-{
-       const entity_render_t *ent = calldata1;
-       const msurface_t *surface = ent->model->brush.data_surfaces + calldata2;
-       vec3_t modelorg;
-       texture_t *texture;
-
-       texture = surface->texture;
-       if (texture->basematerialflags & MATERIALFLAG_SKY)
-               return; // transparent sky is too difficult
-       R_UpdateTextureInfo(ent, texture);
-
-       R_Mesh_Matrix(&ent->matrix);
-       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
-       R_DrawSurfaceList(ent, texture, 1, &surface, modelorg);
-}
-
-void R_QueueSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
-{
-       int texturesurfaceindex;
-       const msurface_t *surface;
-       vec3_t tempcenter, center;
-       if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
-       {
-               // drawing sky transparently would be too difficult
-               if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
-               {
-                       for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
-                       {
-                               surface = texturesurfacelist[texturesurfaceindex];
-                               tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
-                               tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
-                               tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
-                               Matrix4x4_Transform(&ent->matrix, tempcenter, center);
-                               R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces);
-                       }
-               }
-       }
-       else
-               R_DrawSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
-}
-
-void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
-{
-       int i, j, f, flagsmask;
-       msurface_t *surface, **surfacechain;
-       texture_t *t, *texture;
-       model_t *model = ent->model;
-       vec3_t modelorg;
-       const int maxsurfacelist = 1024;
-       int numsurfacelist = 0;
-       const msurface_t *surfacelist[1024];
-       if (model == NULL)
-               return;
-       R_Mesh_Matrix(&ent->matrix);
-       Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
-
-       // update light styles
-       if (!skysurfaces && model->brushq1.light_styleupdatechains)
-       {
-               for (i = 0;i < model->brushq1.light_styles;i++)
-               {
-                       if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
-                       {
-                               model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
-                               if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
-                                       for (;(surface = *surfacechain);surfacechain++)
-                                               surface->cached_dlight = true;
-                       }
-               }
-       }
-
-       R_UpdateAllTextureInfo(ent);
-       flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
-       f = 0;
-       t = NULL;
-       texture = NULL;
-       numsurfacelist = 0;
-       if (ent == r_refdef.worldentity)
-       {
-               for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
-               {
-                       if (!r_worldsurfacevisible[j])
-                               continue;
-                       if (t != surface->texture)
-                       {
-                               if (numsurfacelist)
-                               {
-                                       R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
-                                       numsurfacelist = 0;
-                               }
-                               t = surface->texture;
-                               f = t->currentmaterialflags & flagsmask;
-                               texture = t->currentframe;
-                       }
-                       if (f && surface->num_triangles)
-                       {
-                               // if lightmap parameters changed, rebuild lightmap texture
-                               if (surface->cached_dlight && surface->lightmapinfo->samples)
-                                       R_BuildLightMap(ent, surface);
-                               // add face to draw list
-                               surfacelist[numsurfacelist++] = surface;
-                               if (numsurfacelist >= maxsurfacelist)
-                               {
-                                       R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
-                                       numsurfacelist = 0;
-                               }
-                       }
-               }
-       }
-       else
-       {
-               for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
-               {
-                       if (t != surface->texture)
-                       {
-                               if (numsurfacelist)
-                               {
-                                       R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
-                                       numsurfacelist = 0;
-                               }
-                               t = surface->texture;
-                               f = t->currentmaterialflags & flagsmask;
-                               texture = t->currentframe;
-                       }
-                       if (f && surface->num_triangles)
-                       {
-                               // if lightmap parameters changed, rebuild lightmap texture
-                               if (surface->cached_dlight && surface->lightmapinfo->samples)
-                                       R_BuildLightMap(ent, surface);
-                               // add face to draw list
-                               surfacelist[numsurfacelist++] = surface;
-                               if (numsurfacelist >= maxsurfacelist)
-                               {
-                                       R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
-                                       numsurfacelist = 0;
-                               }
-                       }
-               }
-       }
-       if (numsurfacelist)
-               R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
-}
-
 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
 {
        int i;
@@ -1600,7 +407,7 @@ void R_WorldVisibility(void)
                model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
 
        // clear the visible surface and leaf flags arrays
-       memset(r_worldsurfacevisible, 0, model->brush.num_surfaces);
+       memset(r_worldsurfacevisible, 0, model->num_surfaces);
        memset(r_worldleafvisible, 0, model->brush.num_leafs);
 
        // if the user prefers surfaceworldnode (testing?) or the viewleaf could
@@ -1689,7 +496,7 @@ void R_Q1BSP_Draw(entity_render_t *ent)
                for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
                        if (brush->colbrushf && brush->colbrushf->numtriangles)
                                R_DrawCollisionBrush(brush->colbrushf);
-               for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+               for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
                        if (surface->num_collisiontriangles)
                                R_DrawCollisionSurface(ent, surface);
                qglPolygonOffset(0, 0);
@@ -1760,7 +567,7 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
                                int surfaceindex = leaf->firstleafsurface[leafsurfaceindex];
                                if (!CHECKPVSBIT(info->outsurfacepvs, surfaceindex))
                                {
-                                       msurface_t *surface = info->model->brush.data_surfaces + surfaceindex;
+                                       msurface_t *surface = info->model->data_surfaces + surfaceindex;
                                        if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs))
                                        if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
                                        {
@@ -1861,7 +668,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
                        R_UpdateAllTextureInfo(ent);
                for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
                {
-                       surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
+                       surface = model->data_surfaces + surfacelist[surfacelistindex];
                        if ((surface->texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
                                continue;
                        if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
@@ -1885,7 +692,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces,
                        R_UpdateAllTextureInfo(ent);
                for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
                {
-                       surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
+                       surface = model->data_surfaces + surfacelist[surfacelistindex];
                        if (surface->texture->basematerialflags & MATERIALFLAG_NODRAW || !surface->num_triangles)
                                continue;
                        if (r_shadow_compilingrtlight)
@@ -1957,7 +764,6 @@ void GL_Surf_Init(void)
        Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
        Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);
        Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
-       Cvar_RegisterVariable(&gl_lightmaps);
 
        //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
 }
index 2fb1a35..8334f3e 100644 (file)
@@ -26,27 +26,27 @@ void Mod_AliasInit (void)
 {
 }
 
-void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameblend, const aliasmesh_t *mesh, float *out3f)
+void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameblend, const surfmesh_t *mesh, float *out3f)
 {
        if (mesh->num_vertexboneweights)
        {
                int i, k, blends;
-               aliasvertexboneweight_t *v;
+               surfmeshvertexboneweight_t *v;
                float *out, *matrix, m[12], bonepose[256][12];
                // vertex weighted skeletal
                // interpolate matrices and concatenate them to their parents
-               for (i = 0;i < model->alias.aliasnum_bones;i++)
+               for (i = 0;i < model->num_bones;i++)
                {
                        for (k = 0;k < 12;k++)
                                m[k] = 0;
                        for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
                        {
-                               matrix = model->alias.aliasdata_poses + (frameblend[blends].frame * model->alias.aliasnum_bones + i) * 12;
+                               matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
                                for (k = 0;k < 12;k++)
                                        m[k] += matrix[k] * frameblend[blends].lerp;
                        }
-                       if (model->alias.aliasdata_bones[i].parent >= 0)
-                               R_ConcatTransforms(bonepose[model->alias.aliasdata_bones[i].parent], m, bonepose[i]);
+                       if (model->data_bones[i].parent >= 0)
+                               R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
                        else
                                for (k = 0;k < 12;k++)
                                        bonepose[i][k] = m[k];
@@ -107,19 +107,19 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma
        const float *boneframe;
        float tempbonematrix[12], bonematrix[12];
        Matrix4x4_CreateIdentity(outmatrix);
-       if (model->alias.aliasnum_bones)
+       if (model->num_bones)
        {
-               if (tagindex < 0 || tagindex >= model->alias.aliasnum_bones)
+               if (tagindex < 0 || tagindex >= model->num_bones)
                        return 4;
-               if (poseframe >= model->alias.aliasnum_poses)
+               if (poseframe >= model->num_poses)
                        return 6;
-               boneframe = model->alias.aliasdata_poses + poseframe * model->alias.aliasnum_bones * 12;
+               boneframe = model->data_poses + poseframe * model->num_bones * 12;
                memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
-               while (model->alias.aliasdata_bones[tagindex].parent >= 0)
+               while (model->data_bones[tagindex].parent >= 0)
                {
                        memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
-                       R_ConcatTransforms(boneframe + model->alias.aliasdata_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
-                       tagindex = model->alias.aliasdata_bones[tagindex].parent;
+                       R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
+                       tagindex = model->data_bones[tagindex].parent;
                }
                outmatrix->m[0][0] = bonematrix[0];
                outmatrix->m[0][1] = bonematrix[1];
@@ -138,13 +138,13 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma
                outmatrix->m[3][2] = 0;
                outmatrix->m[3][3] = 1;
        }
-       else if (model->alias.aliasnum_tags)
+       else if (model->num_tags)
        {
-               if (tagindex < 0 || tagindex >= model->alias.aliasnum_tags)
+               if (tagindex < 0 || tagindex >= model->num_tags)
                        return 4;
-               if (poseframe >= model->alias.aliasnum_tagframes)
+               if (poseframe >= model->num_tagframes)
                        return 6;
-               *outmatrix = model->alias.aliasdata_tags[poseframe * model->alias.aliasnum_tags + tagindex].matrix;
+               *outmatrix = model->data_tags[poseframe * model->num_tags + tagindex].matrix;
        }
        return 0;
 }
@@ -156,32 +156,35 @@ int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const
                for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
                        if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
                                return i + 1;
-       if (model->alias.aliasnum_bones)
-               for (i = 0;i < model->alias.aliasnum_bones;i++)
-                       if (!strcasecmp(tagname, model->alias.aliasdata_bones[i].name))
+       if (model->num_bones)
+               for (i = 0;i < model->num_bones;i++)
+                       if (!strcasecmp(tagname, model->data_bones[i].name))
                                return i + 1;
-       if (model->alias.aliasnum_tags)
-               for (i = 0;i < model->alias.aliasnum_tags;i++)
-                       if (!strcasecmp(tagname, model->alias.aliasdata_tags[i].name))
+       if (model->num_tags)
+               for (i = 0;i < model->num_tags;i++)
+                       if (!strcasecmp(tagname, model->data_tags[i].name))
                                return i + 1;
        return 0;
 }
 
-static void Mod_Alias_Mesh_CompileFrameZero(aliasmesh_t *mesh)
+static void Mod_Alias_Mesh_CompileFrameZero(surfmesh_t *mesh)
 {
        frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
-       mesh->data_basevertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[3][4]));
-       mesh->data_basesvector3f = mesh->data_basevertex3f + mesh->num_vertices * 3;
-       mesh->data_basetvector3f = mesh->data_basevertex3f + mesh->num_vertices * 6;
-       mesh->data_basenormal3f = mesh->data_basevertex3f + mesh->num_vertices * 9;
-       Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_basevertex3f);
-       Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_basevertex3f, mesh->data_texcoord2f, mesh->data_element3i, mesh->data_basesvector3f, mesh->data_basetvector3f, mesh->data_basenormal3f);
+       mesh->data_vertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[3][4]));
+       mesh->data_svector3f = mesh->data_vertex3f + mesh->num_vertices * 3;
+       mesh->data_tvector3f = mesh->data_vertex3f + mesh->num_vertices * 6;
+       mesh->data_normal3f = mesh->data_vertex3f + mesh->num_vertices * 9;
+       Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_vertex3f);
+       Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f);
 }
 
 static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
 {
-       int i, framenum;
+       int i, framenum, linetrace;
+       float *vertex3f;
        float segmentmins[3], segmentmaxs[3];
+       msurface_t *surface;
+       surfmesh_t *mesh;
        colbrushf_t *thisbrush_start, *thisbrush_end;
        matrix4x4_t startmatrix, endmatrix;
        memset(trace, 0, sizeof(*trace));
@@ -194,37 +197,32 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co
        segmentmaxs[0] = max(boxstartmaxs[0], boxendmaxs[0]);
        segmentmaxs[1] = max(boxstartmaxs[1], boxendmaxs[1]);
        segmentmaxs[2] = max(boxstartmaxs[2], boxendmaxs[2]);
-       if (VectorCompare(boxstartmins, boxstartmaxs) && VectorCompare(boxendmins, boxendmaxs))
-       {
-               // line trace
-               for (i = 0;i < model->alias.aliasnum_meshes;i++)
-               {
-                       framenum = frame;
-                       if (framenum < 0 || framenum > model->alias.aliasdata_meshes[i].num_morphframes)
-                               framenum = 0;
-                       if (model->alias.aliasdata_meshes[i].data_morphvertex3f)
-                               Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, model->alias.aliasdata_meshes[i].num_triangles, model->alias.aliasdata_meshes[i].data_element3i, model->alias.aliasdata_meshes[i].data_morphvertex3f + framenum * model->alias.aliasdata_meshes[i].num_vertices * 3, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
-                       //else
-                               // FIXME!!!  this needs to handle skeletal!
-               }
-       }
-       else
+       linetrace = VectorCompare(boxstartmins, boxstartmaxs) && VectorCompare(boxendmins, boxendmaxs);
+       if (!linetrace)
        {
                // box trace, performed as brush trace
                Matrix4x4_CreateIdentity(&startmatrix);
                Matrix4x4_CreateIdentity(&endmatrix);
                thisbrush_start = Collision_BrushForBox(&startmatrix, boxstartmins, boxstartmaxs);
                thisbrush_end = Collision_BrushForBox(&endmatrix, boxendmins, boxendmaxs);
-               for (i = 0;i < model->alias.aliasnum_meshes;i++)
+       }
+       for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+       {
+               mesh = surface->groupmesh;
+               framenum = frame;
+               if (framenum < 0 || framenum > mesh->num_morphframes)
+                       framenum = 0;
+               if (mesh->data_morphvertex3f)
+                       vertex3f = mesh->data_morphvertex3f + framenum * mesh->num_vertices * 3;
+               else
                {
-                       framenum = frame;
-                       if (framenum < 0 || framenum > model->alias.aliasdata_meshes[i].num_morphframes)
-                               framenum = 0;
-                       if (model->alias.aliasdata_meshes[i].data_morphvertex3f)
-                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->alias.aliasdata_meshes[i].num_triangles, model->alias.aliasdata_meshes[i].data_element3i, model->alias.aliasdata_meshes[i].data_morphvertex3f + framenum * model->alias.aliasdata_meshes[i].num_vertices * 3, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
-                       //else
-                               // FIXME!!!  this needs to handle skeletal!
+                       vertex3f = varray_vertex3f;
+                       continue; // FIXME!!!  this needs to handle skeletal!
                }
+               if (linetrace)
+                       Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
+               else
+                       Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs);
        }
 }
 
@@ -232,14 +230,15 @@ static void Mod_CalcAliasModelBBoxes (void)
 {
        int vnum, meshnum;
        float dist, yawradius, radius;
-       aliasmesh_t *mesh;
+       surfmesh_t *mesh;
        float *v;
        VectorClear(loadmodel->normalmins);
        VectorClear(loadmodel->normalmaxs);
        yawradius = 0;
        radius = 0;
-       for (meshnum = 0, mesh = loadmodel->alias.aliasdata_meshes;meshnum < loadmodel->alias.aliasnum_meshes;meshnum++, mesh++)
+       for (meshnum = 0;meshnum < loadmodel->num_surfaces;meshnum++)
        {
+               mesh = loadmodel->meshlist[meshnum];
                for (vnum = 0, v = mesh->data_morphvertex3f;vnum < mesh->num_vertices * mesh->num_morphframes;vnum++, v += 3)
                {
                        if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
@@ -343,7 +342,7 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v
                {
                        pinframe = (daliasframe_t *)datapointer;
                        datapointer += sizeof(daliasframe_t);
-                       Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, loadmodel->alias.aliasdata_meshes->data_morphvertex3f + pose * loadmodel->alias.aliasdata_meshes->num_vertices * 3, vertremap);
+                       Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, loadmodel->meshlist[0]->data_morphvertex3f + pose * loadmodel->meshlist[0]->num_vertices * 3, vertremap);
                        datapointer += sizeof(trivertx_t) * inverts;
                        pose++;
                }
@@ -422,6 +421,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
 {
        int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
        float scales, scalet, scale[3], translate[3], interval;
+       msurface_t *surface;
+       qbyte *data;
        mdl_t *pinmodel;
        stvert_t *pinstverts;
        dtriangle_t *pintriangles;
@@ -455,8 +456,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        loadmodel->DrawLight = R_Model_Alias_DrawLight;
        loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
 
-       loadmodel->alias.aliasnum_meshes = 1;
-       loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, sizeof(aliasmesh_t));
+       loadmodel->num_surfaces = 1;
+       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->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       for (i = 0;i < loadmodel->num_surfaces;i++)
+               loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,65536);
@@ -466,8 +472,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        BOUNDI(skinheight,0,65536);
        numverts = LittleLong(pinmodel->numverts);
        BOUNDI(numverts,0,65536);
-       loadmodel->alias.aliasdata_meshes->num_triangles = LittleLong(pinmodel->numtris);
-       BOUNDI(loadmodel->alias.aliasdata_meshes->num_triangles,0,65536);
+       loadmodel->meshlist[0]->num_triangles = LittleLong(pinmodel->numtris);
+       BOUNDI(loadmodel->meshlist[0]->num_triangles,0,65536);
        loadmodel->numframes = LittleLong(pinmodel->numframes);
        BOUNDI(loadmodel->numframes,0,65536);
        loadmodel->synctype = LittleLong (pinmodel->synctype);
@@ -507,10 +513,10 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        datapointer += sizeof(stvert_t) * numverts;
 
        pintriangles = (dtriangle_t *)datapointer;
-       datapointer += sizeof(dtriangle_t) * loadmodel->alias.aliasdata_meshes->num_triangles;
+       datapointer += sizeof(dtriangle_t) * loadmodel->meshlist[0]->num_triangles;
 
        startframes = datapointer;
-       loadmodel->alias.aliasdata_meshes->num_morphframes = 0;
+       loadmodel->meshlist[0]->num_morphframes = 0;
        for (i = 0;i < loadmodel->numframes;i++)
        {
                pinframetype = (daliasframetype_t *)datapointer;
@@ -529,7 +535,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                {
                        datapointer += sizeof(daliasframe_t);
                        datapointer += sizeof(trivertx_t) * numverts;
-                       loadmodel->alias.aliasdata_meshes->num_morphframes++;
+                       loadmodel->meshlist[0]->num_morphframes++;
                }
        }
 
@@ -551,60 +557,60 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        }
 
 // load triangle data
-       loadmodel->alias.aliasdata_meshes->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->alias.aliasdata_meshes->num_triangles);
+       loadmodel->meshlist[0]->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->meshlist[0]->num_triangles);
 
        // read the triangle elements
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++)
+       for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)
                for (j = 0;j < 3;j++)
-                       loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
+                       loadmodel->meshlist[0]->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
        // validate (note numverts is used because this is the original data)
-       Mod_ValidateElements(loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles, numverts, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles, numverts, __FILE__, __LINE__);
        // now butcher the elements according to vertonseam and tri->facesfront
        // and then compact the vertex set to remove duplicates
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++)
+       for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)
                if (!LittleLong(pintriangles[i].facesfront)) // backface
                        for (j = 0;j < 3;j++)
-                               if (vertonseam[loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j]])
-                                       loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] += numverts;
+                               if (vertonseam[loadmodel->meshlist[0]->data_element3i[i*3+j]])
+                                       loadmodel->meshlist[0]->data_element3i[i*3+j] += numverts;
        // count the usage
        // (this uses vertremap to count usage to save some memory)
        for (i = 0;i < numverts*2;i++)
                vertremap[i] = 0;
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles*3;i++)
-               vertremap[loadmodel->alias.aliasdata_meshes->data_element3i[i]]++;
+       for (i = 0;i < loadmodel->meshlist[0]->num_triangles*3;i++)
+               vertremap[loadmodel->meshlist[0]->data_element3i[i]]++;
        // build remapping table and compact array
-       loadmodel->alias.aliasdata_meshes->num_vertices = 0;
+       loadmodel->meshlist[0]->num_vertices = 0;
        for (i = 0;i < numverts*2;i++)
        {
                if (vertremap[i])
                {
-                       vertremap[i] = loadmodel->alias.aliasdata_meshes->num_vertices;
-                       vertst[loadmodel->alias.aliasdata_meshes->num_vertices*2+0] = vertst[i*2+0];
-                       vertst[loadmodel->alias.aliasdata_meshes->num_vertices*2+1] = vertst[i*2+1];
-                       loadmodel->alias.aliasdata_meshes->num_vertices++;
+                       vertremap[i] = loadmodel->meshlist[0]->num_vertices;
+                       vertst[loadmodel->meshlist[0]->num_vertices*2+0] = vertst[i*2+0];
+                       vertst[loadmodel->meshlist[0]->num_vertices*2+1] = vertst[i*2+1];
+                       loadmodel->meshlist[0]->num_vertices++;
                }
                else
                        vertremap[i] = -1; // not used at all
        }
        // remap the elements to the new vertex set
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles * 3;i++)
-               loadmodel->alias.aliasdata_meshes->data_element3i[i] = vertremap[loadmodel->alias.aliasdata_meshes->data_element3i[i]];
+       for (i = 0;i < loadmodel->meshlist[0]->num_triangles * 3;i++)
+               loadmodel->meshlist[0]->data_element3i[i] = vertremap[loadmodel->meshlist[0]->data_element3i[i]];
        // store the texture coordinates
-       loadmodel->alias.aliasdata_meshes->data_texcoord2f = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->alias.aliasdata_meshes->num_vertices);
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_vertices;i++)
+       loadmodel->meshlist[0]->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->meshlist[0]->num_vertices);
+       for (i = 0;i < loadmodel->meshlist[0]->num_vertices;i++)
        {
-               loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+0] = vertst[i*2+0];
-               loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+1] = vertst[i*2+1];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
        }
 
 // load the frames
        loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
-       loadmodel->alias.aliasdata_meshes->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * loadmodel->alias.aliasdata_meshes->num_morphframes * loadmodel->alias.aliasdata_meshes->num_vertices);
-       loadmodel->alias.aliasdata_meshes->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3]));
+       loadmodel->meshlist[0]->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * loadmodel->meshlist[0]->num_morphframes * loadmodel->meshlist[0]->num_vertices);
+       loadmodel->meshlist[0]->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3]));
        Mod_MDL_LoadFrames (startframes, numverts, scale, translate, vertremap);
-       Mod_BuildTriangleNeighbors(loadmodel->alias.aliasdata_meshes->data_neighbor3i, loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles);
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
        Mod_CalcAliasModelBBoxes();
-       Mod_Alias_Mesh_CompileFrameZero(loadmodel->alias.aliasdata_meshes);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
 
        Mem_Free(vertst);
        Mem_Free(vertremap);
@@ -612,9 +618,9 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        // load the skins
        if ((skinfiles = Mod_LoadSkinFiles()))
        {
-               loadmodel->alias.aliasdata_meshes->num_skins = totalskins = loadmodel->numskins;
-               loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->alias.aliasdata_meshes->data_skins, skinfiles, "default", "");
+               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_FreeSkinFiles(skinfiles);
                loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
                for (i = 0;i < loadmodel->numskins;i++)
@@ -627,8 +633,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
        }
        else
        {
-               loadmodel->alias.aliasdata_meshes->num_skins = totalskins;
-               loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t));
+               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;
@@ -674,7 +680,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->alias.aliasdata_meshes->data_skins + totalskins, &tempskinframe);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe);
                                datapointer += skinwidth * skinheight;
                                totalskins++;
                        }
@@ -689,13 +695,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                        memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
                        Mem_Free(tempskinscenes);
 
-                       tempaliasskins = loadmodel->alias.aliasdata_meshes->data_skins;
-                       loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(texture_t));
-                       memcpy(loadmodel->alias.aliasdata_meshes->data_skins, tempaliasskins, totalskins * sizeof(texture_t));
+                       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));
                        Mem_Free(tempaliasskins);
 
                        // store the info about the new skin
-                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + totalskins, &tempskinframe);
+                       Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe);
                        strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name);
                        loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
                        loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
@@ -703,11 +709,20 @@ void Mod_IDP0_Load(model_t *mod, void *buffer)
                        loadmodel->skinscenes[loadmodel->numskins].loop = true;
 
                        //increase skin counts
-                       loadmodel->alias.aliasdata_meshes->num_skins++;
+                       loadmodel->meshlist[0]->num_skins++;
                        loadmodel->numskins++;
                        totalskins++;
                }
        }
+
+       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->num_firsttriangle = 0;
+       surface->num_triangles = surface->groupmesh->num_triangles;
+       surface->num_firstvertex = 0;
+       surface->num_vertices = surface->groupmesh->num_vertices;
 }
 
 static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, float *out3f, int numverts, int *vertremap)
@@ -727,6 +742,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 {
        int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, numverts;
        float *stverts, s, t, scale[3], translate[3];
+       qbyte *data;
+       msurface_t *surface;
        md2_t *pinmodel;
        qbyte *base, *datapointer;
        md2frame_t *pinframe;
@@ -779,15 +796,20 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
        if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
                Host_Error ("%s is not a valid model", loadmodel->name);
 
-       loadmodel->alias.aliasnum_meshes = 1;
-       loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, sizeof(aliasmesh_t));
+       loadmodel->num_surfaces = 1;
+       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->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       for (i = 0;i < loadmodel->num_surfaces;i++)
+               loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
 
        loadmodel->numskins = LittleLong(pinmodel->num_skins);
        numxyz = LittleLong(pinmodel->num_xyz);
        numst = LittleLong(pinmodel->num_st);
-       loadmodel->alias.aliasdata_meshes->num_triangles = LittleLong(pinmodel->num_tris);
+       loadmodel->meshlist[0]->num_triangles = LittleLong(pinmodel->num_tris);
        loadmodel->numframes = LittleLong(pinmodel->num_frames);
-       loadmodel->alias.aliasdata_meshes->num_morphframes = loadmodel->numframes;
+       loadmodel->meshlist[0]->num_morphframes = loadmodel->numframes;
        loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
 
        loadmodel->flags = 0; // there are no MD2 flags
@@ -797,24 +819,24 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
        inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
        if ((skinfiles = Mod_LoadSkinFiles()))
        {
-               loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins;
-               loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinsFromSkinFiles(loadmodel->alias.aliasdata_meshes->data_skins, skinfiles, "default", "");
+               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", "");
                Mod_FreeSkinFiles(skinfiles);
        }
        else if (loadmodel->numskins)
        {
                // skins found (most likely not a player model)
-               loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins;
-               loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t));
+               loadmodel->meshlist[0]->num_skins = loadmodel->numskins;
+               loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * 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->alias.aliasdata_meshes->data_skins + i, &tempskinframe);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, &tempskinframe);
                        else
                        {
                                Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
-                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + i, NULL);
+                               Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, NULL);
                        }
                }
        }
@@ -822,9 +844,9 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
        {
                // no skins (most likely a player model)
                loadmodel->numskins = 1;
-               loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins;
-               loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t));
-               Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins, NULL);
+               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->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
@@ -860,11 +882,11 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
        }
 
        md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash));
-       md2verthashdata = Mem_Alloc(tempmempool, loadmodel->alias.aliasdata_meshes->num_triangles * 3 * sizeof(*hash));
+       md2verthashdata = Mem_Alloc(tempmempool, loadmodel->meshlist[0]->num_triangles * 3 * sizeof(*hash));
        // swap the triangle list
        num = 0;
-       loadmodel->alias.aliasdata_meshes->data_element3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3]));
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++)
+       loadmodel->meshlist[0]->data_element3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3]));
+       for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)
        {
                for (j = 0;j < 3;j++)
                {
@@ -895,22 +917,22 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
                                hash->next = md2verthash[hashindex];
                                md2verthash[hashindex] = hash;
                        }
-                       loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] = (hash - md2verthashdata);
+                       loadmodel->meshlist[0]->data_element3i[i*3+j] = (hash - md2verthashdata);
                }
        }
 
        Mem_Free(stverts);
 
        numverts = num;
-       loadmodel->alias.aliasdata_meshes->num_vertices = numverts;
+       loadmodel->meshlist[0]->num_vertices = numverts;
        vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int));
-       loadmodel->alias.aliasdata_meshes->data_texcoord2f = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2]));
+       loadmodel->meshlist[0]->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2]));
        for (i = 0;i < num;i++)
        {
                hash = md2verthashdata + i;
                vertremap[i] = hash->xyz;
-               loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+0] = hash->st[0];
-               loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+1] = hash->st[1];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+0] = hash->st[0];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+1] = hash->st[1];
        }
 
        Mem_Free(md2verthash);
@@ -918,8 +940,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 
        // load the frames
        datapointer = (base + LittleLong(pinmodel->ofs_frames));
-       loadmodel->alias.aliasdata_meshes->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->alias.aliasdata_meshes->num_morphframes * sizeof(float[3]));
-       for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_morphframes;i++)
+       loadmodel->meshlist[0]->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->meshlist[0]->num_morphframes * sizeof(float[3]));
+       for (i = 0;i < loadmodel->meshlist[0]->num_morphframes;i++)
        {
                pinframe = (md2frame_t *)datapointer;
                datapointer += sizeof(md2frame_t);
@@ -928,7 +950,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
                        scale[j] = LittleFloat(pinframe->scale[j]);
                        translate[j] = LittleFloat(pinframe->translate[j]);
                }
-               Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, loadmodel->alias.aliasdata_meshes->data_morphvertex3f + i * numverts * 3, numverts, vertremap);
+               Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, loadmodel->meshlist[0]->data_morphvertex3f + i * numverts * 3, numverts, vertremap);
                datapointer += numxyz * sizeof(trivertx_t);
 
                strcpy(loadmodel->animscenes[i].name, pinframe->name);
@@ -940,20 +962,31 @@ void Mod_IDP2_Load(model_t *mod, void *buffer)
 
        Mem_Free(vertremap);
 
-       loadmodel->alias.aliasdata_meshes->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3]));
-       Mod_BuildTriangleNeighbors(loadmodel->alias.aliasdata_meshes->data_neighbor3i, loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles);
+       loadmodel->meshlist[0]->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3]));
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
        Mod_CalcAliasModelBBoxes();
-       Mod_Alias_Mesh_CompileFrameZero(loadmodel->alias.aliasdata_meshes);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
+
+       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->num_firsttriangle = 0;
+       surface->num_triangles = surface->groupmesh->num_triangles;
+       surface->num_firstvertex = 0;
+       surface->num_vertices = surface->groupmesh->num_vertices;
 }
 
 void Mod_IDP3_Load(model_t *mod, void *buffer)
 {
        int i, j, k, version;
+       qbyte *data;
+       msurface_t *surface;
+       surfmesh_t *mesh;
        md3modelheader_t *pinmodel;
        md3frameinfo_t *pinframe;
        md3mesh_t *pinmesh;
        md3tag_t *pintag;
-       aliasmesh_t *mesh;
        skinfile_t *skinfiles;
 
        pinmodel = buffer;
@@ -980,7 +1013,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
 
        // set up some global info about the model
        loadmodel->numframes = LittleLong(pinmodel->num_frames);
-       loadmodel->alias.aliasnum_meshes = LittleLong(pinmodel->num_meshes);
+       loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
 
        // make skinscenes for the skins (no groups)
        loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
@@ -1004,29 +1037,34 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
        }
 
        // load tags
-       loadmodel->alias.aliasnum_tagframes = loadmodel->numframes;
-       loadmodel->alias.aliasnum_tags = LittleLong(pinmodel->num_tags);
-       loadmodel->alias.aliasdata_tags = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_tagframes * loadmodel->alias.aliasnum_tags * sizeof(aliastag_t));
-       for (i = 0, pintag = (md3tag_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->alias.aliasnum_tagframes * loadmodel->alias.aliasnum_tags;i++, pintag++)
+       loadmodel->num_tagframes = loadmodel->numframes;
+       loadmodel->num_tags = LittleLong(pinmodel->num_tags);
+       loadmodel->data_tags = Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
+       for (i = 0, pintag = (md3tag_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
        {
-               strcpy(loadmodel->alias.aliasdata_tags[i].name, pintag->name);
-               Matrix4x4_CreateIdentity(&loadmodel->alias.aliasdata_tags[i].matrix);
+               strcpy(loadmodel->data_tags[i].name, pintag->name);
+               Matrix4x4_CreateIdentity(&loadmodel->data_tags[i].matrix);
                for (j = 0;j < 3;j++)
                {
                        for (k = 0;k < 3;k++)
-                               loadmodel->alias.aliasdata_tags[i].matrix.m[j][k] = LittleFloat(pintag->rotationmatrix[k * 3 + j]);
-                       loadmodel->alias.aliasdata_tags[i].matrix.m[j][3] = LittleFloat(pintag->origin[j]);
+                               loadmodel->data_tags[i].matrix.m[j][k] = LittleFloat(pintag->rotationmatrix[k * 3 + j]);
+                       loadmodel->data_tags[i].matrix.m[j][3] = LittleFloat(pintag->origin[j]);
                }
-               //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->alias.aliasnum_tags, i % loadmodel->alias.aliasnum_tags, loadmodel->alias.aliasdata_tags[i].name);
+               //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name);
        }
 
        // load meshes
-       loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_meshes * sizeof(aliasmesh_t));
-       for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->alias.aliasnum_meshes;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end)))
+       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->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       for (i = 0;i < loadmodel->num_surfaces;i++)
+               mesh = 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->alias.aliasdata_meshes + i;
+               mesh = loadmodel->meshlist[i];
                mesh->num_skins = loadmodel->numskins;
                mesh->num_morphframes = LittleLong(pinmesh->num_frames);
                mesh->num_vertices = LittleLong(pinmesh->num_vertices);
@@ -1034,14 +1072,14 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
                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_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
+               mesh->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
                mesh->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_morphframes * sizeof(float[3]));
                for (j = 0;j < mesh->num_triangles * 3;j++)
                        mesh->data_element3i[j] = LittleLong(((int *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
                for (j = 0;j < mesh->num_vertices;j++)
                {
-                       mesh->data_texcoord2f[j * 2 + 0] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
-                       mesh->data_texcoord2f[j * 2 + 1] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
+                       mesh->data_texcoordtexture2f[j * 2 + 0] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
+                       mesh->data_texcoordtexture2f[j * 2 + 1] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
                }
                for (j = 0;j < mesh->num_vertices * mesh->num_morphframes;j++)
                {
@@ -1059,6 +1097,15 @@ void Mod_IDP3_Load(model_t *mod, void *buffer)
                else
                        for (j = 0;j < mesh->num_skins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, 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->num_firsttriangle = 0;
+               surface->num_triangles = mesh->num_triangles;
+               surface->num_firstvertex = 0;
+               surface->num_vertices = mesh->num_vertices;
        }
        Mod_CalcAliasModelBBoxes();
        Mod_FreeSkinFiles(skinfiles);
@@ -1075,7 +1122,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
        zymbone_t *bone;
        char *shadername;
        skinfile_t *skinfiles;
-       aliasmesh_t *mesh;
+       qbyte *data;
+       msurface_t *surface;
+       surfmesh_t *mesh;
 
        pinmodel = (void *)buffer;
        pbase = buffer;
@@ -1129,7 +1178,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
        pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
 
        loadmodel->numframes = pheader->numscenes;
-       loadmodel->alias.aliasnum_meshes = pheader->numshaders;
+       loadmodel->num_surfaces = pheader->numshaders;
 
        skinfiles = Mod_LoadSkinFiles();
        if (loadmodel->numskins < 1)
@@ -1188,22 +1237,22 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
        }
 
        //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
-       loadmodel->alias.aliasnum_poses = pheader->lump_poses.length / sizeof(float[3][4]);
-       loadmodel->alias.aliasdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
+       loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
+       loadmodel->data_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
        poses = (void *) (pheader->lump_poses.start + pbase);
        for (i = 0;i < pheader->lump_poses.length / 4;i++)
-               loadmodel->alias.aliasdata_poses[i] = BigFloat(poses[i]);
+               loadmodel->data_poses[i] = BigFloat(poses[i]);
 
        //zymlump_t lump_bones; // zymbone_t bone[numbones];
-       loadmodel->alias.aliasnum_bones = pheader->numbones;
-       loadmodel->alias.aliasdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
+       loadmodel->num_bones = pheader->numbones;
+       loadmodel->data_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
        bone = (void *) (pheader->lump_bones.start + pbase);
        for (i = 0;i < pheader->numbones;i++)
        {
-               memcpy(loadmodel->alias.aliasdata_bones[i].name, bone[i].name, sizeof(bone[i].name));
-               loadmodel->alias.aliasdata_bones[i].flags = BigLong(bone[i].flags);
-               loadmodel->alias.aliasdata_bones[i].parent = BigLong(bone[i].parent);
-               if (loadmodel->alias.aliasdata_bones[i].parent >= i)
+               memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
+               loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
+               loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
+               if (loadmodel->data_bones[i].parent >= i)
                        Host_Error("%s bone[%i].parent >= %i\n", loadmodel->name, i, i);
        }
 
@@ -1242,7 +1291,12 @@ 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->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_meshes * sizeof(aliasmesh_t));
+       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->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+       for (i = 0;i < loadmodel->num_surfaces;i++)
+               mesh = 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)
@@ -1252,14 +1306,14 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)\n", loadmodel->name, pheader->lump_render.length, count);
        renderlist = (void *) (pheader->lump_render.start + pbase);
        renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length);
-       for (i = 0;i < loadmodel->alias.aliasnum_meshes;i++)
+       for (i = 0;i < loadmodel->num_surfaces;i++)
        {
                if (renderlist >= renderlistend)
                        Host_Error("%s corrupt renderlist (wrong size)\n", loadmodel->name);
                count = BigLong(*renderlist);renderlist++;
                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->alias.aliasdata_meshes + i;
+               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));
@@ -1283,20 +1337,20 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                for (j = 0;j < mesh->num_triangles * 3;j++)
                        mesh->data_element3i[j] = remapvertices[mesh->data_element3i[j]];
                Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-               mesh->data_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
+               mesh->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
                for (j = 0;j < pheader->numverts;j++)
                {
                        if (remapvertices[j] >= 0)
                        {
-                               mesh->data_texcoord2f[remapvertices[j]*2+0] = outtexcoord2f[j*2+0];
-                               mesh->data_texcoord2f[remapvertices[j]*2+1] = outtexcoord2f[j*2+1];
+                               mesh->data_texcoordtexture2f[remapvertices[j]*2+0] = outtexcoord2f[j*2+0];
+                               mesh->data_texcoordtexture2f[remapvertices[j]*2+1] = outtexcoord2f[j*2+1];
                        }
                }
                mesh->num_vertexboneweights = 0;
                for (j = 0;j < mesh->num_vertices;j++)
                        if (remapvertices[j] >= 0)
                                mesh->num_vertexboneweights += vertbonecounts[remapvertices[j]];
-               mesh->data_vertexboneweights = Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(aliasvertexboneweight_t));
+               mesh->data_vertexboneweights = Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t));
                mesh->num_vertexboneweights = 0;
                // note this vertexboneweight ordering requires that the remapvertices array is sequential numbers (separated by -1 values for omitted vertices)
                l = 0;
@@ -1333,6 +1387,15 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer)
                else
                        for (j = 0;j < mesh->num_skins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, 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->num_firsttriangle = 0;
+               surface->num_triangles = mesh->num_triangles;
+               surface->num_firstvertex = 0;
+               surface->num_vertices = mesh->num_vertices;
        }
 
        Mem_Free(vertbonecounts);
index 15c6d8a..c3367f8 100644 (file)
@@ -213,47 +213,6 @@ typedef struct md3modelheader_s
 }
 md3modelheader_t;
 
-typedef struct aliasvertexboneweight_s
-{
-       unsigned int vertexindex;
-       unsigned int boneindex;
-       float origin[3];
-       float weight;
-}
-aliasvertexboneweight_t;
-
-typedef struct aliasmesh_s
-{
-       // skins to choose from (indexed by entity skin)
-       int num_skins;
-       texture_t *data_skins;
-
-       // triangles comprising the mesh
-       int num_triangles;
-       int *data_element3i;
-       int *data_neighbor3i;
-
-       // skin texcoords do not change
-       int num_vertices;
-       float *data_texcoord2f;
-
-       // morph blending, these are zero if model is skeletal
-       int num_morphframes;
-       float *data_morphvertex3f;
-
-       // base frame (frame zero typically)
-       // since most models do not animate, caching the base frame helps
-       float *data_basevertex3f;
-       float *data_basesvector3f;
-       float *data_basetvector3f;
-       float *data_basenormal3f;
-
-       // skeletal blending, these are zero if model is morph
-       int num_vertexboneweights;
-       aliasvertexboneweight_t *data_vertexboneweights;
-}
-aliasmesh_t;
-
 typedef struct aliastag_s
 {
        char name[MD3NAME];
@@ -270,7 +229,7 @@ typedef struct aliasbone_s
 aliasbone_t;
 
 struct frameblend_s;
-void Mod_Alias_GetMesh_Vertex3f(const struct model_s *model, const struct frameblend_s *frameblend, const struct aliasmesh_s *mesh, float *out3f);
+void Mod_Alias_GetMesh_Vertex3f(const struct model_s *model, const struct frameblend_s *frameblend, const struct surfmesh_s *mesh, float *out3f);
 int Mod_Alias_GetTagMatrix(const struct model_s *model, int poseframe, int tagindex, matrix4x4_t *outmatrix);
 int Mod_Alias_GetTagIndexForName(const struct model_s *model, unsigned int skin, const char *tagname);
 
index fd378a2..0a7b87c 100644 (file)
@@ -260,7 +260,7 @@ static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *in
        msurface_t *surface;
        for (surfacenum = 0, mark = leaf->firstleafsurface;surfacenum < leaf->numleafsurfaces;surfacenum++, mark++)
        {
-               surface = info->model->brush.data_surfaces + *mark;
+               surface = info->model->data_surfaces + *mark;
                if (surface->texture->supercontents & SUPERCONTENTS_SOLID)
                {
                        for (k = 0;k < surface->num_triangles;k++)
@@ -827,7 +827,7 @@ loc0:
                        int i, ds, dt;
                        msurface_t *surface;
 
-                       surface = r_refdef.worldmodel->brush.data_surfaces + node->firstsurface;
+                       surface = r_refdef.worldmodel->data_surfaces + node->firstsurface;
                        for (i = 0;i < node->numsurfaces;i++, surface++)
                        {
                                if (!(surface->texture->basematerialflags & MATERIALFLAG_WALL) || !surface->lightmapinfo->samples)
@@ -1025,32 +1025,32 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
        qbyte *data, *mtdata;
        char name[256];
 
-       loadmodel->brush.data_textures = NULL;
+       loadmodel->data_textures = NULL;
 
        // add two slots for notexture walls and notexture liquids
        if (l->filelen)
        {
                m = (dmiptexlump_t *)(mod_base + l->fileofs);
                m->nummiptex = LittleLong (m->nummiptex);
-               loadmodel->brush.num_textures = m->nummiptex + 2;
+               loadmodel->num_textures = m->nummiptex + 2;
        }
        else
        {
                m = NULL;
-               loadmodel->brush.num_textures = 2;
+               loadmodel->num_textures = 2;
        }
 
-       loadmodel->brush.data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_textures * sizeof(texture_t));
+       loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_textures * sizeof(texture_t));
 
        // fill out all slots with notexture
-       for (i = 0, tx = loadmodel->brush.data_textures;i < loadmodel->brush.num_textures;i++, tx++)
+       for (i = 0, tx = loadmodel->data_textures;i < loadmodel->num_textures;i++, tx++)
        {
                strcpy(tx->name, "NO TEXTURE FOUND");
                tx->width = 16;
                tx->height = 16;
                tx->skin.base = r_texture_notexture;
                tx->basematerialflags = 0;
-               if (i == loadmodel->brush.num_textures - 1)
+               if (i == loadmodel->num_textures - 1)
                {
                        tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
                        tx->supercontents = SUPERCONTENTS_WATER;
@@ -1104,7 +1104,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                        if (name[j] >= 'A' && name[j] <= 'Z')
                                name[j] += 'a' - 'A';
 
-               tx = loadmodel->brush.data_textures + i;
+               tx = loadmodel->data_textures + i;
                strcpy(tx->name, name);
                tx->width = mtwidth;
                tx->height = mtheight;
@@ -1217,7 +1217,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
        // sequence the animations
        for (i = 0;i < m->nummiptex;i++)
        {
-               tx = loadmodel->brush.data_textures + i;
+               tx = loadmodel->data_textures + i;
                if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0)
                        continue;
                if (tx->anim_total[0] || tx->anim_total[1])
@@ -1229,7 +1229,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
 
                for (j = i;j < m->nummiptex;j++)
                {
-                       tx2 = loadmodel->brush.data_textures + j;
+                       tx2 = loadmodel->data_textures + j;
                        if (!tx2 || tx2->name[0] != '+' || strcmp(tx2->name+2, tx->name+2))
                                continue;
 
@@ -1627,25 +1627,25 @@ static void Mod_Q1BSP_LoadTexinfo(lump_t *l)
                out->flags = LittleLong(in->flags);
 
                out->texture = NULL;
-               if (loadmodel->brush.data_textures)
+               if (loadmodel->data_textures)
                {
-                       if ((unsigned int) miptex >= (unsigned int) loadmodel->brush.num_textures)
-                               Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->brush.num_textures);
+                       if ((unsigned int) miptex >= (unsigned int) loadmodel->num_textures)
+                               Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->num_textures);
                        else
-                               out->texture = loadmodel->brush.data_textures + miptex;
+                               out->texture = loadmodel->data_textures + miptex;
                }
                if (out->flags & TEX_SPECIAL)
                {
                        // if texture chosen is NULL or the shader needs a lightmap,
                        // force to notexture water shader
                        if (out->texture == NULL || out->texture->basematerialflags & MATERIALFLAG_WALL)
-                               out->texture = loadmodel->brush.data_textures + (loadmodel->brush.num_textures - 1);
+                               out->texture = loadmodel->data_textures + (loadmodel->num_textures - 1);
                }
                else
                {
                        // if texture chosen is NULL, force to notexture
                        if (out->texture == NULL)
-                               out->texture = loadmodel->brush.data_textures + (loadmodel->brush.num_textures - 2);
+                               out->texture = loadmodel->data_textures + (loadmodel->num_textures - 2);
                }
        }
 }
@@ -1813,10 +1813,10 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
        if (l->filelen % sizeof(*in))
                Host_Error("Mod_Q1BSP_LoadFaces: funny lump size in %s",loadmodel->name);
        count = l->filelen / sizeof(*in);
-       loadmodel->brush.data_surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t));
-       loadmodel->brush.data_surfaces_lightmapinfo = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_lightmapinfo_t));
+       loadmodel->data_surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t));
+       loadmodel->data_surfaces_lightmapinfo = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_lightmapinfo_t));
 
-       loadmodel->brush.num_surfaces = count;
+       loadmodel->num_surfaces = count;
 
        totalverts = 0;
        totaltris = 0;
@@ -1835,9 +1835,9 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
 
        totalverts = 0;
        totaltris = 0;
-       for (surfacenum = 0, in = (void *)(mod_base + l->fileofs), surface = loadmodel->brush.data_surfaces;surfacenum < count;surfacenum++, in++, surface++)
+       for (surfacenum = 0, in = (void *)(mod_base + l->fileofs), surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, in++, surface++)
        {
-               surface->lightmapinfo = loadmodel->brush.data_surfaces_lightmapinfo + surfacenum;
+               surface->lightmapinfo = loadmodel->data_surfaces_lightmapinfo + surfacenum;
 
                // FIXME: validate edges, texinfo, etc?
                firstedge = LittleLong(in->firstedge);
@@ -2237,7 +2237,7 @@ static void Mod_Q1BSP_LoadLeaffaces(lump_t *l)
        for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++)
        {
                j = (unsigned) LittleShort(in[i]);
-               if (j >= loadmodel->brush.num_surfaces)
+               if (j >= loadmodel->num_surfaces)
                        Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number");
                loadmodel->brush.data_leafsurfaces[i] = j;
        }
@@ -2776,7 +2776,7 @@ static void Mod_Q1BSP_BuildLightmapUpdateChains(mempool_t *mempool, model_t *mod
        memset(stylecounts, 0, sizeof(stylecounts));
        for (i = 0;i < model->nummodelsurfaces;i++)
        {
-               surface = model->brush.data_surfaces + model->firstmodelsurface + i;
+               surface = model->data_surfaces + model->firstmodelsurface + i;
                for (j = 0;j < MAXLIGHTMAPS;j++)
                        stylecounts[surface->lightmapinfo->styles[j]]++;
        }
@@ -2808,7 +2808,7 @@ static void Mod_Q1BSP_BuildLightmapUpdateChains(mempool_t *mempool, model_t *mod
        }
        for (i = 0;i < model->nummodelsurfaces;i++)
        {
-               surface = model->brush.data_surfaces + model->firstmodelsurface + i;
+               surface = model->data_surfaces + model->firstmodelsurface + i;
                for (j = 0;j < MAXLIGHTMAPS;j++)
                        if (surface->lightmapinfo->styles[j] != 255)
                                *model->brushq1.light_styleupdatechains[remapstyles[surface->lightmapinfo->styles[j]]]++ = surface;
@@ -3006,13 +3006,13 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
 
        // make a single combined shadow mesh to allow optimized shadow volume creation
        numshadowmeshtriangles = 0;
-       for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++)
+       for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
        {
                surface->num_firstshadowmeshtriangle = numshadowmeshtriangles;
                numshadowmeshtriangles += surface->num_triangles;
        }
        loadmodel->brush.shadowmesh = Mod_ShadowMesh_Begin(loadmodel->mempool, numshadowmeshtriangles * 3, numshadowmeshtriangles, NULL, NULL, NULL, false, false, true);
-       for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++)
+       for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
                Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surface->groupmesh->data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
        loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true);
        Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles);
@@ -3113,7 +3113,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                        mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
                        modelyawradius = 0;
                        modelradius = 0;
-                       for (j = 0, surface = &mod->brush.data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
+                       for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
                        {
                                // we only need to have a drawsky function if it is used(usually only on world model)
                                if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
@@ -3158,7 +3158,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        //Mod_Q1BSP_ProcessLightList();
 
        if (developer.integer)
-               Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brush.num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brushq1.submodels[i].visleafs, loadmodel->brush.num_portals);
+               Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brushq1.submodels[i].visleafs, loadmodel->brush.num_portals);
 }
 
 static void Mod_Q2BSP_LoadEntities(lump_t *l)
@@ -3651,8 +3651,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
        count = l->filelen / sizeof(*in);
        out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
 
-       loadmodel->brush.data_textures = out;
-       loadmodel->brush.num_textures = count;
+       loadmodel->data_textures = out;
+       loadmodel->num_textures = count;
 
        for (i = 0;i < count;i++, in++, out++)
        {
@@ -3842,7 +3842,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                }
                                                // add shader to list (shadername and flags)
                                                // actually here we just poke into the texture settings
-                                               for (j = 0, out = loadmodel->brush.data_textures;j < loadmodel->brush.num_textures;j++, out++)
+                                               for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++)
                                                {
                                                        if (!strcasecmp(out->name, shadername))
                                                        {
@@ -3890,7 +3890,7 @@ parseerror:
        }
 
        c = 0;
-       for (j = 0, out = loadmodel->brush.data_textures;j < loadmodel->brush.num_textures;j++, out++)
+       for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++)
        {
                if (out->surfaceparms == -1)
                {
@@ -3970,9 +3970,9 @@ static void Mod_Q3BSP_LoadBrushSides(lump_t *l)
                        Host_Error("Mod_Q3BSP_LoadBrushSides: invalid planeindex %i (%i planes)\n", n, loadmodel->brush.num_planes);
                out->plane = loadmodel->brush.data_planes + n;
                n = LittleLong(in->textureindex);
-               if (n < 0 || n >= loadmodel->brush.num_textures)
-                       Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)\n", n, loadmodel->brush.num_textures);
-               out->texture = loadmodel->brush.data_textures + n;
+               if (n < 0 || n >= loadmodel->num_textures)
+                       Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)\n", n, loadmodel->num_textures);
+               out->texture = loadmodel->data_textures + n;
        }
 }
 
@@ -4004,9 +4004,9 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l)
                out->firstbrushside = loadmodel->brush.data_brushsides + n;
                out->numbrushsides = c;
                n = LittleLong(in->textureindex);
-               if (n < 0 || n >= loadmodel->brush.num_textures)
-                       Host_Error("Mod_Q3BSP_LoadBrushes: invalid textureindex %i (%i textures)\n", n, loadmodel->brush.num_textures);
-               out->texture = loadmodel->brush.data_textures + n;
+               if (n < 0 || n >= loadmodel->num_textures)
+                       Host_Error("Mod_Q3BSP_LoadBrushes: invalid textureindex %i (%i textures)\n", n, loadmodel->num_textures);
+               out->texture = loadmodel->data_textures + n;
 
                // make a list of mplane_t structs to construct a colbrush from
                if (maxplanes < out->numbrushsides)
@@ -4155,8 +4155,8 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
        count = l->filelen / sizeof(*in);
        out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
 
-       loadmodel->brush.data_surfaces = out;
-       loadmodel->brush.num_surfaces = count;
+       loadmodel->data_surfaces = out;
+       loadmodel->num_surfaces = count;
 
        i = 0;
        for (meshnum = 0;i < count;meshnum++)
@@ -4180,12 +4180,12 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                        }
 
                        n = LittleLong(in->textureindex);
-                       if (n < 0 || n >= loadmodel->brush.num_textures)
+                       if (n < 0 || n >= loadmodel->num_textures)
                        {
-                               Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->brush.num_textures);
+                               Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->num_textures);
                                continue;
                        }
-                       out->texture = loadmodel->brush.data_textures + n;
+                       out->texture = loadmodel->data_textures + n;
                        n = LittleLong(in->effectindex);
                        if (n < -1 || n >= loadmodel->brushq3.num_effects)
                        {
@@ -4499,8 +4499,8 @@ static void Mod_Q3BSP_LoadModels(lump_t *l)
                }
                n = LittleLong(in->firstface);
                c = LittleLong(in->numfaces);
-               if (n < 0 || n + c > loadmodel->brush.num_surfaces)
-                       Host_Error("Mod_Q3BSP_LoadModels: invalid face range %i : %i (%i faces)\n", n, n + c, loadmodel->brush.num_surfaces);
+               if (n < 0 || n + c > loadmodel->num_surfaces)
+                       Host_Error("Mod_Q3BSP_LoadModels: invalid face range %i : %i (%i faces)\n", n, n + c, loadmodel->num_surfaces);
                out->firstface = n;
                out->numfaces = c;
                n = LittleLong(in->firstbrush);
@@ -4554,8 +4554,8 @@ static void Mod_Q3BSP_LoadLeafFaces(lump_t *l)
        for (i = 0;i < count;i++, in++, out++)
        {
                n = LittleLong(*in);
-               if (n < 0 || n >= loadmodel->brush.num_surfaces)
-                       Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, loadmodel->brush.num_surfaces);
+               if (n < 0 || n >= loadmodel->num_surfaces)
+                       Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, loadmodel->num_surfaces);
                *out = n;
        }
 }
@@ -4899,7 +4899,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, model_t *model,
                // line trace the curves
                for (i = 0;i < leaf->numleafsurfaces;i++)
                {
-                       surface = model->brush.data_surfaces + leaf->firstleafsurface[i];
+                       surface = model->data_surfaces + leaf->firstleafsurface[i];
                        if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
                        {
                                surface->collisionmarkframe = markframe;
@@ -5279,7 +5279,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, model_t *model
        {
                for (i = 0;i < leaf->numleafsurfaces;i++)
                {
-                       surface = model->brush.data_surfaces + leaf->firstleafsurface[i];
+                       surface = model->data_surfaces + leaf->firstleafsurface[i];
                        if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
                        {
                                surface->collisionmarkframe = markframe;
@@ -5333,7 +5333,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const
                                        if (brush->colbrushf)
                                                Collision_TraceLineBrushFloat(trace, boxstartmins, boxendmins, brush->colbrushf, brush->colbrushf);
                                if (mod_q3bsp_curves_collisions.integer)
-                                       for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+                                       for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
                                                if (surface->num_collisiontriangles)
                                                        Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
                        }
@@ -5352,7 +5352,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const
                                if (brush->colbrushf)
                                        Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf);
                        if (mod_q3bsp_curves_collisions.integer)
-                               for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+                               for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
                                        if (surface->num_collisiontriangles)
                                                Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
                }
@@ -5497,13 +5497,13 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
 
        // make a single combined shadow mesh to allow optimized shadow volume creation
        numshadowmeshtriangles = 0;
-       for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++)
+       for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
        {
                surface->num_firstshadowmeshtriangle = numshadowmeshtriangles;
                numshadowmeshtriangles += surface->num_triangles;
        }
        loadmodel->brush.shadowmesh = Mod_ShadowMesh_Begin(loadmodel->mempool, numshadowmeshtriangles * 3, numshadowmeshtriangles, NULL, NULL, NULL, false, false, true);
-       for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++)
+       for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++)
                Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surface->groupmesh->data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
        loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true);
        Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles);
@@ -5574,7 +5574,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
                mod->radius2 = modelradius * modelradius;
 
                for (j = 0;j < mod->nummodelsurfaces;j++)
-                       if (mod->brush.data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY)
+                       if (mod->data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY)
                                break;
                if (j < mod->nummodelsurfaces)
                        mod->DrawSky = R_Q1BSP_DrawSky;
index 0f2aade..1bf8be8 100644 (file)
@@ -87,119 +87,15 @@ mplane_t;
 // probably used only on q1bsp water
 #define MATERIALFLAG_LIGHTBOTHSIDES 1024
 
-struct entity_render_s;
-struct texture_s;
-struct msurface_s;
-
-typedef struct texture_s
-{
-       // q1bsp
-       // name
-       //char name[16];
-       // size
-       unsigned int width, height;
-       // SURF_ flags
-       //unsigned int flags;
-
-       // base material flags
-       int basematerialflags;
-       // current material flags (updated each bmodel render)
-       int currentmaterialflags;
-
-       // loaded the same as model skins
-       skinframe_t skin;
-
-       // total frames in sequence and alternate sequence
-       int anim_total[2];
-       // direct pointers to each of the frames in the sequences
-       // (indexed as [alternate][frame])
-       struct texture_s *anim_frames[2][10];
-       // set if animated or there is an alternate frame set
-       // (this is an optimization in the renderer)
-       int animated;
-       // the current texture frame in animation
-       struct texture_s *currentframe;
-       // current alpha of the texture
-       float currentalpha;
-
-       // q3bsp
-       char name[Q3PATHLENGTH];
-       char firstpasstexturename[Q3PATHLENGTH]; // used only during loading
-       int surfaceflags;
-       int supercontents;
-       int surfaceparms;
-       int textureflags;
-
-       //skinframe_t skin;
-}
-texture_t;
-
 typedef struct
 {
        unsigned short v[2];
 }
 medge_t;
 
-typedef struct
-{
-       float vecs[2][4];
-       texture_t *texture;
-       int flags;
-}
-mtexinfo_t;
-
-typedef struct msurface_lightmapinfo_s
-{
-       // texture mapping properties used by this surface
-       mtexinfo_t *texinfo; // q1bsp
-       // index into d_lightstylevalue array, 255 means not used (black)
-       qbyte styles[MAXLIGHTMAPS]; // q1bsp
-       // RGB lighting data [numstyles][height][width][3]
-       qbyte *samples; // q1bsp
-       // stain to apply on lightmap (soot/dirt/blood/whatever)
-       qbyte *stainsamples; // q1bsp
-       // the stride when building lightmaps to comply with fragment update
-       int lightmaptexturestride; // q1bsp
-       int texturemins[2]; // q1bsp
-       int extents[2]; // q1bsp
-}
-msurface_lightmapinfo_t;
-
-struct q3deffect_s;
-typedef struct msurface_s
-{
-       // bounding box for onscreen checks
-       vec3_t mins;
-       vec3_t maxs;
-       // the texture to use on the surface
-       texture_t *texture;
-       // the lightmap texture fragment to use on the rendering mesh
-       rtexture_t *lightmaptexture;
-
-       // this surface is part of this mesh
-       surfmesh_t *groupmesh;
-       int num_triangles; // number of triangles in the mesh
-       int num_firsttriangle; // first triangle in the mesh (index into groupmesh)
-       int num_vertices; // number of vertices in the mesh
-       int num_firstvertex; // first vertex in the mesh (index into groupmesh)
-
-       // shadow volume building information
-       int num_firstshadowmeshtriangle; // index into model->brush.shadowmesh
-
-       // lightmaptexture rebuild information not used in q3bsp
-       int cached_dlight; // q1bsp // forces rebuild of lightmaptexture
-       msurface_lightmapinfo_t *lightmapinfo; // q1bsp
-
-       // mesh information for collisions (only used by q3bsp curves)
-       int num_collisiontriangles; // q3bsp
-       int *data_collisionelement3i; // q3bsp
-       int num_collisionvertices; // q3bsp
-       float *data_collisionvertex3f; // q3bsp
-       struct q3deffect_s *effect; // q3bsp
-       // FIXME: collisionmarkframe should be kept in a separate array
-       int collisionmarkframe; // q3bsp // don't collide twice in one trace
-}
-msurface_t;
+struct entity_render_s;
+struct texture_s;
+struct msurface_s;
 
 typedef struct mnode_s
 {
index bcc813a..da90f78 100644 (file)
@@ -63,7 +63,7 @@ static void mod_newmap(void)
        {
                if (mod_known[i].name[0])
                {
-                       for (surfacenum = 0, surface = mod_known[i].brush.data_surfaces;surfacenum < mod_known[i].brush.num_surfaces;surfacenum++, surface++)
+                       for (surfacenum = 0, surface = mod_known[i].data_surfaces;surfacenum < mod_known[i].num_surfaces;surfacenum++, surface++)
                        {
                                if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
                                {
index 96cf129..614ac4c 100644 (file)
@@ -73,6 +73,15 @@ typedef struct overridetagnameset_s
 }
 overridetagnameset_t;
 
+typedef struct surfmeshvertexboneweight_s
+{
+       unsigned int vertexindex;
+       unsigned int boneindex;
+       float origin[3];
+       float weight;
+}
+surfmeshvertexboneweight_t;
+
 // used for mesh lists in q1bsp/q3bsp map models
 // (the surfaces reference portions of these meshes)
 typedef struct surfmesh_s
@@ -82,14 +91,23 @@ typedef struct surfmesh_s
        int *data_neighbor3i; // int[tris*3] neighboring triangle on each edge (-1 if none)
        int num_vertices; // number of vertices in the mesh
        float *data_vertex3f; // float[verts*3] vertex locations
-       float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture
-       float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture
-       float *data_lightmapcolor4f;
        float *data_svector3f; // float[verts*3] direction of 'S' (right) texture axis for each vertex
        float *data_tvector3f; // float[verts*3] direction of 'T' (down) texture axis for each vertex
        float *data_normal3f; // float[verts*3] direction of 'R' (out) texture axis for each vertex
+       float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture
+       float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture
        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;
+       // skeletal blending, these are zero if model is morph or static
+       int num_vertexboneweights;
+       surfmeshvertexboneweight_t *data_vertexboneweights;
 }
 surfmesh_t;
 
@@ -128,33 +146,115 @@ typedef struct shadowmesh_s
 }
 shadowmesh_t;
 
+typedef struct texture_s
+{
+       // q1bsp
+       // name
+       //char name[16];
+       // size
+       unsigned int width, height;
+       // SURF_ flags
+       //unsigned int flags;
+
+       // base material flags
+       int basematerialflags;
+       // current material flags (updated each bmodel render)
+       int currentmaterialflags;
+
+       // loaded the same as model skins
+       skinframe_t skin;
+
+       // total frames in sequence and alternate sequence
+       int anim_total[2];
+       // direct pointers to each of the frames in the sequences
+       // (indexed as [alternate][frame])
+       struct texture_s *anim_frames[2][10];
+       // set if animated or there is an alternate frame set
+       // (this is an optimization in the renderer)
+       int animated;
+       // the current texture frame in animation
+       struct texture_s *currentframe;
+       // current alpha of the texture
+       float currentalpha;
+
+       // q3bsp
+       char name[64];
+       char firstpasstexturename[64]; // used only during loading
+       int surfaceflags;
+       int supercontents;
+       int surfaceparms;
+       int textureflags;
+
+       //skinframe_t skin;
+}
+texture_t;
 
-#include "matrixlib.h"
-
-#include "model_brush.h"
-#include "model_sprite.h"
-#include "model_alias.h"
+typedef struct
+{
+       float vecs[2][4];
+       texture_t *texture;
+       int flags;
+}
+mtexinfo_t;
 
-typedef struct model_alias_s
+typedef struct msurface_lightmapinfo_s
 {
-       // mdl/md2/md3/zym model formats are treated the same after loading
+       // texture mapping properties used by this surface
+       mtexinfo_t *texinfo; // q1bsp
+       // index into d_lightstylevalue array, 255 means not used (black)
+       qbyte styles[MAXLIGHTMAPS]; // q1bsp
+       // RGB lighting data [numstyles][height][width][3]
+       qbyte *samples; // q1bsp
+       // stain to apply on lightmap (soot/dirt/blood/whatever)
+       qbyte *stainsamples; // q1bsp
+       // the stride when building lightmaps to comply with fragment update
+       int lightmaptexturestride; // q1bsp
+       int texturemins[2]; // q1bsp
+       int extents[2]; // q1bsp
+}
+msurface_lightmapinfo_t;
 
-       // the shader meshes comprising this model
-       int                             aliasnum_meshes;
-       aliasmesh_t             *aliasdata_meshes;
+struct q3deffect_s;
+typedef struct msurface_s
+{
+       // bounding box for onscreen checks
+       vec3_t mins;
+       vec3_t maxs;
+       // the texture to use on the surface
+       texture_t *texture;
+       // the lightmap texture fragment to use on the rendering mesh
+       rtexture_t *lightmaptexture;
+
+       // this surface is part of this mesh
+       surfmesh_t *groupmesh;
+       int num_triangles; // number of triangles in the mesh
+       int num_firsttriangle; // first triangle in the mesh (index into groupmesh)
+       int num_vertices; // number of vertices in the mesh
+       int num_firstvertex; // first vertex in the mesh (index into groupmesh)
+
+       // shadow volume building information
+       int num_firstshadowmeshtriangle; // index into model->brush.shadowmesh
+
+       // lightmaptexture rebuild information not used in q3bsp
+       int cached_dlight; // q1bsp // forces rebuild of lightmaptexture
+       msurface_lightmapinfo_t *lightmapinfo; // q1bsp
+
+       // mesh information for collisions (only used by q3bsp curves)
+       int num_collisiontriangles; // q3bsp
+       int *data_collisionelement3i; // q3bsp
+       int num_collisionvertices; // q3bsp
+       float *data_collisionvertex3f; // q3bsp
+       struct q3deffect_s *effect; // q3bsp
+       // FIXME: collisionmarkframe should be kept in a separate array
+       int collisionmarkframe; // q3bsp // don't collide twice in one trace
+}
+msurface_t;
 
-       // for md3 models
-       int                             aliasnum_tags;
-       int                             aliasnum_tagframes;
-       aliastag_t              *aliasdata_tags;
+#include "matrixlib.h"
 
-       // for skeletal models
-       int                             aliasnum_bones;
-       aliasbone_t             *aliasdata_bones;
-       int                             aliasnum_poses;
-       float                   *aliasdata_poses;
-}
-model_alias_t;
+#include "model_brush.h"
+#include "model_sprite.h"
+#include "model_alias.h"
 
 typedef struct model_sprite_s
 {
@@ -206,13 +306,6 @@ typedef struct model_brush_s
        int num_portalpoints;
        mvertex_t *data_portalpoints;
 
-       int num_textures;
-       texture_t *data_textures;
-
-       int num_surfaces;
-       msurface_t *data_surfaces;
-       msurface_lightmapinfo_t *data_surfaces_lightmapinfo;
-
        int num_brushes;
        q3mbrush_t *data_brushes;
 
@@ -392,6 +485,23 @@ typedef struct model_s
        int                             nummodelbrushes;
        // list of surface numbers in this (sub)model
        int                             *sur