]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
modified Q1BSP loader to generate lightmap fragments on its own, rather than relying...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 21 Mar 2006 06:49:25 +0000 (06:49 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 21 Mar 2006 06:49:25 +0000 (06:49 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6155 d7cf8633-e32d-0410-b094-e92efae38249

cl_video.c
gl_draw.c
gl_rsurf.c
gl_textures.c
model_brush.c
model_shared.h
r_textures.h

index 3bbe315a34079e63a20b72ad2e1f43642efcae28..5f56b889014c50308f5b9d4701c466be6144fb56 100644 (file)
@@ -205,7 +205,7 @@ static void VideoFrame( clvideo_t *video )
                                return;
                        }
                } while( video->framenum < destframe );
-               R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata );
+               R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata, 0, 0, video->cpif.width, video->cpif.height );
        }
 }
 
index 50f472d4f099670117e3bade28c14eefbbd1961b..66a5cd19144d077492d65cf678f27de01815a5ca 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -405,7 +405,7 @@ cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, u
        {
                if (pic->tex && pic->width == width && pic->height == height)
                {
-                       R_UpdateTexture(pic->tex, pixels);
+                       R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
                        return pic;
                }
        }
index fc04f2443b9ae6d65f4c2e001e3622103559879d..5bcf8fb3ca763825f71c6132b03ac74b7265f418 100644 (file)
@@ -50,7 +50,7 @@ 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, stride, l;
+       int smax, tmax, i, j, size, size3, maps, l;
        unsigned int *bl, scale;
        unsigned char *lightmap, *out, *stain;
        static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
