]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
Replaced snprintf and vnsprintf calls by dpsnprintf and dpvsnprintf calls, to ensure...
[xonotic/darkplaces.git] / model_brush.c
index d70a58198890880109e9782d37e7fdba3add9f2d..3eab23d01edcd1e0b336649ea5c12cc6a06bb031 100644 (file)
@@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "r_shadow.h"
 #include "polygon.h"
 #include "curves.h"
+#include "wad.h"
+
 
 // note: model_shared.c sets up r_notexture, and r_surf_notexture
 
@@ -786,7 +788,7 @@ loc0:
                        int i, ds, dt;
                        msurface_t *surf;
 
-                       surf = cl.worldmodel->brushq1.surfaces + node->firstsurface;
+                       surf = r_refdef.worldmodel->brushq1.surfaces + node->firstsurface;
                        for (i = 0;i < node->numsurfaces;i++, surf++)
                        {
                                if (!(surf->flags & SURF_LIGHTMAP) || !surf->samples)
@@ -867,7 +869,7 @@ middle sample (the one which was requested)
 
 void Mod_Q1BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
 {
-       Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, cl.worldmodel->brushq1.nodes + cl.worldmodel->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
+       Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
 }
 
 static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *out, qbyte *outend)
@@ -878,7 +880,7 @@ static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *
        {
                if (in == inend)
                {
-                       Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+                       Con_Printf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
                        return;
                }
                c = *in++;
@@ -888,14 +890,14 @@ static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *
                {
                        if (in == inend)
                        {
-                               Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun (during zero-run) on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+                               Con_Printf("Mod_Q1BSP_DecompressVis: input underrun (during zero-run) on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
                                return;
                        }
                        for (c = *in++;c > 0;c--)
                        {
                                if (out == outend)
                                {
-                                       Con_DPrintf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+                                       Con_Printf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
                                        return;
                                }
                                *out++ = 0;
@@ -1321,7 +1323,7 @@ static void Mod_Q1BSP_LoadLighting(lump_t *l)
 static void Mod_Q1BSP_LoadLightList(void)
 {
        int a, n, numlights;
-       char lightsfilename[1024], *s, *t, *lightsstring;
+       char tempchar, *s, *t, *lightsstring, lightsfilename[1024];
        mlight_t *e;
 
        strlcpy (lightsfilename, loadmodel->name, sizeof (lightsfilename));
@@ -1333,12 +1335,13 @@ static void Mod_Q1BSP_LoadLightList(void)
                numlights = 0;
                while (*s)
                {
-                       while (*s && *s != '\n')
+                       while (*s && *s != '\n' && *s != '\r')
                                s++;
                        if (!*s)
                        {
                                Mem_Free(lightsstring);
-                               Host_Error("lights file must end with a newline\n");
+                               Con_Printf("lights file must end with a newline\n");
+                               return;
                        }
                        s++;
                        numlights++;
@@ -1349,30 +1352,31 @@ static void Mod_Q1BSP_LoadLightList(void)
                while (*s && n < numlights)
                {
                        t = s;
-                       while (*s && *s != '\n')
+                       while (*s && *s != '\n' && *s != '\r')
                                s++;
                        if (!*s)
                        {
-                               Mem_Free(lightsstring);
-                               Host_Error("misparsed lights file!\n");
+                               Con_Printf("misparsed lights file!\n");
+                               break;
                        }
                        e = loadmodel->brushq1.lights + n;
+                       tempchar = *s;
                        *s = 0;
                        a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style);
-                       *s = '\n';
+                       *s = tempchar;
                        if (a != 14)
                        {
-                               Mem_Free(lightsstring);
-                               Host_Error("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
+                               Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
+                               break;
                        }
-                       s++;
+                       if (*s == '\r')
+                               s++;
+                       if (*s == '\n')
+                               s++;
                        n++;
                }
                if (*s)
-               {
-                       Mem_Free(lightsstring);
-                       Host_Error("misparsed lights file!\n");
-               }
+                       Con_Printf("misparsed lights file!\n");
                loadmodel->brushq1.numlights = numlights;
                Mem_Free(lightsstring);
        }
@@ -2269,6 +2273,102 @@ static void Mod_Q1BSP_LoadPlanes(lump_t *l)
        }
 }
 
+static void Mod_Q1BSP_LoadMapBrushes(void)
+{
+#if 0
+// unfinished
+       int submodel, numbrushes;
+       qboolean firstbrush;
+       char *text, *maptext;
+       char mapfilename[MAX_QPATH];
+       FS_StripExtension (loadmodel->name, mapfilename, sizeof (mapfilename));
+       strlcat (mapfilename, ".map", sizeof (mapfilename));
+       maptext = (qbyte*) FS_LoadFile(mapfilename, tempmempool, false);
+       if (!maptext)
+               return;
+       text = maptext;
+       if (!COM_ParseToken(&data, false))
+               return; // error
+       submodel = 0;
+       for (;;)
+       {
+               if (!COM_ParseToken(&data, false))
+                       break;
+               if (com_token[0] != '{')
+                       return; // error
+               // entity
+               firstbrush = true;
+               numbrushes = 0;
+               maxbrushes = 256;
+               brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
+               for (;;)
+               {
+                       if (!COM_ParseToken(&data, false))
+                               return; // error
+                       if (com_token[0] == '}')
+                               break; // end of entity
+                       if (com_token[0] == '{')
+                       {
+                               // brush
+                               if (firstbrush)
+                               {
+                                       if (submodel)
+                                       {
+                                               if (submodel > loadmodel->brush.numsubmodels)
+                                               {
+                                                       Con_Printf("Mod_Q1BSP_LoadMapBrushes: .map has more submodels than .bsp!\n");
+                                                       model = NULL;
+                                               }
+                                               else
+                                                       model = loadmodel->brush.submodels[submodel];
+                                       }
+                                       else
+                                               model = loadmodel;
+                               }
+                               for (;;)
+                               {
+                                       if (!COM_ParseToken(&data, false))
+                                               return; // error
+                                       if (com_token[0] == '}')
+                                               break; // end of brush
+                                       // each brush face should be this format:
+                                       // ( x y z ) ( x y z ) ( x y z ) texture scroll_s scroll_t rotateangle scale_s scale_t
+                                       // FIXME: support hl .map format
+                                       for (pointnum = 0;pointnum < 3;pointnum++)
+                                       {
+                                               COM_ParseToken(&data, false);
+                                               for (componentnum = 0;componentnum < 3;componentnum++)
+                                               {
+                                                       COM_ParseToken(&data, false);
+                                                       point[pointnum][componentnum] = atof(com_token);
+                                               }
+                                               COM_ParseToken(&data, false);
+                                       }
+                                       COM_ParseToken(&data, false);
+                                       strlcpy(facetexture, com_token, sizeof(facetexture));
+                                       COM_ParseToken(&data, false);
+                                       //scroll_s = atof(com_token);
+                                       COM_ParseToken(&data, false);
+                                       //scroll_t = atof(com_token);
+                                       COM_ParseToken(&data, false);
+                                       //rotate = atof(com_token);
+                                       COM_ParseToken(&data, false);
+                                       //scale_s = atof(com_token);
+                                       COM_ParseToken(&data, false);
+                                       //scale_t = atof(com_token);
+                                       TriangleNormal(point[0], point[1], point[2], planenormal);
+                                       VectorNormalizeDouble(planenormal);
+                                       planedist = DotProduct(point[0], planenormal);
+                                       //ChooseTexturePlane(planenormal, texturevector[0], texturevector[1]);
+                               }
+                               continue;
+                       }
+               }
+       }
+#endif
+}
+
+
 #define MAX_PORTALPOINTS 64
 
 typedef struct portal_s
@@ -2607,7 +2707,7 @@ static void Mod_Q1BSP_RecursiveNodePortals(mnode_t *node)
                        RemovePortalFromNodes(portal);
 
                        // cut the portal into two portals, one on each side of the node plane
-                       PolygonD_Divide(portal->numpoints, portal->points, plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, 1.0/32.0, MAX_PORTALPOINTS, frontpoints, &numfrontpoints, MAX_PORTALPOINTS, backpoints, &numbackpoints); 
+                       PolygonD_Divide(portal->numpoints, portal->points, plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, 1.0/32.0, MAX_PORTALPOINTS, frontpoints, &numfrontpoints, MAX_PORTALPOINTS, backpoints, &numbackpoints);
 
                        if (!numfrontpoints)
                        {
@@ -2939,7 +3039,7 @@ extern void R_Q1BSP_DrawSky(entity_render_t *ent);
 extern void R_Q1BSP_Draw(entity_render_t *ent);
 extern void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
 extern void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
 void Mod_Q1BSP_Load(model_t *mod, void *buffer)
 {
        int i, j, k;
@@ -3020,11 +3120,11 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        Mod_Q1BSP_MakePortals();
 
        mod->numframes = 2;             // regular and alternate animation
+       mod->numskins = 1;
 
        mainmempool = mod->mempool;
 
        Mod_Q1BSP_LoadLightList();
-       loadmodel = loadmodel;
 
        // make a single combined shadow mesh to allow optimized shadow volume creation
        numshadowmeshtriangles = 0;
@@ -3038,7 +3138,10 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surf->mesh.data_vertex3f, NULL, NULL, NULL, NULL, surf->mesh.num_triangles, surf->mesh.data_element3i);
        loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true);
        Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles);
-       
+
+       if (loadmodel->brush.numsubmodels)
+               loadmodel->brush.submodels = Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(model_t *));
+
        // LordHavoc: to clear the fog around the original quake submodel code, I
        // will explain:
        // first of all, some background info on the submodels:
@@ -3078,6 +3181,9 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                        mod->mempool = NULL;
                }
 
