]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
draw models which have no textures using the notexture checkerboard
[xonotic/darkplaces.git] / model_brush.c
index c0c7fac937843d12862934b9c0feb2c9701c7bf1..92244c451766043a293caeeef637f281afffb23c 100644 (file)
@@ -24,13 +24,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 qbyte mod_novis[(MAX_MAP_LEAFS + 7)/ 8];
 
-cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128"};
+//cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128"};
 cvar_t halflifebsp = {0, "halflifebsp", "0"};
 cvar_t r_novis = {0, "r_novis", "0"};
 cvar_t r_miplightmaps = {CVAR_SAVE, "r_miplightmaps", "0"};
 cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"};
 cvar_t r_vertexsurfacesthreshold = {CVAR_SAVE, "r_vertexsurfacesthreshold", "0"};
 cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"};
+cvar_t r_sortsurfaces = {0, "r_sortsurfaces", "0"};
+
+#define NUM_DETAILTEXTURES 1
+static rtexture_t *detailtextures[NUM_DETAILTEXTURES];
+static rtexturepool_t *detailtexturepool;
 
 /*
 ===============
@@ -39,19 +44,64 @@ Mod_BrushInit
 */
 void Mod_BrushInit (void)
 {
-       Cvar_RegisterVariable(&r_subdivide_size);
+//     Cvar_RegisterVariable(&r_subdivide_size);
        Cvar_RegisterVariable(&halflifebsp);
        Cvar_RegisterVariable(&r_novis);
        Cvar_RegisterVariable(&r_miplightmaps);
        Cvar_RegisterVariable(&r_lightmaprgba);
        Cvar_RegisterVariable(&r_vertexsurfacesthreshold);
        Cvar_RegisterVariable(&r_nosurftextures);
+       Cvar_RegisterVariable(&r_sortsurfaces);
        memset(mod_novis, 0xff, sizeof(mod_novis));
 }
 
-void Mod_Brush_SERAddEntity(void)
+void Mod_BrushStartup (void)
+{
+       int i, x, y, light;
+       float vc[3], vx[3], vy[3], vn[3], lightdir[3];
+#define DETAILRESOLUTION 256
+       qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION];
+       detailtexturepool = R_AllocTexturePool();
+       lightdir[0] = 0.5;
+       lightdir[1] = 1;
+       lightdir[2] = -0.25;
+       VectorNormalize(lightdir);
+       for (i = 0;i < NUM_DETAILTEXTURES;i++)
+       {
+               fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
+               for (y = 0;y < DETAILRESOLUTION;y++)
+               {
+                       for (x = 0;x < DETAILRESOLUTION;x++)
+                       {
+                               vc[0] = x;
+                               vc[1] = y;
+                               vc[2] = noise[y][x] * (1.0f / 32.0f);
+                               vx[0] = x + 1;
+                               vx[1] = y;
+                               vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
+                               vy[0] = x;
+                               vy[1] = y + 1;
+                               vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
+                               VectorSubtract(vx, vc, vx);
+                               VectorSubtract(vy, vc, vy);
+                               CrossProduct(vx, vy, vn);
+                               VectorNormalize(vn);
+                               light = 128 - DotProduct(vn, lightdir) * 128;
+                               light = bound(0, light, 255);
+                               data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
+                               data[y][x][3] = 255;
+                       }
+               }
+               detailtextures[i] = R_LoadTexture(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE);
+       }
+}
+
+void Mod_BrushShutdown (void)
 {
-       R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
+       int i;
+       for (i = 0;i < NUM_DETAILTEXTURES;i++)
+               R_FreeTexture(detailtextures[i]);
+       R_FreeTexturePool(&detailtexturepool);
 }
 
 /*
@@ -59,7 +109,7 @@ void Mod_Brush_SERAddEntity(void)
 Mod_PointInLeaf
 ===============
 */
-mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
+mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model)
 {
        mnode_t         *node;
 
@@ -224,23 +274,27 @@ static void Mod_LoadTextures (lump_t *l)
                // LordHavoc: HL sky textures are entirely different than quake
                if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
                {
-                       data = loadimagepixels(tx->name, false, 0, 0);
-                       if (data)
+                       if (loadmodel->isworldmodel)
                        {
-                               if (image_width == 256 && image_height == 128)
-                               {
-                                       if (loadmodel->isworldmodel)
-                                               R_InitSky (data, 4);
-                                       Mem_Free(data);
-                               }
-                               else
+                               data = loadimagepixels(tx->name, false, 0, 0);
+                               if (data)
                                {
-                                       Mem_Free(data);
-                                       Con_Printf ("Invalid replacement texture for sky \"%s\" in %\"%s\", must be 256x128 pixels\n", tx->name, loadmodel->name);
+                                       if (image_width == 256 && image_height == 128)
+                                       {
+                                               R_InitSky (data, 4);
+                                               Mem_Free(data);
+                                       }
+                                       else
+                                       {
+                                               Mem_Free(data);
+                                               Con_Printf ("Invalid replacement texture for sky \"%s\" in %\"%s\", must be 256x128 pixels\n", tx->name, loadmodel->name);
+                                               if (mtdata != NULL)
+                                                       R_InitSky (mtdata, 1);
+                                       }
                                }
+                               else if (mtdata != NULL)
+                                       R_InitSky (mtdata, 1);
                        }
-                       else if (loadmodel->isworldmodel)
-                               R_InitSky (mtdata, 1);
                }
                else if ((tx->texture = loadtextureimagewithmask(loadmodel->texturepool, tx->name, 0, 0, false, true, true)))
                {
@@ -352,6 +406,8 @@ static void Mod_LoadTextures (lump_t *l)
                        if (!R_TextureHasAlpha(tx->texture))
                                tx->flags |= SURF_CLIPSOLID;
                }
+
+               tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
        }
 
        // sequence the animations
