Index: darkplaces/gl_rsurf.c
diff -u darkplaces/gl_rsurf.c:1.120 darkplaces/gl_rsurf.c:1.121
--- darkplaces/gl_rsurf.c:1.120	Sun Nov 10 00:03:41 2002
+++ darkplaces/gl_rsurf.c	Fri Nov 15 20:24:03 2002
@@ -747,7 +747,7 @@
 	return false;
 }
 
-static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -784,7 +784,7 @@
 	}
 	m.depthwrite = true;
 	R_Mesh_State(&m);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -878,13 +878,14 @@
 	}
 }
 
-static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
+	msurface_t **chain;
 	vec3_t center;
 	if (texture->rendertype != SURFRENDER_OPAQUE)
 	{
-		for (surf = firstsurf;surf;surf = surf->texturechain)
+		for (chain = surfchain;(surf = *chain) != NULL;*chain++)
 		{
 			if (surf->visframe == r_framecount)
 			{
@@ -894,7 +895,7 @@
 		}
 	}
 	else
-		for (surf = firstsurf;surf;surf = surf->texturechain)
+		for (chain = surfchain;(surf = *chain) != NULL;*chain++)
 			if (surf->visframe == r_framecount)
 				RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
 }
@@ -995,7 +996,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1006,7 +1007,7 @@
 	m.blendfunc1 = GL_ONE;
 	m.blendfunc2 = GL_ZERO;
 	m.tex[0] = R_GetTexture(texture->texture);
-	m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
+	m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
 	m.tex[2] = R_GetTexture(texture->detailtexture);
 	m.texrgbscale[0] = 1;
 	m.texrgbscale[1] = 4;
@@ -1014,7 +1015,7 @@
 	R_Mesh_State(&m);
 	cl = (float) (1 << r_lightmapscalebit) * r_colorscale;
 	GL_Color(cl, cl, cl, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1037,7 +1038,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1047,12 +1048,12 @@
 	m.blendfunc1 = GL_ONE;
 	m.blendfunc2 = GL_ZERO;
 	m.tex[0] = R_GetTexture(texture->texture);
-	m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
+	m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
 	if (gl_combine.integer)
 		m.texrgbscale[1] = 4;
 	R_Mesh_State(&m);
 	GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1074,7 +1075,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1085,7 +1086,7 @@
 	m.tex[0] = R_GetTexture(texture->texture);
 	R_Mesh_State(&m);
 	GL_Color(1, 1, 1, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1100,7 +1101,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1109,12 +1110,12 @@
 	memset(&m, 0, sizeof(m));
 	m.blendfunc1 = GL_ZERO;
 	m.blendfunc2 = GL_SRC_COLOR;
-	m.tex[0] = R_GetTexture(firstsurf->lightmaptexture);
+	m.tex[0] = R_GetTexture((**surfchain).lightmaptexture);
 	if (gl_combine.integer)
 		m.texrgbscale[0] = 4;
 	R_Mesh_State(&m);
 	GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1135,7 +1136,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1154,7 +1155,7 @@
 	}
 	R_Mesh_State(&m);
 	GL_UseColorArray();
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount && surf->dlightframe == r_framecount)
 		{
@@ -1175,7 +1176,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1187,7 +1188,7 @@
 	m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
 	R_Mesh_State(&m);
 	GL_UseColorArray();
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1204,7 +1205,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1215,7 +1216,7 @@
 	m.tex[0] = R_GetTexture(texture->detailtexture);
 	R_Mesh_State(&m);
 	GL_Color(1, 1, 1, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1230,7 +1231,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1241,7 +1242,7 @@
 	m.tex[0] = R_GetTexture(texture->glowtexture);
 	R_Mesh_State(&m);
 	GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1256,7 +1257,7 @@
 	}
 }
 
-static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
 	const surfmesh_t *mesh;
@@ -1270,7 +1271,7 @@
 		GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
 	else
 		GL_Color(0, 0, 0, 1);
-	for (surf = firstsurf;surf;surf = surf->texturechain)
+	while((surf = *surfchain++) != NULL)
 	{
 		if (surf->visframe == r_framecount)
 		{
@@ -1315,14 +1316,15 @@
 		RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha);
 }
 
-static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
 	const msurface_t *surf;
