lightmaps.c (9328B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "qbsp.h" 23 24 25 /* 26 27 Lightmap allocation has to be done after all flood filling and 28 visible surface determination. 29 30 */ 31 32 int numSortShaders; 33 mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS]; 34 35 36 int allocated[LIGHTMAP_WIDTH]; 37 38 int numLightmaps = 1; 39 int c_exactLightmap; 40 41 42 void PrepareNewLightmap( void ) { 43 memset( allocated, 0, sizeof( allocated ) ); 44 numLightmaps++; 45 } 46 47 /* 48 =============== 49 AllocLMBlock 50 51 returns a texture number and the position inside it 52 =============== 53 */ 54 qboolean AllocLMBlock (int w, int h, int *x, int *y) 55 { 56 int i, j; 57 int best, best2; 58 59 best = LIGHTMAP_HEIGHT; 60 61 for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) { 62 best2 = 0; 63 64 for (j=0 ; j<w ; j++) { 65 if (allocated[i+j] >= best) { 66 break; 67 } 68 if (allocated[i+j] > best2) { 69 best2 = allocated[i+j]; 70 } 71 } 72 if (j == w) { // this is a valid spot 73 *x = i; 74 *y = best = best2; 75 } 76 } 77 78 if (best + h > LIGHTMAP_HEIGHT) { 79 return qfalse; 80 } 81 82 for (i=0 ; i<w ; i++) { 83 allocated[*x + i] = best + h; 84 } 85 86 return qtrue; 87 } 88 89 90 /* 91 =================== 92 AllocateLightmapForPatch 93 =================== 94 */ 95 //#define LIGHTMAP_PATCHSHIFT 96 97 void AllocateLightmapForPatch( mapDrawSurface_t *ds ) { 98 int i, j, k; 99 drawVert_t *verts; 100 int w, h; 101 int x, y; 102 float s, t; 103 mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh; 104 int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize; 105 106 verts = ds->verts; 107 108 mesh.width = ds->patchWidth; 109 mesh.height = ds->patchHeight; 110 mesh.verts = verts; 111 newmesh = SubdivideMesh( mesh, 8, 999 ); 112 113 PutMeshOnCurve( *newmesh ); 114 tempMesh = RemoveLinearMeshColumnsRows( newmesh ); 115 FreeMesh(newmesh); 116 117 ssize = samplesize; 118 if (ds->shaderInfo->lightmapSampleSize) 119 ssize = ds->shaderInfo->lightmapSampleSize; 120 121 #ifdef LIGHTMAP_PATCHSHIFT 122 subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable); 123 #else 124 subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable); 125 #endif 126 127 w = subdividedMesh->width; 128 h = subdividedMesh->height; 129 130 #ifdef LIGHTMAP_PATCHSHIFT 131 w++; 132 h++; 133 #endif 134 135 FreeMesh(subdividedMesh); 136 137 // allocate the lightmap 138 c_exactLightmap += w * h; 139 140 if ( !AllocLMBlock( w, h, &x, &y ) ) { 141 PrepareNewLightmap(); 142 if ( !AllocLMBlock( w, h, &x, &y ) ) { 143 Error("Entity %i, brush %i: Lightmap allocation failed", 144 ds->mapBrush->entitynum, ds->mapBrush->brushnum ); 145 } 146 } 147 148 #ifdef LIGHTMAP_PATCHSHIFT 149 w--; 150 h--; 151 #endif 152 153 // set the lightmap texture coordinates in the drawVerts 154 ds->lightmapNum = numLightmaps - 1; 155 ds->lightmapWidth = w; 156 ds->lightmapHeight = h; 157 ds->lightmapX = x; 158 ds->lightmapY = y; 159 160 for ( i = 0 ; i < ds->patchWidth ; i++ ) { 161 for ( k = 0 ; k < w ; k++ ) { 162 if ( originalWidths[k] >= i ) { 163 break; 164 } 165 } 166 if (k >= w) 167 k = w-1; 168 s = x + k; 169 for ( j = 0 ; j < ds->patchHeight ; j++ ) { 170 for ( k = 0 ; k < h ; k++ ) { 171 if ( originalHeights[k] >= j ) { 172 break; 173 } 174 } 175 if (k >= h) 176 k = h-1; 177 t = y + k; 178 verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH; 179 verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT; 180 } 181 } 182 } 183 184 185 /* 186 =================== 187 AllocateLightmapForSurface 188 =================== 189 */ 190 //#define LIGHTMAP_BLOCK 16 191 void AllocateLightmapForSurface( mapDrawSurface_t *ds ) { 192 vec3_t mins, maxs, size, exactSize, delta; 193 int i; 194 drawVert_t *verts; 195 int w, h; 196 int x, y, ssize; 197 int axis; 198 vec3_t vecs[2]; 199 float s, t; 200 vec3_t origin; 201 plane_t *plane; 202 float d; 203 vec3_t planeNormal; 204 205 if ( ds->patch ) { 206 AllocateLightmapForPatch( ds ); 207 return; 208 } 209 210 ssize = samplesize; 211 if (ds->shaderInfo->lightmapSampleSize) 212 ssize = ds->shaderInfo->lightmapSampleSize; 213 214 plane = &mapplanes[ ds->side->planenum ]; 215 216 // bound the surface 217 ClearBounds( mins, maxs ); 218 verts = ds->verts; 219 for ( i = 0 ; i < ds->numVerts ; i++ ) { 220 AddPointToBounds( verts[i].xyz, mins, maxs ); 221 } 222 223 // round to the lightmap resolution 224 for ( i = 0 ; i < 3 ; i++ ) { 225 exactSize[i] = maxs[i] - mins[i]; 226 mins[i] = ssize * floor( mins[i] / ssize ); 227 maxs[i] = ssize * ceil( maxs[i] / ssize ); 228 size[i] = (maxs[i] - mins[i]) / ssize + 1; 229 } 230 231 // the two largest axis will be the lightmap size 232 memset( vecs, 0, sizeof( vecs ) ); 233 234 planeNormal[0] = fabs( plane->normal[0] ); 235 planeNormal[1] = fabs( plane->normal[1] ); 236 planeNormal[2] = fabs( plane->normal[2] ); 237 238 if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { 239 w = size[1]; 240 h = size[2]; 241 axis = 0; 242 vecs[0][1] = 1.0 / ssize; 243 vecs[1][2] = 1.0 / ssize; 244 } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { 245 w = size[0]; 246 h = size[2]; 247 axis = 1; 248 vecs[0][0] = 1.0 / ssize; 249 vecs[1][2] = 1.0 / ssize; 250 } else { 251 w = size[0]; 252 h = size[1]; 253 axis = 2; 254 vecs[0][0] = 1.0 / ssize; 255 vecs[1][1] = 1.0 / ssize; 256 } 257 258 if ( !plane->normal[axis] ) { 259 Error( "Chose a 0 valued axis" ); 260 } 261 262 if ( w > LIGHTMAP_WIDTH ) { 263 VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] ); 264 w = LIGHTMAP_WIDTH; 265 } 266 267 if ( h > LIGHTMAP_HEIGHT ) { 268 VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] ); 269 h = LIGHTMAP_HEIGHT; 270 } 271 272 c_exactLightmap += w * h; 273 274 if ( !AllocLMBlock( w, h, &x, &y ) ) { 275 PrepareNewLightmap(); 276 if ( !AllocLMBlock( w, h, &x, &y ) ) { 277 Error("Entity %i, brush %i: Lightmap allocation failed", 278 ds->mapBrush->entitynum, ds->mapBrush->brushnum ); 279 } 280 } 281 282 // set the lightmap texture coordinates in the drawVerts 283 ds->lightmapNum = numLightmaps - 1; 284 ds->lightmapWidth = w; 285 ds->lightmapHeight = h; 286 ds->lightmapX = x; 287 ds->lightmapY = y; 288 289 for ( i = 0 ; i < ds->numVerts ; i++ ) { 290 VectorSubtract( verts[i].xyz, mins, delta ); 291 s = DotProduct( delta, vecs[0] ) + x + 0.5; 292 t = DotProduct( delta, vecs[1] ) + y + 0.5; 293 verts[i].lightmap[0] = s / LIGHTMAP_WIDTH; 294 verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT; 295 } 296 297 // calculate the world coordinates of the lightmap samples 298 299 // project mins onto plane to get origin 300 d = DotProduct( mins, plane->normal ) - plane->dist; 301 d /= plane->normal[ axis ]; 302 VectorCopy( mins, origin ); 303 origin[axis] -= d; 304 305 // project stepped lightmap blocks and subtract to get planevecs 306 for ( i = 0 ; i < 2 ; i++ ) { 307 vec3_t normalized; 308 float len; 309 310 len = VectorNormalize( vecs[i], normalized ); 311 VectorScale( normalized, (1.0/len), vecs[i] ); 312 d = DotProduct( vecs[i], plane->normal ); 313 d /= plane->normal[ axis ]; 314 vecs[i][axis] -= d; 315 } 316 317 VectorCopy( origin, ds->lightmapOrigin ); 318 VectorCopy( vecs[0], ds->lightmapVecs[0] ); 319 VectorCopy( vecs[1], ds->lightmapVecs[1] ); 320 VectorCopy( plane->normal, ds->lightmapVecs[2] ); 321 } 322 323 /* 324 =================== 325 AllocateLightmaps 326 =================== 327 */ 328 void AllocateLightmaps( entity_t *e ) { 329 int i, j; 330 mapDrawSurface_t *ds; 331 shaderInfo_t *si; 332 333 qprintf ("--- AllocateLightmaps ---\n"); 334 335 336 // sort all surfaces by shader so common shaders will usually 337 // be in the same lightmap 338 numSortShaders = 0; 339 340 for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { 341 ds = &mapDrawSurfs[i]; 342 if ( !ds->numVerts ) { 343 continue; // leftover from a surface subdivision 344 } 345 if ( ds->miscModel ) { 346 continue; 347 } 348 if ( !ds->patch ) { 349 VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] ); 350 } 351 352 // search for this shader 353 for ( j = 0 ; j < numSortShaders ; j++ ) { 354 if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) { 355 ds->nextOnShader = surfsOnShader[j]; 356 surfsOnShader[j] = ds; 357 break; 358 } 359 } 360 if ( j == numSortShaders ) { 361 if ( numSortShaders >= MAX_MAP_SHADERS ) { 362 Error( "MAX_MAP_SHADERS" ); 363 } 364 surfsOnShader[j] = ds; 365 numSortShaders++; 366 } 367 } 368 qprintf( "%5i unique shaders\n", numSortShaders ); 369 370 // for each shader, allocate lightmaps for each surface 371 372 // numLightmaps = 0; 373 // PrepareNewLightmap(); 374 375 for ( i = 0 ; i < numSortShaders ; i++ ) { 376 si = surfsOnShader[i]->shaderInfo; 377 378 for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) { 379 // some surfaces don't need lightmaps allocated for them 380 if ( si->surfaceFlags & SURF_NOLIGHTMAP ) { 381 ds->lightmapNum = -1; 382 } else if ( si->surfaceFlags & SURF_POINTLIGHT ) { 383 ds->lightmapNum = -3; 384 } else { 385 AllocateLightmapForSurface( ds ); 386 } 387 } 388 } 389 390 qprintf( "%7i exact lightmap texels\n", c_exactLightmap ); 391 qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT ); 392 } 393 394 395