This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to annotated tag 1.42d
in repository iortcw.

commit f993d35f4ae6fb43480ce854b7511836a96c257d
Author: m4n4t4...@gmail.com 
<m4n4t4...@gmail.com@e65d2741-a53d-b2dc-ae96-bb75fa5e4c4a>
Date:   Wed Oct 8 23:41:14 2014 +0000

    All: Rend2: Better BSP surface merging
---
 MP/code/rend2/tr_bsp.c | 612 ++++++++++++++++++-------------------------------
 SP/code/rend2/tr_bsp.c | 611 ++++++++++++++++++------------------------------
 2 files changed, 454 insertions(+), 769 deletions(-)

diff --git a/MP/code/rend2/tr_bsp.c b/MP/code/rend2/tr_bsp.c
index fc1509c..042efdc 100644
--- a/MP/code/rend2/tr_bsp.c
+++ b/MP/code/rend2/tr_bsp.c
@@ -2040,6 +2040,20 @@ static int BSPSurfaceCompare(const void *a, const void 
*b)
        else if(aa->cubemapIndex > bb->cubemapIndex)
                return 1;
 
+       // by leaf
+       if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] < 
s_worldData.surfacesViewCount[bb - s_worldData.surfaces])
+               return -1;
+
+       else if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] > 
s_worldData.surfacesViewCount[bb - s_worldData.surfaces])
+               return 1;
+
+       // by surface number
+       if (aa < bb)
+               return -1;
+
+       else if (aa > bb)
+               return 1;
+
 
        return 0;
 }
@@ -2047,33 +2061,20 @@ static int BSPSurfaceCompare(const void *a, const void 
*b)
 
 static void CopyVert(const srfVert_t * in, srfVert_t * out)
 {
-       int             j;
-
-       for(j = 0; j < 3; j++)
-       {
-               out->xyz[j]       = in->xyz[j];
+       VectorCopy(in->xyz,      out->xyz);
 #ifdef USE_VERT_TANGENT_SPACE
-               out->tangent[j]   = in->tangent[j];
-               //out->bitangent[j] = in->bitangent[j];
+       VectorCopy4(in->tangent, out->tangent);
 #endif
-               out->normal[j]    = in->normal[j];
-               out->lightdir[j]  = in->lightdir[j];
-       }
+       VectorCopy(in->normal,   out->normal);
+       VectorCopy(in->lightdir, out->lightdir);
 
-       out->tangent[3] = in->tangent[3];
-
-       for(j = 0; j < 2; j++)
-       {
-               out->st[j] = in->st[j];
-               out->lightmap[j] = in->lightmap[j];
-       }
+       VectorCopy2(in->st,       out->st);
+       VectorCopy2(in->lightmap, out->lightmap);
 
-       for(j = 0; j < 4; j++)
-       {
-               out->vertexColors[j] = in->vertexColors[j];
-       }
+       VectorCopy4(in->vertexColors, out->vertexColors);
 }
 
