added loading of hmap2 .dlit tangentspace deluxemap files and a rather lame method...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 28 Mar 2006 10:17:21 +0000 (10:17 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 28 Mar 2006 10:17:21 +0000 (10:17 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6199 d7cf8633-e32d-0410-b094-e92efae38249

gl_rsurf.c
model_brush.c
model_shared.h

index bec8e2e..731eda0 100644 (file)
@@ -50,10 +50,10 @@ Combine and scale multiple lightmaps into the 8.8 format in blocklights
 */
 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
@@ -75,16 +75,13 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
        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;
@@ -96,31 +93,78 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
        // (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])
index fc53c7e..a2524fe 100644 (file)
@@ -1517,9 +1517,9 @@ static void Mod_Q1BSP_LoadLighting(lump_t *l)
 {
        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);
@@ -1536,7 +1536,9 @@ static void Mod_Q1BSP_LoadLighting(lump_t *l)
                // 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)
                {
@@ -1549,30 +1551,45 @@ static void Mod_Q1BSP_LoadLighting(lump_t *l)
                                        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++;
@@ -2015,7 +2032,7 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
        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);
@@ -2043,6 +2060,7 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
        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;
 
@@ -2152,7 +2170,11 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                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)
@@ -2173,13 +2195,16 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                        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;
 
index 85c6d97..8d7b626 100644 (file)
@@ -246,6 +246,8 @@ typedef struct msurface_lightmapinfo_s
        unsigned char styles[MAXLIGHTMAPS]; // q1bsp
        // RGB lighting data [numstyles][height][width][3]
        unsigned char *samples; // q1bsp
+       // RGB normalmap data [numstyles][height][width][3]
+       unsigned char *nmapsamples; // q1bsp
        // stain to apply on lightmap (soot/dirt/blood/whatever)
        unsigned char *stainsamples; // q1bsp
        int texturemins[2]; // q1bsp
@@ -423,6 +425,7 @@ typedef struct model_brushq1_s
 
        int                             num_lightdata;
        unsigned char                   *lightdata;
+       unsigned char                   *nmaplightdata; // deluxemap file
 
        // lightmap update chains for light styles
        int                             light_styles;