@@ -891,6 +947,7 @@ void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
        }
 }
 
+#if 0
 #define MAX_SUBDIVPOLYTRIANGLES 4096
 #define MAX_SUBDIVPOLYVERTS (MAX_SUBDIVPOLYTRIANGLES * 3)
 
@@ -1026,6 +1083,7 @@ void Mod_GenerateWarpMesh (msurface_t *surf)
                v->st[1] = DotProduct (v->v, surf->texinfo->vecs[1]);
        }
 }
+#endif
 
 void Mod_GenerateVertexLitMesh (msurface_t *surf)
 {
@@ -1061,6 +1119,9 @@ void Mod_GenerateVertexLitMesh (msurface_t *surf)
                s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
                t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3];
 
+               out->ab[0] = s * (1.0f / 16.0f);
+               out->ab[1] = t * (1.0f / 16.0f);
+
                out->st[0] = s / surf->texinfo->texture->width;
                out->st[1] = t / surf->texinfo->texture->height;
 
@@ -1093,12 +1154,12 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf)
        if (r_miplightmaps.integer)
        {
                surf->lightmaptexturestride = (surf->extents[0]>>4)+1;
-               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE, NULL, NULL, 0);
+               surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE);
        }
        else
        {
                surf->lightmaptexturestride = R_CompatibleFragmentWidth((surf->extents[0]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0);
-               surf->lightmaptexture = R_ProceduralTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE, NULL, NULL, 0);
+               surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE);
        }
        R_FragmentLocation(surf->lightmaptexture, NULL, NULL, &xbase, &ybase, &xscale, &yscale);
        xscale = (xscale - xbase) * 16.0 / ((surf->extents[0] & ~15) + 16);
@@ -1126,6 +1187,9 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf)
                s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
                t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3];
 
+               out->ab[0] = s * (1.0f / 16.0f);
+               out->ab[1] = t * (1.0f / 16.0f);
+
                out->st[0] = s / surf->texinfo->texture->width;
                out->st[1] = t / surf->texinfo->texture->height;
 
@@ -1148,7 +1212,7 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf)
 void Mod_GenerateVertexMesh (msurface_t *surf)
 {
        int                             i, *index;
-       float                   *in;
+       float                   *in, s, t;
        surfvertex_t    *out;
        surfmesh_t              *mesh;
 
@@ -1173,17 +1237,19 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
        for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++)
        {
                VectorCopy (in, out->v);
-               out->st[0] = (DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) / surf->texinfo->texture->width;
-               out->st[1] = (DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) / surf->texinfo->texture->height;
+               s = (DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
+               t = (DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
+               out->st[0] = s / surf->texinfo->texture->width;
+               out->st[1] = t / surf->texinfo->texture->height;
+               out->ab[0] = s * (1.0f / 16.0f);
+               out->ab[1] = t * (1.0f / 16.0f);
        }
 }
 
 void Mod_GenerateSurfacePolygon (msurface_t *surf)
 {
-       float           *vert;
-       int                     i;
-       int                     lindex;
-       float           *vec;
+       int i, lindex;
+       float *vec, *vert, mins[3], maxs[3];
 
        // convert edges back to a normal polygon
        surf->poly_numverts = surf->numedges;
@@ -1198,6 +1264,20 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
                VectorCopy (vec, vert);
                vert += 3;
        }
+       vert = surf->poly_verts;
+       VectorCopy(vert, mins);
+       VectorCopy(vert, maxs);
+       vert += 3;
+       for (i = 1;i < surf->poly_numverts;i++)
+       {
+               if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0];
+               if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1];
+               if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2];
+               vert += 3;
+       }
+       surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
+       surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
+       surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
 }
 
 static void Mod_SplitSurfMeshIfTooBig(msurface_t *s)
@@ -1322,13 +1402,13 @@ static void Mod_LoadFaces (lump_t *l)
                {
                        out->shader = &Cshader_sky;
                        out->samples = NULL;
-                       Mod_GenerateWarpMesh (out);
+                       Mod_GenerateVertexMesh (out);
                }
                else if (out->texinfo->texture->flags & SURF_DRAWTURB)
                {
                        out->shader = &Cshader_water;
                        out->samples = NULL;
-                       Mod_GenerateWarpMesh (out);
+                       Mod_GenerateVertexMesh (out);
                }
                else
                {
@@ -1340,9 +1420,9 @@ static void Mod_LoadFaces (lump_t *l)
                                out->shader = &Cshader_water;
                                out->shader = &Cshader_water;
                                out->samples = NULL;
-                               Mod_GenerateWarpMesh (out);
+                               Mod_GenerateVertexMesh (out);
                        }
-                       else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16))
+                       else if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256))
                        {
                                Con_Printf ("Bad surface extents, converting to fullbright polygon");
                                out->shader = &Cshader_wall_fullbright;
@@ -1393,7 +1473,8 @@ static void Mod_BrushSortedSurfaces(model_t *model, mempool_t *pool)
        for (surfnum = 0;surfnum < sortmodel->nummodelsurfaces;surfnum++)
                sortmodel->modelsortedsurfaces[surfnum] = &sortmodel->surfaces[surfnum + sortmodel->firstmodelsurface];
 
-       qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare);
+       if (r_sortsurfaces.integer)
+               qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare);
 }
 
 
@@ -2518,7 +2599,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
 
                mod->numleafs = bm->visleafs;
 
-               mod->SERAddEntity = Mod_Brush_SERAddEntity;
                mod->Draw = R_DrawBrushModelNormal;
                mod->DrawShadow = NULL;