00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "r_local.h"
00028 #include "r_error.h"
00029 #include "r_entity.h"
00030 #include "r_lightmap.h"
00031
00032 lightmaps_t r_lightmaps;
00033
00034 static void R_UploadLightmapBlock (void)
00035 {
00036 const int samples = r_config.gl_compressed_solid_format ? r_config.gl_compressed_solid_format : r_config.gl_solid_format;
00037 if (r_lightmaps.lightmap_texnum == MAX_GL_LIGHTMAPS) {
00038 Com_Printf("R_UploadLightmapBlock: MAX_GL_LIGHTMAPS reached.\n");
00039 return;
00040 }
00041
00042 R_BindTexture(r_lightmaps.lightmap_texnum);
00043
00044 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00045 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00046
00047 glTexImage2D(GL_TEXTURE_2D, 0, samples, r_lightmaps.size, r_lightmaps.size,
00048 0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.sample_buffer);
00049
00050 R_CheckError();
00051
00052 r_lightmaps.lightmap_texnum++;
00053
00054 if (r_lightmaps.deluxemap_texnum == MAX_GL_DELUXEMAPS) {
00055 Com_Printf("R_UploadLightmapBlock: MAX_GL_DELUXEMAPS reached.\n");
00056 return;
00057 }
00058
00059 R_BindTexture(r_lightmaps.deluxemap_texnum);
00060
00061 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00062 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00063
00064 glTexImage2D(GL_TEXTURE_2D, 0, samples, r_lightmaps.size, r_lightmaps.size,
00065 0, GL_RGB, GL_UNSIGNED_BYTE, r_lightmaps.direction_buffer);
00066
00067 r_lightmaps.deluxemap_texnum++;
00068
00069
00070 memset(r_lightmaps.allocated, 0, r_lightmaps.size * sizeof(unsigned));
00071 memset(r_lightmaps.sample_buffer, 0, r_lightmaps.size * r_lightmaps.size * sizeof(unsigned));
00072 memset(r_lightmaps.direction_buffer, 0, r_lightmaps.size * r_lightmaps.size * sizeof(unsigned));
00073 }
00074
00078 static qboolean R_AllocLightmapBlock (int w, int h, int *x, int *y)
00079 {
00080 int i, j;
00081 int best;
00082
00083 best = r_lightmaps.size;
00084
00085 for (i = 0; i < r_lightmaps.size - w; i++) {
00086 int best2 = 0;
00087
00088 for (j = 0; j < w; j++) {
00089 if (r_lightmaps.allocated[i + j] >= best)
00090 break;
00091 if (r_lightmaps.allocated[i + j] > best2)
00092 best2 = r_lightmaps.allocated[i + j];
00093 }
00094
00095 if (j == w) {
00096 *x = i;
00097 *y = best = best2;
00098 }
00099 }
00100
00101 if (best + h > r_lightmaps.size)
00102 return qfalse;
00103
00104 for (i = 0; i < w; i++)
00105 r_lightmaps.allocated[*x + i] = best + h;
00106
00107 return qtrue;
00108 }
00109
00114 static void R_BuildDefaultLightmap (mBspSurface_t *surf, byte *sout, byte *dout, int stride)
00115 {
00116 int i, j;
00117
00118 const int smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
00119 const int tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
00120
00121
00122 stride -= (smax * LIGHTMAP_BLOCK_BYTES);
00123
00124 for (i = 0; i < tmax; i++, sout += stride, dout += stride) {
00125 for (j = 0; j < smax; j++) {
00126 sout[0] = 255;
00127 sout[1] = 255;
00128 sout[2] = 255;
00129
00130 sout += LIGHTMAP_BLOCK_BYTES;
00131
00132 dout[0] = 127;
00133 dout[1] = 127;
00134 dout[2] = 255;
00135
00136 dout += DELUXEMAP_BLOCK_BYTES;
00137 }
00138 }
00139
00140 Vector4Set(surf->color, 1.0, 1.0, 1.0, 1.0);
00141 }
00142
00148 static void R_BuildLightmap (mBspSurface_t *surf, byte *sout, byte *dout, int stride)
00149 {
00150 unsigned int i, j;
00151 byte *lightmap, *lm, *l, *deluxemap, *dm;
00152
00153 const int smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
00154 const int tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
00155 const int size = smax * tmax;
00156 stride -= (smax * LIGHTMAP_BLOCK_BYTES);
00157
00158 lightmap = (byte *)Mem_PoolAlloc(size * LIGHTMAP_BLOCK_BYTES, vid_lightPool, 0);
00159 lm = lightmap;
00160
00161 deluxemap = (byte *)Mem_PoolAlloc(size * DELUXEMAP_BLOCK_BYTES, vid_lightPool, 0);
00162 dm = deluxemap;
00163
00164
00165 for (i = j = 0; i < size; i++, lm += LIGHTMAP_BLOCK_BYTES, dm += DELUXEMAP_BLOCK_BYTES) {
00166 lm[0] = surf->samples[j++];
00167 lm[1] = surf->samples[j++];
00168 lm[2] = surf->samples[j++];
00169
00170
00171 dm[0] = surf->samples[j++];
00172 dm[1] = surf->samples[j++];
00173 dm[2] = surf->samples[j++];
00174 }
00175
00176
00177 R_FilterTexture(lightmap, smax, tmax, it_lightmap, LIGHTMAP_BLOCK_BYTES);
00178
00179 if (surf->texinfo->flags & (SURF_BLEND33 | SURF_ALPHATEST))
00180 surf->color[3] = 0.25;
00181 else if (surf->texinfo->flags & SURF_BLEND66)
00182 surf->color[3] = 0.50;
00183 else
00184 surf->color[3] = 1.0;
00185
00186
00187 if (r_soften->integer && size > 128)
00188 for (i = 0; i < 4; i++) {
00189 R_SoftenTexture(lightmap, smax, tmax, LIGHTMAP_BLOCK_BYTES);
00190 R_SoftenTexture(deluxemap, smax, tmax, DELUXEMAP_BLOCK_BYTES);
00191 }
00192
00193
00194
00195
00196 surf->lightmap = (byte *)Mem_PoolAlloc(size * LIGHTMAP_BYTES, vid_lightPool, 0);
00197 l = surf->lightmap;
00198 lm = lightmap;
00199 dm = deluxemap;
00200
00201 for (i = 0; i < tmax; i++, sout += stride, dout += stride) {
00202 for (j = 0; j < smax; j++) {
00203
00204 sout[0] = lm[0];
00205 sout[1] = lm[1];
00206 sout[2] = lm[2];
00207 sout += LIGHTMAP_BLOCK_BYTES;
00208
00209
00210 l[0] = lm[0];
00211 l[1] = lm[1];
00212 l[2] = lm[2];
00213 l += LIGHTMAP_BYTES;
00214
00215 lm += LIGHTMAP_BLOCK_BYTES;
00216
00217
00218 dout[0] = dm[0];
00219 dout[1] = dm[1];
00220 dout[2] = dm[2];
00221 dout += DELUXEMAP_BLOCK_BYTES;
00222
00223 dm += DELUXEMAP_BLOCK_BYTES;
00224 }
00225 }
00226
00227 Mem_Free(lightmap);
00228 Mem_Free(deluxemap);
00229 }
00230
00234 void R_CreateSurfaceLightmap (mBspSurface_t * surf)
00235 {
00236 int smax, tmax;
00237 byte *samples, *directions;
00238
00239 if (!(surf->flags & MSURF_LIGHTMAP))
00240 return;
00241
00242 smax = (surf->stextents[0] / surf->lightmap_scale) + 1;
00243 tmax = (surf->stextents[1] / surf->lightmap_scale) + 1;
00244
00245 if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t)) {
00246
00247 R_UploadLightmapBlock();
00248 if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t))
00249 Com_Error(ERR_DROP, "R_CreateSurfaceLightmap: Consecutive calls to R_AllocLightmapBlock(%d,%d) failed (lightmap_scale: %i, stextends: %f %f)\n",
00250 smax, tmax, surf->lightmap_scale, surf->stextents[0], surf->stextents[1]);
00251 }
00252
00253 surf->lightmap_texnum = r_lightmaps.lightmap_texnum;
00254 surf->deluxemap_texnum = r_lightmaps.deluxemap_texnum;
00255
00256 samples = r_lightmaps.sample_buffer;
00257 samples += (surf->light_t * r_lightmaps.size + surf->light_s) * LIGHTMAP_BLOCK_BYTES;
00258
00259 directions = r_lightmaps.direction_buffer;
00260 directions += (surf->light_t * r_lightmaps.size + surf->light_s) * DELUXEMAP_BLOCK_BYTES;
00261
00262 if (!surf->samples)
00263 R_BuildDefaultLightmap(surf, samples, directions, r_lightmaps.size * LIGHTMAP_BLOCK_BYTES);
00264 else
00265 R_BuildLightmap(surf, samples, directions, r_lightmaps.size * LIGHTMAP_BLOCK_BYTES);
00266 }
00267
00272 void R_BeginBuildingLightmaps (void)
00273 {
00274
00275 r_lightmaps.size = r_maxlightmap->integer;
00276
00277 r_lightmaps.allocated = (unsigned *)Mem_PoolAlloc(r_lightmaps.size *
00278 sizeof(unsigned), vid_lightPool, 0);
00279
00280 r_lightmaps.sample_buffer = (byte *)Mem_PoolAlloc(
00281 r_lightmaps.size * r_lightmaps.size * sizeof(unsigned), vid_lightPool, 0);
00282
00283 r_lightmaps.direction_buffer = (byte *)Mem_PoolAlloc(
00284 r_lightmaps.size * r_lightmaps.size * sizeof(unsigned), vid_lightPool, 0);
00285
00286 r_lightmaps.lightmap_texnum = TEXNUM_LIGHTMAPS;
00287 r_lightmaps.deluxemap_texnum = TEXNUM_DELUXEMAPS;
00288 }
00289
00294 void R_EndBuildingLightmaps (void)
00295 {
00296
00297 R_UploadLightmapBlock();
00298 }
00299
00300
00308 void R_Trace (vec3_t start, vec3_t end, float size, int contentmask)
00309 {
00310 vec3_t mins, maxs;
00311 float frac;
00312 trace_t tr;
00313 int i;
00314
00315 r_locals.tracenum++;
00316
00317 if (r_locals.tracenum > 0xffff)
00318 r_locals.tracenum = 0;
00319
00320 VectorSet(mins, -size, -size, -size);
00321 VectorSet(maxs, size, size, size);
00322
00323 refdef.trace = CM_CompleteBoxTrace(refdef.mapTiles, start, end, mins, maxs, TRACING_ALL_VISIBLE_LEVELS, contentmask, 0);
00324 refdef.traceEntity = NULL;
00325
00326 frac = refdef.trace.fraction;
00327
00328
00329 for (i = 0; i < refdef.numEntities; i++) {
00330 entity_t *ent = R_GetEntity(i);
00331 const model_t *m = ent->model;
00332
00333 if (!m || m->type != mod_bsp_submodel)
00334 continue;
00335
00336 tr = CM_TransformedBoxTrace(&(refdef.mapTiles->mapTiles[m->bsp.maptile]), start, end, mins, maxs, m->bsp.firstnode,
00337 contentmask, 0, ent->origin, ent->angles);
00338
00339 if (tr.fraction < frac) {
00340 refdef.trace = tr;
00341 refdef.traceEntity = ent;
00342
00343 frac = tr.fraction;
00344 }
00345 }
00346
00347 assert(refdef.trace.mapTile >= 0);
00348 assert(refdef.trace.mapTile < r_numMapTiles);
00349 }