summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/renderergl2/tr_bsp.c610
1 files changed, 225 insertions, 385 deletions
diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c
index acc77c98..1947c0f1 100644
--- a/src/renderergl2/tr_bsp.c
+++ b/src/renderergl2/tr_bsp.c
@@ -1809,6 +1809,19 @@ 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;
}
@@ -1816,31 +1829,17 @@ 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];
- }
-
- out->tangent[3] = in->tangent[3];
+ VectorCopy(in->normal, out->normal);
+ VectorCopy(in->lightdir, out->lightdir);
- 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);
}
@@ -1867,26 +1866,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
@@ -1905,18 +1952,12 @@ static void R_CreateWorldVBOs(void)
surfacesSorted = ri.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
@@ -1934,37 +1975,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
@@ -2040,6 +2078,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();
@@ -2915,335 +3088,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.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;
@@ -3570,10 +3414,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;