+               if (loadmodel->brush.submodels)
+                       loadmodel->brush.submodels[i] = mod;
+
                bm = &mod->brushq1.submodels[i];
 
                mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
@@ -3166,6 +3272,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                mod->brushq1.num_visleafs = bm->visleafs;
        }
 
+       Mod_Q1BSP_LoadMapBrushes();
+
        //Mod_Q1BSP_ProcessLightList();
 
        if (developer.integer)
@@ -3739,6 +3847,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                                else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
                                                                                        strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename));
                                                                        }
+                                                                       if (!strcasecmp(parameter[0], "alphafunc"))
+                                                                               flags2 |= Q3TEXTUREFLAG_ALPHATEST;
                                                                        // break out a level if it was }
                                                                        if (!strcasecmp(com_token, "}"))
                                                                                break;
@@ -3822,6 +3932,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                        flags |= Q3SURFACEPARM_TRANS;
                                                                else if (!strcasecmp(parameter[1], "water"))
                                                                        flags |= Q3SURFACEPARM_WATER;
+                                                               else if (!strcasecmp(parameter[1], "pointlight"))
+                                                                       flags |= Q3SURFACEPARM_POINTLIGHT;
                                                                else
                                                                        Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], parameter[1]);
                                                        }
@@ -3852,7 +3964,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                // force transparent render path for a number of odd
                                                // shader effects to avoid bogging down the normal
                                                // render path unnecessarily