+
 /*
 ===============
 R_CreateWorldVBOs
@@ -2097,26 +2098,74 @@ static void R_CreateWorldVBOs(void)
        IBO_t *ibo;
 
        int maxVboSize = 4 * 1024 * 1024;
-       int maxIboSize = 4 * 1024 * 1024;
 
        int             startTime, endTime;
 
        startTime = ri.Milliseconds();
 
+       // mark surfaces with best matching leaf, using overlapping bounds
+       // using surfaceViewCount[] as leaf number, and surfacesDlightBits[] as 
coverage * 256
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesViewCount[i] = -1;
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesDlightBits[i] = 0;
+       }
+
+       for (i = s_worldData.numDecisionNodes; i < s_worldData.numnodes; i++)
+       {
+               mnode_t *leaf = s_worldData.nodes + i;
+
+               for (j = leaf->firstmarksurface; j < leaf->firstmarksurface + 
leaf->nummarksurfaces; j++)
+               {
+                       int surfaceNum = s_worldData.marksurfaces[j];
+                       msurface_t *surface = s_worldData.surfaces + surfaceNum;
+                       float coverage = 1.0f;
+                       int iCoverage;
+
+                       for (k = 0; k < 3; k++)
+                       {
+                               float left, right;
+
+                               if (leaf->mins[k] > 
surface->cullinfo.bounds[1][k] || surface->cullinfo.bounds[0][k] > 
leaf->maxs[k])
+                               {
+                                       coverage = 0.0f;
+                                       break;
+                               }
+
+                               left  = MAX(leaf->mins[k], 
surface->cullinfo.bounds[0][k]);
+                               right = MIN(leaf->maxs[k], 
surface->cullinfo.bounds[1][k]);
+
+                               // nudge a bit in case this is an axis aligned 
wall
+                               coverage *= right - left + 1.0f/256.0f;
+                       }
+
+                       iCoverage = coverage * 256;
+
+                       if (iCoverage > 
s_worldData.surfacesDlightBits[surfaceNum])
+                       {
+                               s_worldData.surfacesDlightBits[surfaceNum] = 
iCoverage;
+                               s_worldData.surfacesViewCount[surfaceNum] = i - 
s_worldData.numDecisionNodes;
+                       }
+               }
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesDlightBits[i] = 0;
+       }
+
        // count surfaces
        numSortedSurfaces = 0;
-       for(surface = &s_worldData.surfaces[0]; surface < 
&s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
+       for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + 
s_worldData.numWorldSurfaces; surface++)
        {
                srfBspSurface_t *bspSurf;
                shader_t *shader = surface->shader;
 
-               if (shader->isPortal)
-                       continue;
-
-               if (shader->isSky)
-                       continue;
-
-               if (ShaderRequiresCPUDeforms(shader))
+               if (shader->isPortal || shader->isSky || 
ShaderRequiresCPUDeforms(shader))
                        continue;
 
                // check for this now so we can use srfBspSurface_t* 
universally in the rest of the function
@@ -2135,18 +2184,12 @@ static void R_CreateWorldVBOs(void)
        surfacesSorted = ri.Z_Malloc(numSortedSurfaces * 
sizeof(*surfacesSorted));
 
        j = 0;
-       for(surface = &s_worldData.surfaces[0]; surface < 
&s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
+       for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + 
s_worldData.numWorldSurfaces; surface++)
        {
                srfBspSurface_t *bspSurf;
                shader_t *shader = surface->shader;
 
-               if (shader->isPortal)
-                       continue;
-
-               if (shader->isSky)
-                       continue;
-
-               if (ShaderRequiresCPUDeforms(shader))
+               if (shader->isPortal || shader->isSky || 
ShaderRequiresCPUDeforms(shader))
                        continue;
 
                // check for this now so we can use srfBspSurface_t* 
universally in the rest of the function
@@ -2164,37 +2207,34 @@ static void R_CreateWorldVBOs(void)
        qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), 
BSPSurfaceCompare);
 
        k = 0;
-       for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
&surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf)
+       for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + 
numSortedSurfaces; firstSurf = lastSurf)
        {
-               int currVboSize, currIboSize;
+               int currVboSize;
 
-               // Find range of surfaces to merge by:
-               // - Collecting a number of surfaces which fit under 
maxVboSize/maxIboSize, or
-               // - All the surfaces with a single shader which go over 
maxVboSize/maxIboSize
-               currVboSize = currIboSize = 0;
-               while (currVboSize < maxVboSize && currIboSize < maxIboSize && 
lastSurf < &surfacesSorted[numSortedSurfaces])
+               // Find range of surfaces to place in a vbo/ibo by:
+               // - Collecting a number of surfaces which fit under 
maxVboSize, or
+               // - All the surfaces with a single shader which go over 
maxVboSize
+               currVboSize = 0;
+               while (currVboSize < maxVboSize && lastSurf < surfacesSorted + 
numSortedSurfaces)
                {
-                       int addVboSize, addIboSize, currShaderIndex;
+                       int addVboSize, currShaderIndex;
 
-                       addVboSize = addIboSize = 0;
+                       addVboSize = 0;
                        currShaderIndex = (*lastSurf)->shader->sortedIndex;
 
-                       for(currSurf = lastSurf; currSurf < 
&surfacesSorted[numSortedSurfaces] && (*currSurf)->shader->sortedIndex == 
currShaderIndex; currSurf++)
+                       for(currSurf = lastSurf; currSurf < surfacesSorted + 
numSortedSurfaces && (*currSurf)->shader->sortedIndex == currShaderIndex; 
currSurf++)
                        {
                                srfBspSurface_t *bspSurf = (srfBspSurface_t *) 
(*currSurf)->data;
 
                                addVboSize += bspSurf->numVerts * 
sizeof(srfVert_t);
-                               addIboSize += bspSurf->numIndexes * 
sizeof(glIndex_t);
                        }
 
-                       if ((currVboSize != 0 && addVboSize + currVboSize > 
maxVboSize)
-                        || (currIboSize != 0 && addIboSize + currIboSize > 
maxIboSize))
+                       if (currVboSize != 0 && addVboSize + currVboSize > 
maxVboSize)
                                break;
 
                        lastSurf = currSurf;
 
                        currVboSize += addVboSize;
-                       currIboSize += addIboSize;
                }
 
                // count verts/indexes/surfaces
@@ -2270,6 +2310,141 @@ static void R_CreateWorldVBOs(void)
                k++;
        }
 
+       if (r_mergeLeafSurfaces->integer)
+       {
+               msurface_t *mergedSurf;
+
+               // count merged surfaces
+               int numMergedSurfaces = 0, numUnmergedSurfaces = 0;
+               for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
+               {
+                       for (lastSurf++ ; lastSurf < surfacesSorted + 
numSortedSurfaces; lastSurf++)
+                       {
+                               int lastSurfLeafIndex, firstSurfLeafIndex;
+
+                               if ((*lastSurf)->shader         != 
(*firstSurf)->shader
+                                || (*lastSurf)->fogIndex       != 
(*firstSurf)->fogIndex
+                                || (*lastSurf)->cubemapIndex   != 
(*firstSurf)->cubemapIndex)
+                                       break;
+
+                               lastSurfLeafIndex  = 
s_worldData.surfacesViewCount[*lastSurf  - s_worldData.surfaces];
+                               firstSurfLeafIndex = 
s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces];
+
+                               if (lastSurfLeafIndex != firstSurfLeafIndex)
+                                       break;
+                       }
+
+                       // don't merge single surfaces
+                       if (firstSurf + 1 == lastSurf)
+                       {
+                               numUnmergedSurfaces++;
+                               continue;
+                       }
+
+                       numMergedSurfaces++;
+               }
+
+               // Allocate merged surfaces
+               s_worldData.mergedSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low);
+               s_worldData.mergedSurfacesViewCount = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, 
h_low);
+               s_worldData.mergedSurfacesDlightBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * 
numMergedSurfaces, h_low);
+               s_worldData.mergedSurfacesPshadowBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * 
numMergedSurfaces, h_low);
+               s_worldData.numMergedSurfaces = numMergedSurfaces;
+               
+               // view surfaces are like mark surfaces, except negative ones 
represent merged surfaces
+               // -1 represents 0, -2 represents 1, and so on
+               s_worldData.viewSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, 
h_low);
+
+               // copy view surfaces into mark surfaces
+               for (i = 0; i < s_worldData.nummarksurfaces; i++)
+               {
+                       s_worldData.viewSurfaces[i] = 
s_worldData.marksurfaces[i];
+               }
+
+               // actually merge surfaces
+               mergedSurf = s_worldData.mergedSurfaces;
+               for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
+               {
+                       srfBspSurface_t *bspSurf, *vboSurf;
+
+                       for ( lastSurf++ ; lastSurf < surfacesSorted + 
numSortedSurfaces; lastSurf++)
+                       {
+                               int lastSurfLeafIndex, firstSurfLeafIndex;
+
+                               if ((*lastSurf)->shader         != 
(*firstSurf)->shader
+                                || (*lastSurf)->fogIndex       != 
(*firstSurf)->fogIndex
+                                || (*lastSurf)->cubemapIndex   != 
(*firstSurf)->cubemapIndex)
+                                       break;
+
+                               lastSurfLeafIndex  = 
s_worldData.surfacesViewCount[*lastSurf  - s_worldData.surfaces];
+                               firstSurfLeafIndex = 
s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces];
+
+                               if (lastSurfLeafIndex != firstSurfLeafIndex)
+                                       break;
+                       }
+
+                       // don't merge single surfaces
+                       if (firstSurf + 1 == lastSurf)
+                               continue;
+
+                       bspSurf = (srfBspSurface_t *)(*firstSurf)->data;
+
+                       vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
+                       memset(vboSurf, 0, sizeof(*vboSurf));
+                       vboSurf->surfaceType = SF_VBO_MESH;
+
+                       vboSurf->vbo = bspSurf->vbo;
+                       vboSurf->ibo = bspSurf->ibo;
+
+                       vboSurf->firstIndex = bspSurf->firstIndex;
+                       vboSurf->minIndex = bspSurf->minIndex;
+                       vboSurf->maxIndex = bspSurf->maxIndex;
+
+                       ClearBounds(vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                       {
+                               srfBspSurface_t *currBspSurf = (srfBspSurface_t 
*)(*currSurf)->data;
+
+                               vboSurf->numVerts   += currBspSurf->numVerts;
+                               vboSurf->numIndexes += currBspSurf->numIndexes;
+                               vboSurf->minIndex = MIN(vboSurf->minIndex, 
currBspSurf->minIndex);
+                               vboSurf->maxIndex = MAX(vboSurf->maxIndex, 
currBspSurf->maxIndex);
+                               
AddPointToBounds((*currSurf)->cullinfo.bounds[0], vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                               
AddPointToBounds((*currSurf)->cullinfo.bounds[1], vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                       }
+
+                       VectorCopy(vboSurf->cullBounds[0], 
mergedSurf->cullinfo.bounds[0]);
+                       VectorCopy(vboSurf->cullBounds[1], 
mergedSurf->cullinfo.bounds[1]);
+
+                       mergedSurf->cullinfo.type =  CULLINFO_BOX;
+                       mergedSurf->data          =  (surfaceType_t *)vboSurf;
+                       mergedSurf->fogIndex      =  (*firstSurf)->fogIndex;
+                       mergedSurf->cubemapIndex  =  (*firstSurf)->cubemapIndex;
+                       mergedSurf->shader        =  (*firstSurf)->shader;
+
+                       // redirect view surfaces to this surf
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                               s_worldData.surfacesViewCount[*currSurf - 
s_worldData.surfaces] = -2;
+
+                       for (k = 0; k < s_worldData.nummarksurfaces; k++)
+                       {
+                               if 
(s_worldData.surfacesViewCount[s_worldData.marksurfaces[k]] == -2)
+                                       s_worldData.viewSurfaces[k] = 
-((int)(mergedSurf - s_worldData.mergedSurfaces) + 1);
+                       }
+
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                               s_worldData.surfacesViewCount[*currSurf - 
s_worldData.surfaces] = -1;
+
+                       mergedSurf++;
+               }
+
+               ri.Printf(PRINT_ALL, "Processed %d mergeable surfaces into %d 
merged, %d unmerged\n", 
+                       numSortedSurfaces, numMergedSurfaces, 
numUnmergedSurfaces);
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+               s_worldData.surfacesViewCount[i] = -1;
+
        ri.Free(surfacesSorted);
 
        endTime = ri.Milliseconds();
@@ -3266,335 +3441,6 @@ void R_RenderAllCubemaps(void)
 }
 
 
-/*
-=================
-R_MergeLeafSurfaces
-
-Merges surfaces that share a common leaf
-=================
-*/
-void R_MergeLeafSurfaces(void)
-{
-       int i, j, k;
-       int numWorldSurfaces;
-       int mergedSurfIndex;
-       int numMergedSurfaces;
-       int numUnmergedSurfaces;
-       VBO_t *vbo;
-       IBO_t *ibo;
-
-       msurface_t *mergedSurf;
-
-       glIndex_t *iboIndexes, *outIboIndexes;
-       int numIboIndexes;
-
-       int startTime, endTime;
-
-       startTime = ri.Milliseconds();
-
-       numWorldSurfaces = s_worldData.numWorldSurfaces;
-
-       // use viewcount to keep track of mergers
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               s_worldData.surfacesViewCount[i] = -1;
-       }
-
-       // mark matching surfaces
-       for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; 
i++)
-       {
-               mnode_t *leaf = s_worldData.nodes + 
s_worldData.numDecisionNodes + i;
-
-               for (j = 0; j < leaf->nummarksurfaces; j++)
-               {
-                       msurface_t *surf1;
-                       shader_t *shader1;
-                       int fogIndex1;
-                       int cubemapIndex1;
-                       int surfNum1;
-
-                       surfNum1 = *(s_worldData.marksurfaces + 
leaf->firstmarksurface + j);
-
-                       if (s_worldData.surfacesViewCount[surfNum1] != -1)
-                               continue;
-
-                       surf1 = s_worldData.surfaces + surfNum1;
-
-                       if ((*surf1->data != SF_GRID) && (*surf1->data != 
SF_TRIANGLES) && (*surf1->data != SF_FACE))
-                               continue;
-
-                       shader1 = surf1->shader;
-
-                       if(shader1->isSky)
-                               continue;
-
-                       if(shader1->isPortal)
-                               continue;
-
-                       if(ShaderRequiresCPUDeforms(shader1))
-                               continue;
-
-                       fogIndex1 = surf1->fogIndex;
-                       cubemapIndex1 = surf1->cubemapIndex;
-
-                       s_worldData.surfacesViewCount[surfNum1] = surfNum1;
-
-                       for (k = j + 1; k < leaf->nummarksurfaces; k++)
-                       {
-                               msurface_t *surf2;
-                               shader_t *shader2;
-                               int fogIndex2;
-                               int cubemapIndex2;
-                               int surfNum2;
-
-                               surfNum2 = *(s_worldData.marksurfaces + 
leaf->firstmarksurface + k);
-
-                               if (s_worldData.surfacesViewCount[surfNum2] != 
-1)
-                                       continue;
-                               
-                               surf2 = s_worldData.surfaces + surfNum2;
-
-                               if ((*surf2->data != SF_GRID) && (*surf2->data 
!= SF_TRIANGLES) && (*surf2->data != SF_FACE))
-                                       continue;
-
-                               shader2 = surf2->shader;
-
-                               if (shader1 != shader2)
-                                       continue;
-
-                               fogIndex2 = surf2->fogIndex;
-
-                               if (fogIndex1 != fogIndex2)
-                                       continue;
-
-                               cubemapIndex2 = surf2->cubemapIndex;
-
-                               if (cubemapIndex1 != cubemapIndex2)
-                                       continue;
-
-                               s_worldData.surfacesViewCount[surfNum2] = 
surfNum1;
-                       }
-               }
-       }
-
-       // don't add surfaces that don't merge to any others to the merged list
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               qboolean merges = qfalse;
-
-               if (s_worldData.surfacesViewCount[i] != i)
-                       continue;
-
-               for (j = 0; j < numWorldSurfaces; j++)
-               {
-                       if (j == i)
-                               continue;
-
-                       if (s_worldData.surfacesViewCount[j] == i)
-                       {
-                               merges = qtrue;
-                               break;
-                       }
-               }
-
-               if (!merges)
-                       s_worldData.surfacesViewCount[i] = -1;
-       }       
-
-       // count merged/unmerged surfaces
-       numMergedSurfaces = 0;
-       numUnmergedSurfaces = 0;
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               if (s_worldData.surfacesViewCount[i] == i)
-               {
-                       numMergedSurfaces++;
-               }
-               else if (s_worldData.surfacesViewCount[i] == -1)
-               {
-                       numUnmergedSurfaces++;
-               }
-       }
-
-       // Allocate merged surfaces
-       s_worldData.mergedSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low);
-       s_worldData.mergedSurfacesViewCount = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, 
h_low);
-       s_worldData.mergedSurfacesDlightBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * 
numMergedSurfaces, h_low);
-       s_worldData.mergedSurfacesPshadowBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * 
numMergedSurfaces, h_low);
-       s_worldData.numMergedSurfaces = numMergedSurfaces;
-       
-       // view surfaces are like mark surfaces, except negative ones represent 
merged surfaces
-       // -1 represents 0, -2 represents 1, and so on
-       s_worldData.viewSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, 
h_low);
-
-       // copy view surfaces into mark surfaces
-       for (i = 0; i < s_worldData.nummarksurfaces; i++)
-       {
-               s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
-       }
-
-       // need to be synched here
-       R_IssuePendingRenderCommands();
-
-       // actually merge surfaces
-       mergedSurfIndex = 0;
-       mergedSurf = s_worldData.mergedSurfaces;
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               msurface_t *surf1;
-
-               vec3_t bounds[2];
-
-               int numSurfsToMerge;
-               int numIndexes;
-               int numVerts;
-               int firstIndex;
-
-               srfBspSurface_t *vboSurf;
-
-               if (s_worldData.surfacesViewCount[i] != i)
-                       continue;
-
-               surf1 = s_worldData.surfaces + i;
-
-               // retrieve vbo
-               vbo = ((srfBspSurface_t *)(surf1->data))->vbo;
-
-               // count verts, indexes, and surfaces
-               numSurfsToMerge = 0;
-               numIndexes = 0;
-               numVerts = 0;
-               for (j = i; j < numWorldSurfaces; j++)
-               {
-                       msurface_t *surf2;
-                       srfBspSurface_t *bspSurf;
-
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       surf2 = s_worldData.surfaces + j;
-
-                       bspSurf = (srfBspSurface_t *) surf2->data;
-
-                       numIndexes += bspSurf->numIndexes;
-                       numVerts += bspSurf->numVerts;
-                       numSurfsToMerge++;
-               }
-
-               if (numVerts == 0 || numIndexes == 0 || numSurfsToMerge < 2)
-               {
-                       continue;
-               }
-
-               // create ibo
-               ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
-               memset(ibo, 0, sizeof(*ibo));
-               Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", 
tr.numIBOs++), sizeof(ibo->name));
-               numIboIndexes = 0;
-
-               // allocate indexes
-               iboIndexes = outIboIndexes = ri.Z_Malloc(numIndexes * 
sizeof(*outIboIndexes));
-
-               // Merge surfaces (indexes) and calculate bounds
-               ClearBounds(bounds[0], bounds[1]);
-               firstIndex = numIboIndexes;
-               for (j = i; j < numWorldSurfaces; j++)
-               {
-                       msurface_t *surf2;
-                       srfBspSurface_t *bspSurf;
-
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       surf2 = s_worldData.surfaces + j;
-
-                       AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], 
bounds[1]);
-                       AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], 
bounds[1]);
-
-                       bspSurf = (srfBspSurface_t *) surf2->data;
-                       for (k = 0; k < bspSurf->numIndexes; k++)
-                       {
-                               *outIboIndexes++ = bspSurf->indexes[k] + 
bspSurf->firstVert;
-                               numIboIndexes++;
-                       }
-                       break;
-               }
-
-               vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
-               memset(vboSurf, 0, sizeof(*vboSurf));
-               vboSurf->surfaceType = SF_VBO_MESH;
-
-               vboSurf->vbo = vbo;
-               vboSurf->ibo = ibo;
-
-               vboSurf->numIndexes = numIndexes;
-               vboSurf->numVerts = numVerts;
-               vboSurf->firstIndex = firstIndex;
-
-               vboSurf->minIndex = *(iboIndexes + firstIndex);
-               vboSurf->maxIndex = *(iboIndexes + firstIndex);
-
-               for (j = 0; j < numIndexes; j++)
-               {
-                       vboSurf->minIndex = MIN(vboSurf->minIndex, *(iboIndexes 
+ firstIndex + j));
-                       vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes 
+ firstIndex + j));
-               }
-
-               VectorCopy(bounds[0], vboSurf->cullBounds[0]);
-               VectorCopy(bounds[1], vboSurf->cullBounds[1]);
-
-               VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]);
-               VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]);
-
-               mergedSurf->cullinfo.type = CULLINFO_BOX;
-               mergedSurf->data          = (surfaceType_t *)vboSurf;
-               mergedSurf->fogIndex      = surf1->fogIndex;
-               mergedSurf->cubemapIndex  = surf1->cubemapIndex;
-               mergedSurf->shader        = surf1->shader;
-
-               // finish up the ibo
-               qglGenBuffersARB(1, &ibo->indexesVBO);
-
-               R_BindIBO(ibo);
-               qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * 
sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
-               R_BindNullIBO();
-
-               GL_CheckErrors();
-
-               ri.Free(iboIndexes);
-
-               // redirect view surfaces to this surf
-               for (j = 0; j < numWorldSurfaces; j++)
-               {
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       for (k = 0; k < s_worldData.nummarksurfaces; k++)
-                       {
-                               int *mark = s_worldData.marksurfaces + k;
-                               int *view = s_worldData.viewSurfaces + k;
-
-                               if (*mark == j)
-                                       *view = -(mergedSurfIndex + 1);
-                       }
-               }
-
-               mergedSurfIndex++;
-               mergedSurf++;
-       }
-
-       endTime = ri.Milliseconds();
-
-       ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged 
in %5.2f seconds\n", 
-               numWorldSurfaces, numMergedSurfaces, numUnmergedSurfaces, 
(endTime - startTime) / 1000.0f);
-
-       // reset viewcounts
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               s_worldData.surfacesViewCount[i] = -1;
-       }
-}
-
 void R_CalcVertexLightDirs( void )
 {
        int i, k;
@@ -3945,10 +3791,6 @@ void RE_LoadWorldMap( const char *name ) {
 
        // create static VBOS from the world
        R_CreateWorldVBOs();
-       if (r_mergeLeafSurfaces->integer)
-       {
-               R_MergeLeafSurfaces();
-       }
 
        s_worldData.dataSize = (byte *)ri.Hunk_Alloc( 0, h_low ) - startMarker;
 
diff --git a/SP/code/rend2/tr_bsp.c b/SP/code/rend2/tr_bsp.c
index 1b9365d..4b616df 100644
--- a/SP/code/rend2/tr_bsp.c
+++ b/SP/code/rend2/tr_bsp.c
@@ -2029,39 +2029,40 @@ static int BSPSurfaceCompare(const void *a, const void 
*b)
        else if(aa->fogIndex > bb->fogIndex)
                return 1;
 
+       // by leaf
+       if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] < 
s_worldData.surfacesViewCount[bb - s_worldData.surfaces])
+               return -1;
+
+       else if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] > 
s_worldData.surfacesViewCount[bb - s_worldData.surfaces])
+               return 1;
+
+       // by surface number
+       if (aa < bb)
+               return -1;
+
+       else if (aa > bb)
+               return 1;
+
        return 0;
 }
 
 
 static void CopyVert(const srfVert_t * in, srfVert_t * out)
 {
-       int             j;
-
-       for(j = 0; j < 3; j++)
-       {
-               out->xyz[j]       = in->xyz[j];
+       VectorCopy(in->xyz,      out->xyz);
 #ifdef USE_VERT_TANGENT_SPACE
-               out->tangent[j]   = in->tangent[j];
-               //out->bitangent[j] = in->bitangent[j];
+       VectorCopy4(in->tangent, out->tangent);
 #endif
-               out->normal[j]    = in->normal[j];
-               out->lightdir[j]  = in->lightdir[j];
-       }
+       VectorCopy(in->normal,   out->normal);
+       VectorCopy(in->lightdir, out->lightdir);
 
-       out->tangent[3] = in->tangent[3];
-
-       for(j = 0; j < 2; j++)
-       {
-               out->st[j] = in->st[j];
-               out->lightmap[j] = in->lightmap[j];
-       }
+       VectorCopy2(in->st,       out->st);
+       VectorCopy2(in->lightmap, out->lightmap);
 
-       for(j = 0; j < 4; j++)
-       {
-               out->vertexColors[j] = in->vertexColors[j];
-       }
+       VectorCopy4(in->vertexColors, out->vertexColors);
 }
 
