*/
void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
{
- int smax, tmax, i, j, size, size3, maps, l;
- unsigned int *bl, scale;
+ int smax, tmax, i, size, size3, maps, l;
+ int *bl, scale;
unsigned char *lightmap, *out, *stain;
- static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
+ static int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
static unsigned char templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
// update cached lighting info
else
{
// clear to no light
- memset(bl, 0, size*3*sizeof(unsigned int));
+ memset(bl, 0, size3*sizeof(*bl));
// add all the lightmaps
if (lightmap)
- {
- bl = intblocklights;
for (maps = 0;maps < MAXLIGHTMAPS && surface->lightmapinfo->styles[maps] != 255;maps++, lightmap += size3)
for (scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[maps]], i = 0;i < size3;i++)
bl[i] += lightmap[i] * scale;
- }
}
stain = surface->lightmapinfo->stainsamples;
// (0 = 0.0, 128 = 1.0, 256 = 2.0)
if (ent->model->brushq1.lightmaprgba)
{
- for (i = 0;i < tmax;i++)
+ for (i = 0;i < size;i++)
{
- for (j = 0;j < smax;j++)
- {
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- *out++ = 255;
- }
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
+ *out++ = 255;
}
}
else
{
- for (i = 0;i < tmax;i++)
+ for (i = 0;i < size;i++)
{
- for (j = 0;j < smax;j++)
- {
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
- }
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
+ l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
}
}
R_UpdateTexture(surface->lightmaptexture, templight, surface->lightmapinfo->lightmaporigin[0], surface->lightmapinfo->lightmaporigin[1], smax, tmax);
+
+ // update the surface's deluxemap if it has one
+ if (surface->deluxemaptexture != r_texture_blanknormalmap)
+ {
+ vec3_t n;
+ unsigned char *normalmap = surface->lightmapinfo->nmapsamples;
+ lightmap = surface->lightmapinfo->samples;
+ // clear to no normalmap
+ bl = intblocklights;
+ memset(bl, 0, size3*sizeof(*bl));
+ // add all the normalmaps
+ if (lightmap && normalmap)
+ {
+ for (maps = 0;maps < MAXLIGHTMAPS && surface->lightmapinfo->styles[maps] != 255;maps++, lightmap += size3, normalmap += size3)
+ {
+ for (scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[maps]], i = 0;i < size;i++)
+ {
+ // add the normalmap with weighting proportional to the style's lightmap intensity
+ l = (int)(VectorLength(lightmap + i*3) * scale);
+ bl[i*3+0] += ((int)normalmap[i*3+0] - 128) * l;
+ bl[i*3+1] += ((int)normalmap[i*3+1] - 128) * l;
+ bl[i*3+2] += ((int)normalmap[i*3+2] - 128) * l;
+ }
+ }
+ }
+ bl = intblocklights;
+ out = templight;
+ // we simply renormalize the weighted normals to get a valid deluxemap
+ if (ent->model->brushq1.lightmaprgba)
+ {
+ for (i = 0;i < size;i++, bl += 3)
+ {
+ VectorCopy(bl, n);
+ VectorNormalize(n);
+ l = (int)(n[0] * 128 + 128);*out++ = bound(0, l, 255);
+ l = (int)(n[1] * 128 + 128);*out++ = bound(0, l, 255);
+ l = (int)(n[2] * 128 + 128);*out++ = bound(0, l, 255);
+ *out++ = 255;
+ }
+ }
+ else
+ {
+ for (i = 0;i < size;i++, bl += 3)
+ {
+ VectorCopy(bl, n);
+ VectorNormalize(n);
+ l = (int)(n[0] * 128 + 128);*out++ = bound(0, l, 255);
+ l = (int)(n[1] * 128 + 128);*out++ = bound(0, l, 255);
+ l = (int)(n[2] * 128 + 128);*out++ = bound(0, l, 255);
+ }
+ }
+ R_UpdateTexture(surface->deluxemaptexture, templight, surface->lightmapinfo->lightmaporigin[0], surface->lightmapinfo->lightmaporigin[1], smax, tmax);
+ }
}
void R_StainNode (mnode_t *node, model_t *model, const vec3_t origin, float radius, const float fcolor[8])
{
int i;
unsigned char *in, *out, *data, d;
- char litfilename[1024];
+ char litfilename[MAX_QPATH];
+ char dlitfilename[MAX_QPATH];
fs_offset_t filesize;
- loadmodel->brushq1.lightdata = NULL;
if (loadmodel->brush.ishlbsp) // LordHavoc: load the colored lighting data straight
{
loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, l->filelen);
// LordHavoc: hope is not lost yet, check for a .lit file to load
strlcpy (litfilename, loadmodel->name, sizeof (litfilename));
FS_StripExtension (litfilename, litfilename, sizeof (litfilename));
+ strlcpy (dlitfilename, litfilename, sizeof (dlitfilename));
strlcat (litfilename, ".lit", sizeof (litfilename));
+ strlcat (dlitfilename, ".dlit", sizeof (dlitfilename));
data = (unsigned char*) FS_LoadFile(litfilename, tempmempool, false, &filesize);
if (data)
{
loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, filesize - 8);
memcpy(loadmodel->brushq1.lightdata, data + 8, filesize - 8);
Mem_Free(data);
+ data = (unsigned char*) FS_LoadFile(dlitfilename, tempmempool, false, &filesize);
+ if (data)
+ {
+ if (filesize == (fs_offset_t)(8 + l->filelen * 3) && data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T')
+ {
+ i = LittleLong(((int *)data)[1]);
+ if (i == 1)
+ {
+ Con_DPrintf("loaded %s\n", dlitfilename);
+ loadmodel->brushq1.nmaplightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, filesize - 8);
+ memcpy(loadmodel->brushq1.nmaplightdata, data + 8, filesize - 8);
+ loadmodel->brushq3.deluxemapping_modelspace = false;
+ loadmodel->brushq3.deluxemapping = true;
+ }
+ }
+ Mem_Free(data);
+ data = NULL;
+ }
return;
}
else
- {
Con_Printf("Unknown .lit file version (%d)\n", i);
- Mem_Free(data);
- }
}
+ else if (filesize == 8)
+ Con_Print("Empty .lit file, ignoring\n");
else
+ Con_Printf("Corrupt .lit file (file size %i bytes, should be %i bytes), ignoring\n", filesize, 8 + l->filelen * 3);
+ if (data)
{
- if (filesize == 8)
- Con_Print("Empty .lit file, ignoring\n");
- else
- Con_Printf("Corrupt .lit file (file size %i bytes, should be %i bytes), ignoring\n", filesize, 8 + l->filelen * 3);
Mem_Free(data);
+ data = NULL;
}
}
// LordHavoc: oh well, expand the white lighting data
if (!l->filelen)
return;
loadmodel->brushq1.lightdata = (unsigned char *)Mem_Alloc(loadmodel->mempool, l->filelen*3);
- in = loadmodel->brushq1.lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
+ in = mod_base + l->fileofs;
out = loadmodel->brushq1.lightdata;
- memcpy(in, mod_base + l->fileofs, l->filelen);
for (i = 0;i < l->filelen;i++)
{
d = *in++;
int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris, lightmapnumber;
float texmins[2], texmaxs[2], val, lightmaptexcoordscale;
#define LIGHTMAPSIZE 256
- rtexture_t *lightmaptexture;
+ rtexture_t *lightmaptexture, *deluxemaptexture;
int lightmap_lineused[LIGHTMAPSIZE];
in = (dface_t *)(mod_base + l->fileofs);
loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false, false);
lightmaptexture = NULL;
+ deluxemaptexture = r_texture_blanknormalmap;
lightmapnumber = 1;
lightmaptexcoordscale = 1.0f / (float)LIGHTMAPSIZE;
else if (loadmodel->brush.ishlbsp) // LordHavoc: HalfLife map (bsp version 30)
surface->lightmapinfo->samples = loadmodel->brushq1.lightdata + i;
else // LordHavoc: white lighting (bsp version 29)
+ {
surface->lightmapinfo->samples = loadmodel->brushq1.lightdata + (i * 3);
+ if (loadmodel->brushq1.nmaplightdata)
+ surface->lightmapinfo->nmapsamples = loadmodel->brushq1.nmaplightdata + (i * 3);
+ }
// check if we should apply a lightmap to this
if (!(surface->lightmapinfo->texinfo->flags & TEX_SPECIAL) || surface->lightmapinfo->samples)
if (!lightmaptexture || !Mod_Q1BSP_AllocLightmapBlock(lightmap_lineused, LIGHTMAPSIZE, LIGHTMAPSIZE, ssize, tsize, &lightmapx, &lightmapy))
{
// could not find room, make a new lightmap
- lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%i", lightmapnumber++), LIGHTMAPSIZE, LIGHTMAPSIZE, NULL, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
+ lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%i", lightmapnumber), LIGHTMAPSIZE, LIGHTMAPSIZE, NULL, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
+ if (loadmodel->brushq1.nmaplightdata)
+ deluxemaptexture = R_LoadTexture2D(loadmodel->texturepool, va("deluxemap%i", lightmapnumber), LIGHTMAPSIZE, LIGHTMAPSIZE, NULL, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
+ lightmapnumber++;
memset(lightmap_lineused, 0, sizeof(lightmap_lineused));
Mod_Q1BSP_AllocLightmapBlock(lightmap_lineused, LIGHTMAPSIZE, LIGHTMAPSIZE, ssize, tsize, &lightmapx, &lightmapy);
}
surface->lightmaptexture = lightmaptexture;
- surface->deluxemaptexture = r_texture_blanknormalmap;
+ surface->deluxemaptexture = deluxemaptexture;
surface->lightmapinfo->lightmaporigin[0] = lightmapx;
surface->lightmapinfo->lightmaporigin[1] = lightmapy;