-                                               if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                                               if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2 | Q3TEXTUREFLAG_ALPHATEST))
                                                        flags |= Q3SURFACEPARM_TRANS;
                                                // add shader to list (shadername and flags)
                                                // actually here we just poke into the texture settings
@@ -3866,7 +3978,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                if ((flags & Q3SURFACEPARM_SKY) && sky[0])
                                                                {
                                                                        // quake3 seems to append a _ to the skybox name, so this must do so as well
-                                                                       snprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", sky);
+                                                                       dpsnprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", sky);
                                                                }
                                                        }
                                                }
@@ -3892,8 +4004,8 @@ parseerror:
                        Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
                        out->surfaceparms = 0;
                        // these are defaults
-                       if (!strncmp(out->name, "textures/skies/", 15))
-                               out->surfaceparms |= Q3SURFACEPARM_SKY;
+                       //if (!strncmp(out->name, "textures/skies/", 15))
+                       //      out->surfaceparms |= Q3SURFACEPARM_SKY;
                        //if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")
                        // || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw"))
                        //      out->surfaceparms |= Q3SURFACEPARM_NODRAW;
@@ -3901,9 +4013,11 @@ parseerror:
                        //      out->surfaceparms |= Q3SURFACEPARM_TRANS;
                }
                if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true))