+
 /*
 ===============
 R_CreateWorldVBOs
@@ -2085,26 +2086,74 @@ static void R_CreateWorldVBOs(void)
        IBO_t *ibo;
 
        int maxVboSize = 4 * 1024 * 1024;
-       int maxIboSize = 4 * 1024 * 1024;
 
        int             startTime, endTime;
 
        startTime = ri.Milliseconds();
 
+       // mark surfaces with best matching leaf, using overlapping bounds
+       // using surfaceViewCount[] as leaf number, and surfacesDlightBits[] as 
coverage * 256
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesViewCount[i] = -1;
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesDlightBits[i] = 0;
+       }
+
+       for (i = s_worldData.numDecisionNodes; i < s_worldData.numnodes; i++)
+       {
+               mnode_t *leaf = s_worldData.nodes + i;
+
+               for (j = leaf->firstmarksurface; j < leaf->firstmarksurface + 
leaf->nummarksurfaces; j++)
+               {
+                       int surfaceNum = s_worldData.marksurfaces[j];
+                       msurface_t *surface = s_worldData.surfaces + surfaceNum;
+                       float coverage = 1.0f;
+                       int iCoverage;
+
+                       for (k = 0; k < 3; k++)
+                       {
+                               float left, right;
+
+                               if (leaf->mins[k] > 
surface->cullinfo.bounds[1][k] || surface->cullinfo.bounds[0][k] > 
leaf->maxs[k])
+                               {
+                                       coverage = 0.0f;
+                                       break;
+                               }
+
+                               left  = MAX(leaf->mins[k], 
surface->cullinfo.bounds[0][k]);
+                               right = MIN(leaf->maxs[k], 
surface->cullinfo.bounds[1][k]);
+
+                               // nudge a bit in case this is an axis aligned 
wall
+                               coverage *= right - left + 1.0f/256.0f;
+                       }
+
+                       iCoverage = coverage * 256;
+
+                       if (iCoverage > 
s_worldData.surfacesDlightBits[surfaceNum])
+                       {
+                               s_worldData.surfacesDlightBits[surfaceNum] = 
iCoverage;
+                               s_worldData.surfacesViewCount[surfaceNum] = i - 
s_worldData.numDecisionNodes;
+                       }
+               }
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+       {
+               s_worldData.surfacesDlightBits[i] = 0;
+       }
+
        // count surfaces
        numSortedSurfaces = 0;
-       for(surface = &s_worldData.surfaces[0]; surface < 
&s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
+       for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + 
s_worldData.numWorldSurfaces; surface++)
        {
                srfBspSurface_t *bspSurf;
                shader_t *shader = surface->shader;
 
-               if (shader->isPortal)
-                       continue;
-
-               if (shader->isSky)
-                       continue;
-
-               if (ShaderRequiresCPUDeforms(shader))
+               if (shader->isPortal || shader->isSky || 
ShaderRequiresCPUDeforms(shader))
                        continue;
 
                // check for this now so we can use srfBspSurface_t* 
universally in the rest of the function
@@ -2123,18 +2172,12 @@ static void R_CreateWorldVBOs(void)
        surfacesSorted = ri.Z_Malloc(numSortedSurfaces * 
sizeof(*surfacesSorted));
 
        j = 0;
-       for(surface = &s_worldData.surfaces[0]; surface < 
&s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
+       for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + 
s_worldData.numWorldSurfaces; surface++)
        {
                srfBspSurface_t *bspSurf;
                shader_t *shader = surface->shader;
 
-               if (shader->isPortal)
-                       continue;
-
-               if (shader->isSky)
-                       continue;
-
-               if (ShaderRequiresCPUDeforms(shader))
+               if (shader->isPortal || shader->isSky || 
ShaderRequiresCPUDeforms(shader))
                        continue;
 
                // check for this now so we can use srfBspSurface_t* 
universally in the rest of the function
@@ -2152,37 +2195,34 @@ static void R_CreateWorldVBOs(void)
        qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), 
BSPSurfaceCompare);
 
        k = 0;
-       for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
&surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf)
+       for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + 
numSortedSurfaces; firstSurf = lastSurf)
        {
-               int currVboSize, currIboSize;
+               int currVboSize;
 
-               // Find range of surfaces to merge by:
-               // - Collecting a number of surfaces which fit under 
maxVboSize/maxIboSize, or
-               // - All the surfaces with a single shader which go over 
maxVboSize/maxIboSize
-               currVboSize = currIboSize = 0;
-               while (currVboSize < maxVboSize && currIboSize < maxIboSize && 
lastSurf < &surfacesSorted[numSortedSurfaces])
+               // Find range of surfaces to place in a vbo/ibo by:
+               // - Collecting a number of surfaces which fit under 
maxVboSize, or
+               // - All the surfaces with a single shader which go over 
maxVboSize
+               currVboSize = 0;
+               while (currVboSize < maxVboSize && lastSurf < surfacesSorted + 
numSortedSurfaces)
                {
-                       int addVboSize, addIboSize, currShaderIndex;
+                       int addVboSize, currShaderIndex;
 
-                       addVboSize = addIboSize = 0;
+                       addVboSize = 0;
                        currShaderIndex = (*lastSurf)->shader->sortedIndex;
 
-                       for(currSurf = lastSurf; currSurf < 
&surfacesSorted[numSortedSurfaces] && (*currSurf)->shader->sortedIndex == 
currShaderIndex; currSurf++)
+                       for(currSurf = lastSurf; currSurf < surfacesSorted + 
numSortedSurfaces && (*currSurf)->shader->sortedIndex == currShaderIndex; 
currSurf++)
                        {
                                srfBspSurface_t *bspSurf = (srfBspSurface_t *) 
(*currSurf)->data;
 
                                addVboSize += bspSurf->numVerts * 
sizeof(srfVert_t);
-                               addIboSize += bspSurf->numIndexes * 
sizeof(glIndex_t);
                        }
 
-                       if ((currVboSize != 0 && addVboSize + currVboSize > 
maxVboSize)
-                        || (currIboSize != 0 && addIboSize + currIboSize > 
maxIboSize))
+                       if (currVboSize != 0 && addVboSize + currVboSize > 
maxVboSize)
                                break;
 
                        lastSurf = currSurf;
 
                        currVboSize += addVboSize;
-                       currIboSize += addIboSize;
                }
 
                // count verts/indexes/surfaces
@@ -2258,6 +2298,141 @@ static void R_CreateWorldVBOs(void)
                k++;
        }
 
+       if (r_mergeLeafSurfaces->integer)
+       {
+               msurface_t *mergedSurf;
+
+               // count merged surfaces
+               int numMergedSurfaces = 0, numUnmergedSurfaces = 0;
+               for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
+               {
+                       for (lastSurf++ ; lastSurf < surfacesSorted + 
numSortedSurfaces; lastSurf++)
+                       {
+                               int lastSurfLeafIndex, firstSurfLeafIndex;
+
+                               if ((*lastSurf)->shader         != 
(*firstSurf)->shader
+                                || (*lastSurf)->fogIndex       != 
(*firstSurf)->fogIndex
+                                || (*lastSurf)->cubemapIndex   != 
(*firstSurf)->cubemapIndex)
+                                       break;
+
+                               lastSurfLeafIndex  = 
s_worldData.surfacesViewCount[*lastSurf  - s_worldData.surfaces];
+                               firstSurfLeafIndex = 
s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces];
+
+                               if (lastSurfLeafIndex != firstSurfLeafIndex)
+                                       break;
+                       }
+
+                       // don't merge single surfaces
+                       if (firstSurf + 1 == lastSurf)
+                       {
+                               numUnmergedSurfaces++;
+                               continue;
+                       }
+
+                       numMergedSurfaces++;
+               }
+
+               // Allocate merged surfaces
+               s_worldData.mergedSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low);
+               s_worldData.mergedSurfacesViewCount = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, 
h_low);
+               s_worldData.mergedSurfacesDlightBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * 
numMergedSurfaces, h_low);
+               s_worldData.mergedSurfacesPshadowBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * 
numMergedSurfaces, h_low);
+               s_worldData.numMergedSurfaces = numMergedSurfaces;
+               
+               // view surfaces are like mark surfaces, except negative ones 
represent merged surfaces
+               // -1 represents 0, -2 represents 1, and so on
+               s_worldData.viewSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, 
h_low);
+
+               // copy view surfaces into mark surfaces
+               for (i = 0; i < s_worldData.nummarksurfaces; i++)
+               {
+                       s_worldData.viewSurfaces[i] = 
s_worldData.marksurfaces[i];
+               }
+
+               // actually merge surfaces
+               mergedSurf = s_worldData.mergedSurfaces;
+               for(firstSurf = lastSurf = surfacesSorted; firstSurf < 
surfacesSorted + numSortedSurfaces; firstSurf = lastSurf)
+               {
+                       srfBspSurface_t *bspSurf, *vboSurf;
+
+                       for ( lastSurf++ ; lastSurf < surfacesSorted + 
numSortedSurfaces; lastSurf++)
+                       {
+                               int lastSurfLeafIndex, firstSurfLeafIndex;
+
+                               if ((*lastSurf)->shader         != 
(*firstSurf)->shader
+                                || (*lastSurf)->fogIndex       != 
(*firstSurf)->fogIndex
+                                || (*lastSurf)->cubemapIndex   != 
(*firstSurf)->cubemapIndex)
+                                       break;
+
+                               lastSurfLeafIndex  = 
s_worldData.surfacesViewCount[*lastSurf  - s_worldData.surfaces];
+                               firstSurfLeafIndex = 
s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces];
+
+                               if (lastSurfLeafIndex != firstSurfLeafIndex)
+                                       break;
+                       }
+
+                       // don't merge single surfaces
+                       if (firstSurf + 1 == lastSurf)
+                               continue;
+
+                       bspSurf = (srfBspSurface_t *)(*firstSurf)->data;
+
+                       vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
+                       memset(vboSurf, 0, sizeof(*vboSurf));
+                       vboSurf->surfaceType = SF_VBO_MESH;
+
+                       vboSurf->vbo = bspSurf->vbo;
+                       vboSurf->ibo = bspSurf->ibo;
+
+                       vboSurf->firstIndex = bspSurf->firstIndex;
+                       vboSurf->minIndex = bspSurf->minIndex;
+                       vboSurf->maxIndex = bspSurf->maxIndex;
+
+                       ClearBounds(vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                       {
+                               srfBspSurface_t *currBspSurf = (srfBspSurface_t 
*)(*currSurf)->data;
+
+                               vboSurf->numVerts   += currBspSurf->numVerts;
+                               vboSurf->numIndexes += currBspSurf->numIndexes;
+                               vboSurf->minIndex = MIN(vboSurf->minIndex, 
currBspSurf->minIndex);
+                               vboSurf->maxIndex = MAX(vboSurf->maxIndex, 
currBspSurf->maxIndex);
+                               
AddPointToBounds((*currSurf)->cullinfo.bounds[0], vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                               
AddPointToBounds((*currSurf)->cullinfo.bounds[1], vboSurf->cullBounds[0], 
vboSurf->cullBounds[1]);
+                       }
+
+                       VectorCopy(vboSurf->cullBounds[0], 
mergedSurf->cullinfo.bounds[0]);
+                       VectorCopy(vboSurf->cullBounds[1], 
mergedSurf->cullinfo.bounds[1]);
+
+                       mergedSurf->cullinfo.type =  CULLINFO_BOX;
+                       mergedSurf->data          =  (surfaceType_t *)vboSurf;
+                       mergedSurf->fogIndex      =  (*firstSurf)->fogIndex;
+                       mergedSurf->cubemapIndex  =  (*firstSurf)->cubemapIndex;
+                       mergedSurf->shader        =  (*firstSurf)->shader;
+
+                       // redirect view surfaces to this surf
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                               s_worldData.surfacesViewCount[*currSurf - 
s_worldData.surfaces] = -2;
+
+                       for (k = 0; k < s_worldData.nummarksurfaces; k++)
+                       {
+                               if 
(s_worldData.surfacesViewCount[s_worldData.marksurfaces[k]] == -2)
+                                       s_worldData.viewSurfaces[k] = 
-((int)(mergedSurf - s_worldData.mergedSurfaces) + 1);
+                       }
+
+                       for (currSurf = firstSurf; currSurf < lastSurf; 
currSurf++)
+                               s_worldData.surfacesViewCount[*currSurf - 
s_worldData.surfaces] = -1;
+
+                       mergedSurf++;
+               }
+
+               ri.Printf(PRINT_ALL, "Processed %d mergeable surfaces into %d 
merged, %d unmerged\n", 
+                       numSortedSurfaces, numMergedSurfaces, 
numUnmergedSurfaces);
+       }
+
+       for (i = 0; i < s_worldData.numWorldSurfaces; i++)
+               s_worldData.surfacesViewCount[i] = -1;
+
        ri.Free(surfacesSorted);
 
        endTime = ri.Milliseconds();
@@ -3252,334 +3427,6 @@ void R_RenderAllCubemaps(void)
 }
 
 
-/*
-=================
-R_MergeLeafSurfaces
-
-Merges surfaces that share a common leaf
-=================
-*/
-void R_MergeLeafSurfaces(void)
-{
-       int i, j, k;
-       int numWorldSurfaces;
-       int mergedSurfIndex;
-       int numMergedSurfaces;
-       int numUnmergedSurfaces;
-       VBO_t *vbo;
-       IBO_t *ibo;
-
-       msurface_t *mergedSurf;
-
-       glIndex_t *iboIndexes, *outIboIndexes;
-       int numIboIndexes;
-
-       int startTime, endTime;
-
-       startTime = ri.Milliseconds();
-
-       numWorldSurfaces = s_worldData.numWorldSurfaces;
-
-       // use viewcount to keep track of mergers
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               s_worldData.surfacesViewCount[i] = -1;
-       }
-
-       // mark matching surfaces
-       for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; 
i++)
-       {
-               mnode_t *leaf = s_worldData.nodes + 
s_worldData.numDecisionNodes + i;
-
-               for (j = 0; j < leaf->nummarksurfaces; j++)
-               {
-                       msurface_t *surf1;
-                       shader_t *shader1;
-                       int fogIndex1;
-                       int cubemapIndex1;
-                       int surfNum1;
-
-                       surfNum1 = *(s_worldData.marksurfaces + 
leaf->firstmarksurface + j);
-
-                       if (s_worldData.surfacesViewCount[surfNum1] != -1)
-                               continue;
-
-                       surf1 = s_worldData.surfaces + surfNum1;
-
-                       if ((*surf1->data != SF_GRID) && (*surf1->data != 
SF_TRIANGLES) && (*surf1->data != SF_FACE))
-                               continue;
-
-                       shader1 = surf1->shader;
-
-                       if(shader1->isSky)
-                               continue;
-
-                       if(shader1->isPortal)
-                               continue;
-
-                       if(ShaderRequiresCPUDeforms(shader1))
-                               continue;
-
-                       fogIndex1 = surf1->fogIndex;
-                       cubemapIndex1 = surf1->cubemapIndex;
-
-                       s_worldData.surfacesViewCount[surfNum1] = surfNum1;
-
-                       for (k = j + 1; k < leaf->nummarksurfaces; k++)
-                       {
-                               msurface_t *surf2;
-                               shader_t *shader2;
-                               int fogIndex2;
-                               int cubemapIndex2;
-                               int surfNum2;
-
-                               surfNum2 = *(s_worldData.marksurfaces + 
leaf->firstmarksurface + k);
-
-                               if (s_worldData.surfacesViewCount[surfNum2] != 
-1)
-                                       continue;
-                               
-                               surf2 = s_worldData.surfaces + surfNum2;
-
-                               if ((*surf2->data != SF_GRID) && (*surf2->data 
!= SF_TRIANGLES) && (*surf2->data != SF_FACE))
-                                       continue;
-
-                               shader2 = surf2->shader;
-
-                               if (shader1 != shader2)
-                                       continue;
-
-                               fogIndex2 = surf2->fogIndex;
-
-                               if (fogIndex1 != fogIndex2)
-                                       continue;
-
-                               cubemapIndex2 = surf2->cubemapIndex;
-
-                               if (cubemapIndex1 != cubemapIndex2)
-                                       continue;
-
-                               s_worldData.surfacesViewCount[surfNum2] = 
surfNum1;
-                       }
-               }
-       }
-
-       // don't add surfaces that don't merge to any others to the merged list
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               qboolean merges = qfalse;
-
-               if (s_worldData.surfacesViewCount[i] != i)
-                       continue;
-
-               for (j = 0; j < numWorldSurfaces; j++)
-               {
-                       if (j == i)
-                               continue;
-
-                       if (s_worldData.surfacesViewCount[j] == i)
-                       {
-                               merges = qtrue;
-                               break;
-                       }
-               }
-
-               if (!merges)
-                       s_worldData.surfacesViewCount[i] = -1;
-       }       
-
-       // count merged/unmerged surfaces
-       numMergedSurfaces = 0;
-       numUnmergedSurfaces = 0;
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               if (s_worldData.surfacesViewCount[i] == i)
-               {
-                       numMergedSurfaces++;
-               }
-               else if (s_worldData.surfacesViewCount[i] == -1)
-               {
-                       numUnmergedSurfaces++;
-               }
-       }
-
-       // Allocate merged surfaces
-       s_worldData.mergedSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low);
-       s_worldData.mergedSurfacesViewCount = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, 
h_low);
-       s_worldData.mergedSurfacesDlightBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * 
numMergedSurfaces, h_low);
-       s_worldData.mergedSurfacesPshadowBits = 
ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * 
numMergedSurfaces, h_low);
-       s_worldData.numMergedSurfaces = numMergedSurfaces;
-       
-       // view surfaces are like mark surfaces, except negative ones represent 
merged surfaces
-       // -1 represents 0, -2 represents 1, and so on
-       s_worldData.viewSurfaces = 
ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, 
h_low);
-
-       // copy view surfaces into mark surfaces
-       for (i = 0; i < s_worldData.nummarksurfaces; i++)
-       {
-               s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
-       }
-
-       // need to be synched here
-       R_IssuePendingRenderCommands();
-
-       // actually merge surfaces
-       mergedSurfIndex = 0;
-       mergedSurf = s_worldData.mergedSurfaces;
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               msurface_t *surf1;
-
-               vec3_t bounds[2];
-
-               int numSurfsToMerge;
-               int numIndexes;
-               int numVerts;
-               int firstIndex;
-
-               srfBspSurface_t *vboSurf;
-
-               if (s_worldData.surfacesViewCount[i] != i)
-                       continue;
-
-               surf1 = s_worldData.surfaces + i;
-
-               // retrieve vbo
-               vbo = ((srfBspSurface_t *)(surf1->data))->vbo;
-
-               // count verts, indexes, and surfaces
-               numSurfsToMerge = 0;
-               numIndexes = 0;
-               numVerts = 0;
-               for (j = i; j < numWorldSurfaces; j++)
-               {
-                       msurface_t *surf2;
-                       srfBspSurface_t *bspSurf;
-
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       surf2 = s_worldData.surfaces + j;
-
-                       bspSurf = (srfBspSurface_t *) surf2->data;
-                       numIndexes += bspSurf->numIndexes;
-                       numVerts += bspSurf->numVerts;
-                       numSurfsToMerge++;
-               }
-
-               if (numVerts == 0 || numIndexes == 0 || numSurfsToMerge < 2)
-               {
-                       continue;
-               }
-
-               // create ibo
-               ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
-               memset(ibo, 0, sizeof(*ibo));
-               Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", 
tr.numIBOs++), sizeof(ibo->name));
-               numIboIndexes = 0;
-
-               // allocate indexes
-               iboIndexes = outIboIndexes = ri.Z_Malloc(numIndexes * 
sizeof(*outIboIndexes));
-
-               // Merge surfaces (indexes) and calculate bounds
-               ClearBounds(bounds[0], bounds[1]);
-               firstIndex = numIboIndexes;
-               for (j = i; j < numWorldSurfaces; j++)
-               {
-                       msurface_t *surf2;
-                       srfBspSurface_t *bspSurf;
-
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       surf2 = s_worldData.surfaces + j;
-
-                       AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], 
bounds[1]);
-                       AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], 
bounds[1]);
-
-                       bspSurf = (srfBspSurface_t *) surf2->data;
-                       for (k = 0; k < bspSurf->numIndexes; k++)
-                       {
-                               *outIboIndexes++ = bspSurf->indexes[k] + 
bspSurf->firstVert;
-                               numIboIndexes++;
-                       }
-                       break;
-               }
-
-               vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
-               memset(vboSurf, 0, sizeof(*vboSurf));
-               vboSurf->surfaceType = SF_VBO_MESH;
-
-               vboSurf->vbo = vbo;
-               vboSurf->ibo = ibo;
-
-               vboSurf->numIndexes = numIndexes;
-               vboSurf->numVerts = numVerts;
-               vboSurf->firstIndex = firstIndex;
-
-               vboSurf->minIndex = *(iboIndexes + firstIndex);
-               vboSurf->maxIndex = *(iboIndexes + firstIndex);
-
-               for (j = 0; j < numIndexes; j++)
-               {
-                       vboSurf->minIndex = MIN(vboSurf->minIndex, *(iboIndexes 
+ firstIndex + j));
-                       vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes 
+ firstIndex + j));
-               }
-
-               VectorCopy(bounds[0], vboSurf->cullBounds[0]);
-               VectorCopy(bounds[1], vboSurf->cullBounds[1]);
-
-               VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]);
-               VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]);
-
-               mergedSurf->cullinfo.type = CULLINFO_BOX;
-               mergedSurf->data          = (surfaceType_t *)vboSurf;
-               mergedSurf->fogIndex      = surf1->fogIndex;
-               mergedSurf->cubemapIndex  = surf1->cubemapIndex;
-               mergedSurf->shader        = surf1->shader;
-
-               // finish up the ibo
-               qglGenBuffersARB(1, &ibo->indexesVBO);
-
-               R_BindIBO(ibo);
-               qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * 
sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
-               R_BindNullIBO();
-
-               GL_CheckErrors();
-
-               ri.Free(iboIndexes);
-
-               // redirect view surfaces to this surf
-               for (j = 0; j < numWorldSurfaces; j++)
-               {
-                       if (s_worldData.surfacesViewCount[j] != i)
-                               continue;
-
-                       for (k = 0; k < s_worldData.nummarksurfaces; k++)
-                       {
-                               int *mark = s_worldData.marksurfaces + k;
-                               int *view = s_worldData.viewSurfaces + k;
-
-                               if (*mark == j)
-                                       *view = -(mergedSurfIndex + 1);
-                       }
-               }
-
-               mergedSurfIndex++;
-               mergedSurf++;
-       }
-
-       endTime = ri.Milliseconds();
-
-       ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged 
in %5.2f seconds\n", 
-               numWorldSurfaces, numMergedSurfaces, numUnmergedSurfaces, 
(endTime - startTime) / 1000.0f);
-
-       // reset viewcounts
-       for (i = 0; i < numWorldSurfaces; i++)
-       {
-               s_worldData.surfacesViewCount[i] = -1;
-       }
-}
-
 void R_CalcVertexLightDirs( void )
 {
        int i, k;
@@ -3932,10 +3779,6 @@ void RE_LoadWorldMap( const char *name ) {
 
        // create static VBOS from the world
        R_CreateWorldVBOs();
-       if (r_mergeLeafSurfaces->integer)
-       {
-               R_MergeLeafSurfaces();
-       }
 
        s_worldData.dataSize = (byte *)ri.Hunk_Alloc( 0, h_low ) - startMarker;
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/iortcw.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to