+	msurface_t **chain;
 	vec3_t center;
 	if (texture->rendertype != SURFRENDER_OPAQUE)
 	{
 		// transparent vertex shaded from lightmap
-		for (surf = firstsurf;surf;surf = surf->texturechain)
+		for (chain = surfchain;(surf = *chain) != NULL;chain++)
 		{
 			if (surf->visframe == r_framecount)
 			{
@@ -1334,22 +1336,22 @@
 	else if (r_shadow_lightingmode >= 2)
 	{
 		// opaque base lighting
-		RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
+		RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, surfchain);
 		if (fogenabled)
-			RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
+			RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain);
 	}
 	else if (r_vertexsurfaces.integer)
 	{
 		// opaque vertex shaded from lightmap
-		for (surf = firstsurf;surf;surf = surf->texturechain)
+		for (chain = surfchain;(surf = *chain) != NULL;chain++)
 			if (surf->visframe == r_framecount)
 				RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, texture->rendertype, texture->currentalpha);
 		if (texture->glowtexture)
-			for (surf = firstsurf;surf;surf = surf->texturechain)
+			for (chain = surfchain;(surf = *chain) != NULL;chain++)
 				if (surf->visframe == r_framecount)
 					RSurfShader_Wall_Pass_Glow(ent, surf, texture, texture->rendertype, texture->currentalpha);
 		if (fogenabled)
-			for (surf = firstsurf;surf;surf = surf->texturechain)
+			for (chain = surfchain;(surf = *chain) != NULL;chain++)
 				if (surf->visframe == r_framecount)
 					RSurfShader_Wall_Pass_Fog(ent, surf, texture, texture->rendertype, texture->currentalpha);
 	}
@@ -1359,27 +1361,27 @@
 		if (r_textureunits.integer >= 2)
 		{
 			if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
-				RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
+				RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, surfchain);
 			else
 			{
-				RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
+				RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, surfchain);
 				if (r_detailtextures.integer)
-					RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+					RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain);
 			}
 		}
 		else
 		{
-			RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
-			RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
+			RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain);
+			RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, surfchain);
 			if (r_detailtextures.integer)
-				RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+				RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain);
 		}
 		if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
-			RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
+			RSurfShader_OpaqueWall_Pass_Light(ent, texture, surfchain);
 		if (texture->glowtexture)
-			RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
+			RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain);
 		if (fogenabled)
-			RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
+			RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain);
 	}
 }
 
@@ -1488,14 +1490,14 @@
 	}
 }
 
-void R_DrawSurfaces(entity_render_t *ent, int type)
+void R_DrawSurfaces(entity_render_t *ent, int type, msurface_t ***chains)
 {
 	int i;
 	texture_t *t;
 	R_Mesh_Matrix(&ent->matrix);
 	for (i = 0, t = ent->model->textures;i < ent->model->numtextures;i++, t++)
-		if (t->shader->shaderfunc[type] && t->currentframe && ent->model->texturesurfacechains[i])
-			t->shader->shaderfunc[type](ent, t->currentframe, ent->model->texturesurfacechains[i]);
+		if (t->shader->shaderfunc[type] && t->currentframe && chains[i] != NULL)
+			t->shader->shaderfunc[type](ent, t->currentframe, chains[i]);
 }
 
 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
@@ -1532,24 +1534,17 @@
 	int i;
 	mportal_t *portal, *endportal;
 	float temp[3], center[3], f;
-
-	if (r_drawportals.integer < 1)
-		return;
-
 	for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
 	{
-		if (portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount)
+		if ((portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount) && portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
 		{
-			if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
-			{
-				VectorClear(temp);
-				for (i = 0;i < portal->numpoints;i++)
-					VectorAdd(temp, portal->points[i].position, temp);
-				f = ixtable[portal->numpoints];
-				VectorScale(temp, f, temp);
-				Matrix4x4_Transform(&ent->matrix, temp, center);
-				R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
-			}
+			VectorClear(temp);
+			for (i = 0;i < portal->numpoints;i++)
+				VectorAdd(temp, portal->points[i].position, temp);
+			f = ixtable[portal->numpoints];
+			VectorScale(temp, f, temp);
+			Matrix4x4_Transform(&ent->matrix, temp, center);
+			R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
 		}
 	}
 }
@@ -1580,22 +1575,12 @@
 		if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
 		{
 			if ((surf->flags & SURF_PLANEBACK))
-			{
 				surfacevisframes[i] = r_framecount;
-				surfacepvsframes[i] = model->pvsframecount;
-			}
-		}
-		else
-		{
-			if (!(surf->flags & SURF_PLANEBACK))
-			{
-				surfacevisframes[i] = r_framecount;
-				surfacepvsframes[i] = model->pvsframecount;
-			}
 		}
+		else if (!(surf->flags & SURF_PLANEBACK))
+			surfacevisframes[i] = r_framecount;
 #else
 		surfacevisframes[i] = r_framecount;