@@ -96,8 +96,7 @@ 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)
        {
-               stride = (surface->lightmapinfo->lightmaptexturestride - smax) * 4;
-               for (i = 0;i < tmax;i++, out += stride)
+               for (i = 0;i < tmax;i++)
                {
                        for (j = 0;j < smax;j++)
                        {
@@ -110,8 +109,7 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
        }
        else
        {
-               stride = (surface->lightmapinfo->lightmaptexturestride - smax) * 3;
-               for (i = 0;i < tmax;i++, out += stride)
+               for (i = 0;i < tmax;i++)
                {
                        for (j = 0;j < smax;j++)
                        {
@@ -122,7 +120,7 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
                }
        }
 
-       R_UpdateTexture(surface->lightmaptexture, templight);
+       R_UpdateTexture(surface->lightmaptexture, 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 0e5812bd4d3d0b627f918d60882acc452524aa69..c23980f1ba383ec05694ec61308ee529b5aadd97 100644 (file)
@@ -683,7 +683,7 @@ static void GL_SetupTextureParameters(int flags, int texturetype)
        CHECKGLERROR
 }
 
-static void R_Upload(gltexture_t *glt, unsigned char *data)
+static void R_Upload(gltexture_t *glt, unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth)
 {
        int i, mip, width, height, depth;
        GLint oldbindtexnum;
@@ -699,7 +699,7 @@ static void R_Upload(gltexture_t *glt, unsigned char *data)
        CHECKGLERROR
        glt->flags &= ~GLTEXF_UPLOAD;
 
-       if (glt->flags & TEXF_FRAGMENT)
+       if ((glt->flags & TEXF_FRAGMENT) || (glt->image->flags & (TEXF_MIPMAP | TEXF_PICMIP | GLTEXF_UPLOAD)) == 0)
        {
                if (glt->image->flags & GLTEXF_UPLOAD)
                {
@@ -730,31 +730,31 @@ static void R_Upload(gltexture_t *glt, unsigned char *data)
 
                if (prevbuffer == NULL)
                {
-                       R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->bytesperpixel);
-                       memset(resizebuffer, 0, glt->width * glt->height * glt->image->depth * glt->image->bytesperpixel);
+                       R_MakeResizeBufferBigger(fragwidth * fragheight * fragdepth * glt->image->bytesperpixel);
+                       memset(resizebuffer, 0, fragwidth * fragheight * fragdepth * glt->image->bytesperpixel);
                        prevbuffer = resizebuffer;
                }
                else if (glt->textype->textype == TEXTYPE_PALETTE)
                {
                        // promote paletted to RGBA, so we only have to worry about RGB and
                        // RGBA in the rest of this code
-                       R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->sides * glt->image->bytesperpixel);
-                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, glt->palette);
+                       R_MakeResizeBufferBigger(fragwidth * fragheight * fragdepth * glt->image->sides * glt->image->bytesperpixel);
+                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, fragwidth * fragheight * fragdepth, glt->palette);
                        prevbuffer = colorconvertbuffer;
                }
 
                switch(glt->image->texturetype)
                {
                case GLTEXTURETYPE_1D:
-                       qglTexSubImage1D(GL_TEXTURE_1D, 0, glt->x, glt->width, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       qglTexSubImage1D(GL_TEXTURE_1D, 0, glt->x + fragx, fragwidth, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                        CHECKGLERROR
                        break;
                case GLTEXTURETYPE_2D:
-                       qglTexSubImage2D(GL_TEXTURE_2D, 0, glt->x, glt->y, glt->width, glt->height, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       qglTexSubImage2D(GL_TEXTURE_2D, 0, glt->x + fragx, glt->y + fragy, fragwidth, fragheight, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                        CHECKGLERROR
                        break;
                case GLTEXTURETYPE_3D:
-                       qglTexSubImage3D(GL_TEXTURE_3D, 0, glt->x, glt->y, glt->z, glt->width, glt->height, glt->depth, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
+                       qglTexSubImage3D(GL_TEXTURE_3D, 0, glt->x + fragx, glt->y + fragy, glt->z + fragz, fragwidth, fragheight, fragdepth, glt->image->glformat, GL_UNSIGNED_BYTE, prevbuffer);
                        CHECKGLERROR
                        break;
                default:
@@ -1020,7 +1020,7 @@ static void R_UploadTexture (gltexture_t *glt)
        if (!(glt->flags & GLTEXF_UPLOAD))
                return;
 
-       R_Upload(glt, glt->inputtexels);
+       R_Upload(glt, glt->inputtexels, 0, 0, 0, glt->width, glt->height, glt->depth);
        if (glt->inputtexels)
        {
                Mem_Free(glt->inputtexels);
@@ -1267,12 +1267,7 @@ void R_FragmentLocation(rtexture_t *rt, int *x, int *y, float *fx1, float *fy1,
        R_FragmentLocation3D(rt, x, y, NULL, fx1, fy1, NULL, fx2, fy2, NULL);
 }
 
-int R_CompatibleFragmentWidth(int width, int textype, int flags)
-{
-       return width;
-}
-
-void R_UpdateTexture(rtexture_t *rt, unsigned char *data)
+void R_UpdateTexture(rtexture_t *rt, unsigned char *data, int x, int y, int width, int height)
 {
        gltexture_t *glt;
        if (rt == NULL)
@@ -1281,10 +1276,11 @@ void R_UpdateTexture(rtexture_t *rt, unsigned char *data)
                Host_Error("R_UpdateTexture: no data supplied");
        glt = (gltexture_t *)rt;
 
-       // if it has not been uploaded yet, update the data that will be used when it is
-       if (glt->inputtexels)
-               memcpy(glt->inputtexels, data, glt->inputdatasize);
-       else
-               R_Upload(glt, data);
+       // we need it to be uploaded before we can update a part of it
+       if (glt->flags & GLTEXF_UPLOAD)
+               R_UploadTexture(glt);
+
+       // update part of the texture
+       R_Upload(glt, data, x, y, 0, width, height, 1);
 }
 
index d69bfe851efc14e68a8fab36209b48597cec51b5..d53885e2e0af44151ea8ac31b83109c740c9ddf6 100644 (file)
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 cvar_t halflifebsp = {0, "halflifebsp", "0", "indicates the current map is hlbsp format (useful to know because of different bounding box sizes)"};
 cvar_t mcbsp = {0, "mcbsp", "0", "indicates the current map is mcbsp format (useful to know because of different bounding box sizes)"};
 cvar_t r_novis = {0, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"};
-cvar_t r_miplightmaps = {CVAR_SAVE, "r_miplightmaps", "0", "mipmaps lightmaps on upload, also expanding them to power of 2 sizes, this runs slower"};
 cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1", "whether to use RGBA (32bit) or RGB (24bit) lightmaps"};
 cvar_t r_nosurftextures = {0, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"};
 cvar_t r_subdivisions_tolerance = {0, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"};
@@ -51,7 +50,6 @@ void Mod_BrushInit(void)
        Cvar_RegisterVariable(&halflifebsp);
        Cvar_RegisterVariable(&mcbsp);
        Cvar_RegisterVariable(&r_novis);
-       Cvar_RegisterVariable(&r_miplightmaps);
        Cvar_RegisterVariable(&r_lightmaprgba);
        Cvar_RegisterVariable(&r_nosurftextures);
        Cvar_RegisterVariable(&r_subdivisions_tolerance);
@@ -1912,12 +1910,46 @@ static void Mod_Q1BSP_GenerateWarpMesh(msurface_t *surface)
 }
 #endif
 
+static qboolean Mod_Q1BSP_AllocLightmapBlock(int *lineused, int totalwidth, int totalheight, int blockwidth, int blockheight, int *outx, int *outy)
+{
+       int y, x2, y2;
+       int bestx = totalwidth, besty = 0;
+       // find the left-most space we can find
+       for (y = 0;y <= totalheight - blockheight;y++)
+       {
+               x2 = 0;
+               for (y2 = 0;y2 < blockheight;y2++)
+                       x2 = max(x2, lineused[y+y2]);
+               if (bestx > x2)
+               {
+                       bestx = x2;
+                       besty = y;
+               }
+       }
+       // if the best was not good enough, return failure
+       if (bestx > totalwidth - blockwidth)
+               return false;
+       // we found a good spot
+       if (outx)
+               *outx = bestx;
+       if (outy)
+               *outy = besty;
+       // now mark the space used
+       for (y2 = 0;y2 < blockheight;y2++)
+               lineused[besty+y2] = bestx + blockwidth;
+       // return success
+       return true;
+}
+
 static void Mod_Q1BSP_LoadFaces(lump_t *l)
 {
        dface_t *in;
        msurface_t *surface;
-       int i, j, count, surfacenum, planenum, smax, tmax, ssize, tsize, firstedge, numedges, totalverts, totaltris;
-       float texmins[2], texmaxs[2], val;
+       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;
+       int lightmap_lineused[LIGHTMAPSIZE];
 
        in = (dface_t *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -1943,6 +1975,10 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
        loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
        loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false, false);
 
+       lightmaptexture = NULL;
+       lightmapnumber = 1;
+       lightmaptexcoordscale = 1.0f / (float)LIGHTMAPSIZE;
+
        totalverts = 0;
        totaltris = 0;
        for (surfacenum = 0, in = (dface_t *)(mod_base + l->fileofs), surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, in++, surface++)
@@ -2032,7 +2068,6 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                // lighting info
                for (i = 0;i < MAXLIGHTMAPS;i++)
                        surface->lightmapinfo->styles[i] = in->styles[i];
-               surface->lightmapinfo->lightmaptexturestride = 0;
                surface->lightmaptexture = NULL;
                surface->deluxemaptexture = r_texture_blanknormalmap;
                i = LittleLong(in->lightofs);
@@ -2055,7 +2090,7 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                // check if we should apply a lightmap to this
                if (!(surface->lightmapinfo->texinfo->flags & TEX_SPECIAL) || surface->lightmapinfo->samples)
                {
-                       int i, iu, iv;
+                       int i, iu, iv, lightmapx, lightmapy;
                        float u, v, ubase, vbase, uscale, vscale;
 
                        if (ssize > 256 || tsize > 256)
@@ -2067,21 +2102,24 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                        // clear to white
                        memset(surface->lightmapinfo->stainsamples, 255, ssize * tsize * 3);
 
-                       if (r_miplightmaps.integer)
-                       {
-                               surface->lightmapinfo->lightmaptexturestride = ssize;
-                               surface->lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, NULL, surface->lightmapinfo->lightmaptexturestride, tsize, NULL, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
-                               surface->deluxemaptexture = r_texture_blanknormalmap;
-                       }
-                       else
+                       // find a place for this lightmap
+                       if (!lightmaptexture || !Mod_Q1BSP_AllocLightmapBlock(lightmap_lineused, LIGHTMAPSIZE, LIGHTMAPSIZE, ssize, tsize, &lightmapx, &lightmapy))
                        {
-                               surface->lightmapinfo->lightmaptexturestride = R_CompatibleFragmentWidth(ssize, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0);
-                               surface->lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, NULL, surface->lightmapinfo->lightmaptexturestride, tsize, NULL, loadmodel->brushq1.lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
-                               surface->deluxemaptexture = r_texture_blanknormalmap;
+                               // 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);
+                               memset(lightmap_lineused, 0, sizeof(lightmap_lineused));
+                               Mod_Q1BSP_AllocLightmapBlock(lightmap_lineused, LIGHTMAPSIZE, LIGHTMAPSIZE, ssize, tsize, &lightmapx, &lightmapy);
                        }
-                       R_FragmentLocation(surface->lightmaptexture, NULL, NULL, &ubase, &vbase, &uscale, &vscale);
-                       uscale = (uscale - ubase) / ssize;
-                       vscale = (vscale - vbase) / tsize;
+
+                       surface->lightmaptexture = lightmaptexture;
+                       surface->deluxemaptexture = r_texture_blanknormalmap;
+                       surface->lightmapinfo->lightmaporigin[0] = lightmapx;
+                       surface->lightmapinfo->lightmaporigin[1] = lightmapy;
+
+                       ubase = lightmapx * lightmaptexcoordscale;
+                       vbase = lightmapy * lightmaptexcoordscale;
+                       uscale = lightmaptexcoordscale;
+                       vscale = lightmaptexcoordscale;
 
                        for (i = 0;i < surface->num_vertices;i++)
                        {
index 4d47eecd65f484a30bafc03269d81d0979d0697f..85c6d970f7dbb066a3b08c164e863ccb1e26ac1b 100644 (file)
@@ -248,10 +248,9 @@ typedef struct msurface_lightmapinfo_s
        unsigned char *samples; // q1bsp
        // stain to apply on lightmap (soot/dirt/blood/whatever)
        unsigned char *stainsamples; // q1bsp
-       // the stride when building lightmaps to comply with fragment update
-       int lightmaptexturestride; // q1bsp
        int texturemins[2]; // q1bsp
        int extents[2]; // q1bsp
+       int lightmaporigin[2]; // q1bsp
 }
 msurface_lightmapinfo_t;
 
index 080aa3140594463217b2f05925cdbdd202385d1a..ace8301737731c85e33fb67c86e69417c666da17 100644 (file)
@@ -53,11 +53,6 @@ rtexturepool_t *R_AllocTexturePool(void);
 // free a texture pool (textures can not be freed individually)
 void R_FreeTexturePool(rtexturepool_t **rtexturepool);
 
-// important technical note:
-// fragment textures must have a width that is compatible with the fragment
-// update system, to get a compliant size, use R_CompatibleFragmentWidth
-int R_CompatibleFragmentWidth(int width, int textype, int flags);
-
 // add a texture to a pool and optionally precache (upload) it
 // (note: data == NULL is perfectly acceptable)
 // (note: palette must not be NULL if using TEXTYPE_PALETTE)
@@ -69,9 +64,9 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident
 // free a texture
 void R_FreeTexture(rtexture_t *rt);
 
-// update the image data of a texture, used by lightmap updates and
-// procedural textures.
-void R_UpdateTexture(rtexture_t *rt, unsigned char *data);
+// update a portion of the image data of a texture, used by lightmap updates
+// and procedural textures such as video playback.
+void R_UpdateTexture(rtexture_t *rt, unsigned char *data, int x, int y, int width, int height);
 
 // location of the fragment in the texture (note: any parameter except rt can
 // be NULL)