00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "qbsp.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 int numSortShaders;
00033 mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS];
00034
00035
00036 int allocated[LIGHTMAP_WIDTH];
00037
00038 int numLightmaps = 1;
00039 int c_exactLightmap;
00040
00041
00042 void PrepareNewLightmap( void ) {
00043 memset( allocated, 0, sizeof( allocated ) );
00044 numLightmaps++;
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054 qboolean AllocLMBlock (int w, int h, int *x, int *y)
00055 {
00056 int i, j;
00057 int best, best2;
00058
00059 best = LIGHTMAP_HEIGHT;
00060
00061 for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
00062 best2 = 0;
00063
00064 for (j=0 ; j<w ; j++) {
00065 if (allocated[i+j] >= best) {
00066 break;
00067 }
00068 if (allocated[i+j] > best2) {
00069 best2 = allocated[i+j];
00070 }
00071 }
00072 if (j == w) {
00073 *x = i;
00074 *y = best = best2;
00075 }
00076 }
00077
00078 if (best + h > LIGHTMAP_HEIGHT) {
00079 return qfalse;
00080 }
00081
00082 for (i=0 ; i<w ; i++) {
00083 allocated[*x + i] = best + h;
00084 }
00085
00086 return qtrue;
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
00098 int i, j, k;
00099 drawVert_t *verts;
00100 int w, h;
00101 int x, y;
00102 float s, t;
00103 mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh;
00104 int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
00105
00106 verts = ds->verts;
00107
00108 mesh.width = ds->patchWidth;
00109 mesh.height = ds->patchHeight;
00110 mesh.verts = verts;
00111 newmesh = SubdivideMesh( mesh, 8, 999 );
00112
00113 PutMeshOnCurve( *newmesh );
00114 tempMesh = RemoveLinearMeshColumnsRows( newmesh );
00115 FreeMesh(newmesh);
00116
00117 ssize = samplesize;
00118 if (ds->shaderInfo->lightmapSampleSize)
00119 ssize = ds->shaderInfo->lightmapSampleSize;
00120
00121 #ifdef LIGHTMAP_PATCHSHIFT
00122 subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
00123 #else
00124 subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
00125 #endif
00126
00127 w = subdividedMesh->width;
00128 h = subdividedMesh->height;
00129
00130 #ifdef LIGHTMAP_PATCHSHIFT
00131 w++;
00132 h++;
00133 #endif
00134
00135 FreeMesh(subdividedMesh);
00136
00137
00138 c_exactLightmap += w * h;
00139
00140 if ( !AllocLMBlock( w, h, &x, &y ) ) {
00141 PrepareNewLightmap();
00142 if ( !AllocLMBlock( w, h, &x, &y ) ) {
00143 Error("Entity %i, brush %i: Lightmap allocation failed",
00144 ds->mapBrush->entitynum, ds->mapBrush->brushnum );
00145 }
00146 }
00147
00148 #ifdef LIGHTMAP_PATCHSHIFT
00149 w--;
00150 h--;
00151 #endif
00152
00153
00154 ds->lightmapNum = numLightmaps - 1;
00155 ds->lightmapWidth = w;
00156 ds->lightmapHeight = h;
00157 ds->lightmapX = x;
00158 ds->lightmapY = y;
00159
00160 for ( i = 0 ; i < ds->patchWidth ; i++ ) {
00161 for ( k = 0 ; k < w ; k++ ) {
00162 if ( originalWidths[k] >= i ) {
00163 break;
00164 }
00165 }
00166 if (k >= w)
00167 k = w-1;
00168 s = x + k;
00169 for ( j = 0 ; j < ds->patchHeight ; j++ ) {
00170 for ( k = 0 ; k < h ; k++ ) {
00171 if ( originalHeights[k] >= j ) {
00172 break;
00173 }
00174 }
00175 if (k >= h)
00176 k = h-1;
00177 t = y + k;
00178 verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
00179 verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
00180 }
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191 void AllocateLightmapForSurface( mapDrawSurface_t *ds ) {
00192 vec3_t mins, maxs, size, exactSize, delta;
00193 int i;
00194 drawVert_t *verts;
00195 int w, h;
00196 int x, y, ssize;
00197 int axis;
00198 vec3_t vecs[2];
00199 float s, t;
00200 vec3_t origin;
00201 plane_t *plane;
00202 float d;
00203 vec3_t planeNormal;
00204
00205 if ( ds->patch ) {
00206 AllocateLightmapForPatch( ds );
00207 return;
00208 }
00209
00210 ssize = samplesize;
00211 if (ds->shaderInfo->lightmapSampleSize)
00212 ssize = ds->shaderInfo->lightmapSampleSize;
00213
00214 plane = &mapplanes[ ds->side->planenum ];
00215
00216
00217 ClearBounds( mins, maxs );
00218 verts = ds->verts;
00219 for ( i = 0 ; i < ds->numVerts ; i++ ) {
00220 AddPointToBounds( verts[i].xyz, mins, maxs );
00221 }
00222
00223
00224 for ( i = 0 ; i < 3 ; i++ ) {
00225 exactSize[i] = maxs[i] - mins[i];
00226 mins[i] = ssize * floor( mins[i] / ssize );
00227 maxs[i] = ssize * ceil( maxs[i] / ssize );
00228 size[i] = (maxs[i] - mins[i]) / ssize + 1;
00229 }
00230
00231
00232 memset( vecs, 0, sizeof( vecs ) );
00233
00234 planeNormal[0] = fabs( plane->normal[0] );
00235 planeNormal[1] = fabs( plane->normal[1] );
00236 planeNormal[2] = fabs( plane->normal[2] );
00237
00238 if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
00239 w = size[1];
00240 h = size[2];
00241 axis = 0;
00242 vecs[0][1] = 1.0 / ssize;
00243 vecs[1][2] = 1.0 / ssize;
00244 } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
00245 w = size[0];
00246 h = size[2];
00247 axis = 1;
00248 vecs[0][0] = 1.0 / ssize;
00249 vecs[1][2] = 1.0 / ssize;
00250 } else {
00251 w = size[0];
00252 h = size[1];
00253 axis = 2;
00254 vecs[0][0] = 1.0 / ssize;
00255 vecs[1][1] = 1.0 / ssize;
00256 }
00257
00258 if ( !plane->normal[axis] ) {
00259 Error( "Chose a 0 valued axis" );
00260 }
00261
00262 if ( w > LIGHTMAP_WIDTH ) {
00263 VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] );
00264 w = LIGHTMAP_WIDTH;
00265 }
00266
00267 if ( h > LIGHTMAP_HEIGHT ) {
00268 VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] );
00269 h = LIGHTMAP_HEIGHT;
00270 }
00271
00272 c_exactLightmap += w * h;
00273
00274 if ( !AllocLMBlock( w, h, &x, &y ) ) {
00275 PrepareNewLightmap();
00276 if ( !AllocLMBlock( w, h, &x, &y ) ) {
00277 Error("Entity %i, brush %i: Lightmap allocation failed",
00278 ds->mapBrush->entitynum, ds->mapBrush->brushnum );
00279 }
00280 }
00281
00282
00283 ds->lightmapNum = numLightmaps - 1;
00284 ds->lightmapWidth = w;
00285 ds->lightmapHeight = h;
00286 ds->lightmapX = x;
00287 ds->lightmapY = y;
00288
00289 for ( i = 0 ; i < ds->numVerts ; i++ ) {
00290 VectorSubtract( verts[i].xyz, mins, delta );
00291 s = DotProduct( delta, vecs[0] ) + x + 0.5;
00292 t = DotProduct( delta, vecs[1] ) + y + 0.5;
00293 verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
00294 verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
00295 }
00296
00297
00298
00299
00300 d = DotProduct( mins, plane->normal ) - plane->dist;
00301 d /= plane->normal[ axis ];
00302 VectorCopy( mins, origin );
00303 origin[axis] -= d;
00304
00305
00306 for ( i = 0 ; i < 2 ; i++ ) {
00307 vec3_t normalized;
00308 float len;
00309
00310 len = VectorNormalize( vecs[i], normalized );
00311 VectorScale( normalized, (1.0/len), vecs[i] );
00312 d = DotProduct( vecs[i], plane->normal );
00313 d /= plane->normal[ axis ];
00314 vecs[i][axis] -= d;
00315 }
00316
00317 VectorCopy( origin, ds->lightmapOrigin );
00318 VectorCopy( vecs[0], ds->lightmapVecs[0] );
00319 VectorCopy( vecs[1], ds->lightmapVecs[1] );
00320 VectorCopy( plane->normal, ds->lightmapVecs[2] );
00321 }
00322
00323
00324
00325
00326
00327
00328 void AllocateLightmaps( entity_t *e ) {
00329 int i, j;
00330 mapDrawSurface_t *ds;
00331 shaderInfo_t *si;
00332
00333 qprintf ("--- AllocateLightmaps ---\n");
00334
00335
00336
00337
00338 numSortShaders = 0;
00339
00340 for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) {
00341 ds = &mapDrawSurfs[i];
00342 if ( !ds->numVerts ) {
00343 continue;
00344 }
00345 if ( ds->miscModel ) {
00346 continue;
00347 }
00348 if ( !ds->patch ) {
00349 VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] );
00350 }
00351
00352
00353 for ( j = 0 ; j < numSortShaders ; j++ ) {
00354 if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) {
00355 ds->nextOnShader = surfsOnShader[j];
00356 surfsOnShader[j] = ds;
00357 break;
00358 }
00359 }
00360 if ( j == numSortShaders ) {
00361 if ( numSortShaders >= MAX_MAP_SHADERS ) {
00362 Error( "MAX_MAP_SHADERS" );
00363 }
00364 surfsOnShader[j] = ds;
00365 numSortShaders++;
00366 }
00367 }
00368 qprintf( "%5i unique shaders\n", numSortShaders );
00369
00370
00371
00372
00373
00374
00375 for ( i = 0 ; i < numSortShaders ; i++ ) {
00376 si = surfsOnShader[i]->shaderInfo;
00377
00378 for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) {
00379
00380 if ( si->surfaceFlags & SURF_NOLIGHTMAP ) {
00381 ds->lightmapNum = -1;
00382 } else if ( si->surfaceFlags & SURF_POINTLIGHT ) {
00383 ds->lightmapNum = -3;
00384 } else {
00385 AllocateLightmapForSurface( ds );
00386 }
00387 }
00388 }
00389
00390 qprintf( "%7i exact lightmap texels\n", c_exactLightmap );
00391 qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT );
00392 }
00393
00394
00395