diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index b658d987..fa045122 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -1808,6 +1808,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; } @@ -1815,31 +1828,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]; - } + VectorCopy(in->normal, out->normal); + VectorCopy(in->lightdir, out->lightdir); - out->tangent[3] = in->tangent[3]; + VectorCopy2(in->st, out->st); + VectorCopy2(in->lightmap, out->lightmap); - for(j = 0; j < 2; j++) - { - out->st[j] = in->st[j]; - out->lightmap[j] = in->lightmap[j]; - } - - for(j = 0; j < 4; j++) - { - out->vertexColors[j] = in->vertexColors[j]; - } + VectorCopy4(in->vertexColors, out->vertexColors); } @@ -1866,26 +1865,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 @@ -1904,18 +1951,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 @@ -1933,37 +1974,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 @@ -2039,6 +2077,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(); @@ -2914,335 +3087,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; @@ -3569,10 +3413,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;