-                       Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true);
+                       if (!Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true))
+                               Con_Printf("%s: texture loading for shader \"%s\" failed (first layer \"%s\" not found either)\n", loadmodel->name, out->name, out->firstpasstexturename);
        }
-       Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
+       if (c)
+               Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
 }
 
 static void Mod_Q3BSP_LoadPlanes(lump_t *l)
@@ -4192,11 +4306,13 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                else
                        out->effect = loadmodel->brushq3.data_effects + n;
                n = LittleLong(in->lightmapindex);
-               if (n < -1 || n >= loadmodel->brushq3.num_lightmaps)
+               if (n >= loadmodel->brushq3.num_lightmaps)
                {
-                       Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
                        n = -1;
                }
+               else if (n < 0)
+                       n = -1;
                if (n == -1)
                        out->lightmaptexture = NULL;
                else
@@ -4355,7 +4471,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                        Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
                        Q3PatchTriangleElements(out->data_collisionelement3i, finalwidth, finalheight);
 
-                       Mod_SnapVertices(3, out->num_vertices, out->data_vertex3f, 0.25);
+                       //Mod_SnapVertices(3, out->num_vertices, out->data_vertex3f, 0.25);
                        Mod_SnapVertices(3, out->num_collisionvertices, out->data_collisionvertex3f, 1);
 
                        oldnumtriangles = out->num_triangles;
@@ -4771,7 +4887,7 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
                // leafs to find real number of clusters
                loadmodel->brush.num_pvsclusters = 1;
                for (i = 0;i < loadmodel->brushq3.num_leafs;i++)
-                       loadmodel->brush.num_pvsclusters = min(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
+                       loadmodel->brush.num_pvsclusters = max(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
 
                // create clusters
                loadmodel->brush.num_pvsclusterbytes = (loadmodel->brush.num_pvsclusters + 7) / 8;
@@ -5042,7 +5158,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, q3mnode_t *nod
                        if (dist1near >= 0 && dist2near >= 0 && dist1far <  0 && dist2far >= 0){node = node->children[0];continue;}
                        if (dist1near >= 0 && dist2near >= 0 && dist1far >= 0 && dist2far <  0){node = node->children[0];continue;}
                        if (dist1near >= 0 && dist2near >= 0 && dist1far >= 0 && dist2far >= 0){node = node->children[0];continue;}
-                       {             
+                       {
                                if (dist2near < 0) // d1n<0 && d2n<0
                                {
                                        if (dist2near < 0) // d1n<0 && d2n<0
@@ -5669,7 +5785,7 @@ extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
 extern void R_Q3BSP_Draw(struct entity_render_s *ent);
 extern void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
 extern void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
 void Mod_Q3BSP_Load(model_t *mod, void *buffer)
 {
        int i, j, numshadowmeshtriangles;
@@ -5678,7 +5794,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
        q3msurface_t *face;
 
        mod->type = mod_brushq3;
-       mod->numframes = 1;
+       mod->numframes = 2; // although alternate textures are not supported it is annoying to complain about no such frame 1
        mod->numskins = 1;
 
        header = (q3dheader_t *)buffer;