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"};
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));
// add two slots for notexture walls and notexture liquids
loadmodel->numtextures = m->nummiptex + 2;
- loadmodel->textures = Mem_Alloc(loadmodel->mempool, loadmodel->numtextures * sizeof(*loadmodel->textures));
+ loadmodel->textures = Mem_Alloc(loadmodel->mempool, loadmodel->numtextures * sizeof(texture_t));
// fill out all slots with notexture
- for (i = 0;i < loadmodel->numtextures;i++)
+ for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
{
- loadmodel->textures[i] = tx = Mem_Alloc(loadmodel->mempool, sizeof(texture_t));
tx->width = 16;
tx->height = 16;
tx->texture = r_notexture;
+ tx->shader = &Cshader_wall_lightmap;
if (i == loadmodel->numtextures - 1)
- tx->flags = SURF_DRAWTURB | SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID;
+ {
+ tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES;
+ tx->shader = &Cshader_water;
+ }
}
// just to work around bounds checking when debugging with it (array index out of bounds error thing)
if (name[j] >= 'A' && name[j] <= 'Z')
name[j] += 'a' - 'A';
- tx = loadmodel->textures[i];
+ tx = loadmodel->textures + i;
strcpy(tx->name, name);
tx->width = mtwidth;
tx->height = mtheight;
- tx->texture = NULL;
- tx->glowtexture = NULL;
- tx->fogtexture = NULL;
if (!tx->name[0])
{
if (tx->name[0] == '*')
{
- tx->flags |= (SURF_DRAWTURB | SURF_LIGHTBOTHSIDES);
+ tx->flags |= SURF_DRAWTURB | SURF_LIGHTBOTHSIDES;
// LordHavoc: some turbulent textures should be fullbright and solid
if (!strncmp(tx->name,"*lava",5)
|| !strncmp(tx->name,"*teleport",9)
|| !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
- tx->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
+ tx->flags |= SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA;
+ tx->shader = &Cshader_water;
}
else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y')
- tx->flags |= (SURF_DRAWSKY | SURF_CLIPSOLID);
+ {
+ tx->flags |= SURF_DRAWSKY;
+ tx->shader = &Cshader_sky;
+ }
else
{
tx->flags |= SURF_LIGHTMAP;
- if (!R_TextureHasAlpha(tx->texture))
- tx->flags |= SURF_CLIPSOLID;
+ tx->shader = &Cshader_wall_lightmap;
}
tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
// sequence the animations
for (i = 0;i < m->nummiptex;i++)
{
- tx = loadmodel->textures[i];
+ tx = loadmodel->textures + i;
if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0)
continue;
if (tx->anim_total[0] || tx->anim_total[1])
for (j = i;j < m->nummiptex;j++)
{
- tx2 = loadmodel->textures[j];
+ tx2 = loadmodel->textures + j;
if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2))
continue;
if (a != 14)
{
Mem_Free(lightsstring);
- Host_Error("invalid lights file, found %d parameters on line %i, should be 13 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone style)\n", a, n + 1);
+ 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);
}
s++;
n++;
}
// used only for HalfLife maps
-void Mod_ParseWadsFromEntityLump(char *data)
+void Mod_ParseWadsFromEntityLump(const char *data)
{
char key[128], value[4096];
char wadname[128];
int i, j, k;
if (!data)
return;
- data = COM_Parse(data);
- if (!data)
+ if (!COM_ParseToken(&data))
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
- data = COM_Parse(data);
- if (!data)
+ if (!COM_ParseToken(&data))
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
strcpy(key, com_token);
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- data = COM_Parse(data);
- if (!data)
+ if (!COM_ParseToken(&data))
return; // error
strcpy(value, com_token);
if (!strcmp("wad", key)) // for HalfLife maps
if ((unsigned int) miptex >= (unsigned int) loadmodel->numtextures)
Con_Printf ("error in model \"%s\": invalid miptex index %i (of %i)\n", loadmodel->name, miptex, loadmodel->numtextures);
else
- out->texture = loadmodel->textures[miptex];
+ out->texture = loadmodel->textures + miptex;
}
- if (out->texture == NULL)
+ if (out->flags & TEX_SPECIAL)
{
- // choose either the liquid notexture, or the normal notexture
- if (out->flags & TEX_SPECIAL)
- out->texture = loadmodel->textures[loadmodel->numtextures - 1];
- else
- out->texture = loadmodel->textures[loadmodel->numtextures - 2];
+ // if texture chosen is NULL or the shader needs a lightmap,
+ // force to notexture water shader
+ if (out->texture == NULL || out->texture->shader->flags & SHADERFLAGS_NEEDLIGHTMAP)
+ out->texture = loadmodel->textures + (loadmodel->numtextures - 1);
+ }
+ else
+ {
+ // if texture chosen is NULL, force to notexture
+ if (out->texture == NULL)
+ out->texture = loadmodel->textures + (loadmodel->numtextures - 2);
}
}
}
{
s = DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
t = DotProduct (in, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3];
- u = (s + 8 - surf->texturemins[0]) * (1.0 / 16.0) * uscale + ubase;
- v = (t + 8 - surf->texturemins[1]) * (1.0 / 16.0) * vscale + vbase;
+ u = (s + 8 - surf->texturemins[0]) * (1.0 / 16.0);
+ v = (t + 8 - surf->texturemins[1]) * (1.0 / 16.0);
// LordHavoc: calc lightmap data offset for vertex lighting to use
iu = (int) u;
iv = (int) v;
iu = bound(0, iu, smax);
iv = bound(0, iv, tmax);
+ u = u * uscale + ubase;
+ v = v * vscale + vbase;
mesh->verts[i * 4 + 0] = in[0];
mesh->verts[i * 4 + 1] = in[1];
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
+ loadmodel->surfacevisframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
+ loadmodel->surfacepvsframes = Mem_Alloc(loadmodel->mempool, count * sizeof(int));
for (surfnum = 0;surfnum < count;surfnum++, in++, out++)
{
+ out->number = surfnum;
// FIXME: validate edges, texinfo, etc?
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
// force lightmap upload on first time seeing the surface
out->cached_dlight = true;
- out->cached_ambient = -1000;
- out->cached_lightscalebit = -1000;
CalcSurfaceExtents (out);
out->samples = loadmodel->lightdata + (i * 3);
Mod_GenerateSurfacePolygon(out);
-
- if (out->texinfo->texture->flags & SURF_DRAWSKY)
+ if (out->texinfo->texture->shader == &Cshader_wall_lightmap)
{
- out->shader = &Cshader_sky;
- out->samples = NULL;
- Mod_GenerateVertexMesh (out);
- }
- else if (out->texinfo->texture->flags & SURF_DRAWTURB)
- {
- out->shader = &Cshader_water;
- out->samples = NULL;
- Mod_GenerateVertexMesh (out);
+ if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256))
+ Host_Error ("Bad surface extents");
+ Mod_GenerateWallMesh (out, false);
+ // stainmap for permanent marks on walls
+ out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
+ // clear to white
+ memset(out->stainsamples, 255, ssize * tsize * 3);
}
else
- {
- if (!R_TextureHasAlpha(out->texinfo->texture->texture))
- out->flags |= SURF_CLIPSOLID;
- if (out->texinfo->flags & TEX_SPECIAL)
- {
- // qbsp couldn't find the texture for this surface, but it was either turb or sky... assume turb
- out->shader = &Cshader_water;
- out->shader = &Cshader_water;
- out->samples = NULL;
- Mod_GenerateVertexMesh (out);
- }
- 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;
- out->samples = NULL;
- Mod_GenerateVertexMesh(out);
- }
- else
- {
- // stainmap for permanent marks on walls
- out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
- // clear to white
- memset(out->stainsamples, 255, ssize * tsize * 3);
- if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
- {
- out->shader = &Cshader_wall_vertex;
- Mod_GenerateWallMesh (out, true);
- }
- else
- {
- out->shader = &Cshader_wall_lightmap;
- Mod_GenerateWallMesh (out, false);
- }
- }
- }
+ Mod_GenerateVertexMesh (out);
}
}
-static model_t *sortmodel;
-
-static int Mod_SurfaceQSortCompare(const void *voida, const void *voidb)
-{
- const msurface_t *a, *b;
- a = *((const msurface_t **)voida);
- b = *((const msurface_t **)voidb);
- if (a->shader != b->shader)
- return (qbyte *) a->shader - (qbyte *) b->shader;
- if (a->texinfo->texture != b->texinfo->texture);
- return a->texinfo->texture - b->texinfo->texture;
- return 0;
-}
-
-static void Mod_BrushSortedSurfaces(model_t *model, mempool_t *pool)
-{
- int surfnum;
- sortmodel = model;
- sortmodel->modelsortedsurfaces = Mem_Alloc(pool, sortmodel->nummodelsurfaces * sizeof(msurface_t *));
- for (surfnum = 0;surfnum < sortmodel->nummodelsurfaces;surfnum++)
- sortmodel->modelsortedsurfaces[surfnum] = &sortmodel->surfaces[surfnum + sortmodel->firstmodelsurface];
-
- if (r_sortsurfaces.integer)
- qsort(sortmodel->modelsortedsurfaces, sortmodel->nummodelsurfaces, sizeof(msurface_t *), Mod_SurfaceQSortCompare);
-}
-
-
/*
=================
Mod_SetParent
*/
static void Mod_LoadMarksurfaces (lump_t *l)
{
- int i, j;
- short *in;
+ int i, j;
+ short *in;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
loadmodel->nummarksurfaces = l->filelen / sizeof(*in);
- loadmodel->marksurfaces = Mem_Alloc(loadmodel->mempool, loadmodel->nummarksurfaces * sizeof(msurface_t *));
+ loadmodel->marksurfaces = Mem_Alloc(loadmodel->mempool, loadmodel->nummarksurfaces * sizeof(int));
for (i = 0;i < loadmodel->nummarksurfaces;i++)
{
j = (unsigned) LittleShort(in[i]);
if (j >= loadmodel->numsurfaces)
Host_Error ("Mod_ParseMarksurfaces: bad surface number");
- loadmodel->marksurfaces[i] = loadmodel->surfaces + j;
+ loadmodel->marksurfaces[i] = j;
}
}
for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
{
// we only need to have a drawsky function if it is used (usually only on world model)
- if (surf->shader == &Cshader_sky)
+ if (surf->texinfo->texture->shader == &Cshader_sky)
mod->DrawSky = R_DrawBrushModelSky;
for (k = 0;k < surf->numedges;k++)
{
mod->Draw = R_DrawBrushModelNormal;
mod->DrawShadow = NULL;
- Mod_BrushSortedSurfaces(mod, mainmempool);
-
// LordHavoc: only register submodels if it is the world
// (prevents bsp models from replacing world submodels)
if (loadmodel->isworldmodel && i < (mod->numsubmodels - 1))