-		surfacepvsframes[i] = model->pvsframecount;
 #endif
 		surf->dlightframe = -1;
 	}
@@ -1757,20 +1742,12 @@
 							leaf->pvsframe = model->pvsframecount;
 							// mark surfaces bounding this leaf as visible
 							for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--, mark++)
-							{
-								//if (surfacepvsframes[*mark] != model->pvsframecount)
-								//{
-									surfacepvsframes[*mark] = model->pvsframecount;
-								//	model->pvssurflist[model->pvssurflistlength++] = *mark;
-								//}
-							}
+								surfacepvsframes[*mark] = model->pvsframecount;
 						}
 					}
 				}
 			}
-			for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
-				if (model->surfacepvsframes[j] == model->pvsframecount)
-					model->pvssurflist[model->pvssurflistlength++] = j;
+			Mod_BuildPVSTextureChains(model);
 		}
 	}
 }
@@ -1796,15 +1773,15 @@
 void R_DrawWorld (entity_render_t *ent)
 {
 	R_PrepareSurfaces(ent);
-	R_DrawSurfaces(ent, SHADERSTAGE_SKY);
-	R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
+	R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->pvstexturechains);
+	R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_DrawSky (entity_render_t *ent)
 {
 	if (ent != &cl_entities[0].render)
 		R_PrepareBrushModel(ent);
-	R_DrawSurfaces(ent, SHADERSTAGE_SKY);
+	R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_Draw (entity_render_t *ent)
@@ -1812,7 +1789,7 @@
 	c_bmodels++;
 	if (ent != &cl_entities[0].render)
 		R_PrepareBrushModel(ent);
-	R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
+	R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
Index: darkplaces/model_brush.c
diff -u darkplaces/model_brush.c:1.86 darkplaces/model_brush.c:1.87
--- darkplaces/model_brush.c:1.86	Sat Nov  9 21:34:19 2002
+++ darkplaces/model_brush.c	Fri Nov 15 20:24:03 2002
@@ -236,6 +236,7 @@
 	// fill out all slots with notexture
 	for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
 	{
+		tx->number = i;
 		tx->width = 16;
 		tx->height = 16;
 		tx->texture = r_notexture;
@@ -2738,6 +2739,42 @@
 #endif
 }
 
+void Mod_BuildPVSTextureChains(model_t *model)
+{
+	int i, j;
+	for (i = 0;i < model->numtextures;i++)
+		model->pvstexturechainslength[i] = 0;
+	for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+	{
+		if (model->surfacepvsframes[j] == model->pvsframecount)
+		{
+			model->pvssurflist[model->pvssurflistlength++] = j;
+			model->pvstexturechainslength[model->surfaces[j].texinfo->texture->number]++;
+		}
+	}
+	for (i = 0, j = 0;i < model->numtextures;i++)
+	{
+		if (model->pvstexturechainslength[i])
+		{
+			model->pvstexturechains[i] = model->pvstexturechainsbuffer + j;
+			j += model->pvstexturechainslength[i] + 1;
+		}
+		else
+			model->pvstexturechains[i] = NULL;
+	}
+	for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+		if (model->surfacepvsframes[j] == model->pvsframecount)
+			*model->pvstexturechains[model->surfaces[j].texinfo->texture->number]++ = model->surfaces + j;
+	for (i = 0;i < model->numtextures;i++)
+	{
+		if (model->pvstexturechainslength[i])
+		{
+			*model->pvstexturechains[i] = NULL;
+			model->pvstexturechains[i] -= model->pvstexturechainslength[i];
+		}
+	}
+}
+
 /*
 =================
 Mod_LoadBrushModel
@@ -2818,11 +2855,6 @@
 		float dist, modelyawradius, modelradius, *vec;
 		msurface_t *surf;
 
-		mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
-		mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
-		modelyawradius = 0;
-		modelradius = 0;
-
 		bm = &mod->submodels[i];
 
 		mod->hulls[0].firstclipnode = bm->headnode[0];
@@ -2841,18 +2873,22 @@
 		mod->DrawFakeShadow = NULL;
 		mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
 		mod->DrawLight = R_Model_Brush_DrawLight;
-		mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
+		mod->pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t **));
+		mod->pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool, (mod->nummodelsurfaces + mod->numtextures) * sizeof(msurface_t *));
+		mod->pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(int));
+		Mod_BuildPVSTextureChains(mod);
 		if (mod->nummodelsurfaces)
 		{
 			// LordHavoc: calculate bmodel bounding box rather than trusting what it says
+			mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+			mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+			modelyawradius = 0;
+			modelradius = 0;
 			for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
 			{
 				// we only need to have a drawsky function if it is used (usually only on world model)
 				if (surf->texinfo->texture->shader == &Cshader_sky)
 					mod->DrawSky = R_Model_Brush_DrawSky;
-				// link into texture chain
-				surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
-				mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
 				// calculate bounding shapes
 				for (k = 0;k < surf->numedges;k++)
 				{
@@ -2884,28 +2920,11 @@
 			mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
 			mod->radius = modelradius;
 			mod->radius2 = modelradius * modelradius;
-			// LordHavoc: build triangle meshs for entire model's geometry
-			// (only used for shadow volumes)
-			mod->shadowmesh = Mod_ShadowMesh_Begin(originalloadmodel->mempool, 1024);
-			for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
-				if (surf->flags & SURF_SHADOWCAST)
-					Mod_ShadowMesh_AddPolygon(originalloadmodel->mempool, mod->shadowmesh, surf->poly_numverts, surf->poly_verts);
-			mod->shadowmesh = Mod_ShadowMesh_Finish(originalloadmodel->mempool, mod->shadowmesh);
-			Mod_ShadowMesh_CalcBBox(mod->shadowmesh, mod->shadowmesh_mins, mod->shadowmesh_maxs, mod->shadowmesh_center, &mod->shadowmesh_radius);
 		}
 		else
 		{
 			// LordHavoc: empty submodel (lacrima.bsp has such a glitch)
 			Con_Printf("warning: empty submodel *%i in %s\n", i+1, loadname);
-			VectorClear(mod->normalmins);
-			VectorClear(mod->normalmaxs);
-			VectorClear(mod->yawmins);
-			VectorClear(mod->yawmaxs);
-			VectorClear(mod->rotatedmins);
-			VectorClear(mod->rotatedmaxs);
-			mod->radius = 0;
-			mod->radius2 = 0;
-			mod->shadowmesh = NULL;
 		}
 		Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);
 
Index: darkplaces/model_brush.h
diff -u darkplaces/model_brush.h:1.58 darkplaces/model_brush.h:1.59
--- darkplaces/model_brush.h:1.58	Mon Nov  4 10:56:31 2002
+++ darkplaces/model_brush.h	Fri Nov 15 20:24:03 2002
@@ -82,7 +82,7 @@
 // change this stuff when real shaders are added
 typedef struct Cshader_s
 {
-	void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, const struct msurface_s *firstsurf);
+	void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, struct msurface_s **surfchain);
 	int flags;
 }
 Cshader_t;
@@ -100,6 +100,9 @@
 	// SURF_ flags
 	unsigned int flags;
 
+	// position in the model's textures array
+	int number;
+
 	// type of rendering (SURFRENDER_ value)
 	int rendertype;
 
@@ -380,6 +383,7 @@
 mleaf_t *Mod_PointInLeaf (const float *p, struct model_s *model);
 int Mod_PointContents (const float *p, struct model_s *model);
 qbyte *Mod_LeafPVS (mleaf_t *leaf, struct model_s *model);
+void Mod_BuildPVSTextureChains(struct model_s *model);
 
 #endif
 
Index: darkplaces/model_shared.h
diff -u darkplaces/model_shared.h:1.36 darkplaces/model_shared.h:1.37
--- darkplaces/model_shared.h:1.36	Sun Nov 10 00:03:42 2002
+++ darkplaces/model_shared.h	Fri Nov 15 20:24:03 2002
@@ -188,8 +188,6 @@
 	int				numtextures;
 	texture_t		*textures;
 
-	msurface_t		**texturesurfacechains;
-
 	qbyte			*visdata;
 	qbyte			*lightdata;
 	char			*entities;
@@ -203,11 +201,6 @@
 	int				numlights;
 	mlight_t		*lights;
 
-	// used only for casting dynamic shadow volumes
-	shadowmesh_t	*shadowmesh;
-	vec3_t			shadowmesh_mins, shadowmesh_maxs, shadowmesh_center;
-	float			shadowmesh_radius;
-
 	// pvs visibility marking
 	mleaf_t			*pvsviewleaf;
 	int				pvsviewleafnovis;
@@ -215,6 +208,12 @@
 	mleaf_t			*pvsleafchain;
 	int				*pvssurflist;
 	int				pvssurflistlength;
+	// these get rebuilt as the player moves around if this is the world,
+	// otherwise they are left alone (no pvs for bmodels)
+	msurface_t		***pvstexturechains;
+	msurface_t		**pvstexturechainsbuffer;
+	int				*pvstexturechainslength;
+
 
 	// skin animation info
 	animscene_t		*skinscenes; // [numskins]