qbsp, light: Strip texinfo flags other than TEX_SPECIAL.
Write extended ones to a "mapname.texinfo" file. Support "_dirt" and "_minlight" flags on func_detail/group.
This commit is contained in:
parent
0b4c044473
commit
41972a376a
|
|
@ -210,9 +210,15 @@ typedef struct texinfo_s {
|
|||
int32_t flags;
|
||||
} texinfo_t;
|
||||
|
||||
// Texture flags. Only TEX_SPECIAL is written to the .bsp.
|
||||
#define TEX_SPECIAL 1 /* sky or slime, no lightmap or 256 subdivision */
|
||||
#define TEX_PHONG_ANGLE_SHIFT 11
|
||||
#define TEX_SKIP (1U << 1) /* an invisible surface */
|
||||
#define TEX_HINT (1U << 2) /* hint surface */
|
||||
#define TEX_NODIRT (1U << 3) /* don't receive dirtmapping */
|
||||
#define TEX_PHONG_ANGLE_SHIFT 4
|
||||
#define TEX_PHONG_ANGLE_MASK (255U << TEX_PHONG_ANGLE_SHIFT) /* 8 bit value. if non zero, enables phong shading and gives the angle threshold to use. */
|
||||
#define TEX_MINLIGHT_SHIFT 12
|
||||
#define TEX_MINLIGHT_MASK (255U << TEX_MINLIGHT_SHIFT) /* 8 bit value, minlight value for this face. */
|
||||
|
||||
/*
|
||||
* Note that edge 0 is never used, because negative edge nums are used for
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@ typedef struct {
|
|||
/*Warning: this stuff needs explicit initialisation*/
|
||||
typedef struct {
|
||||
const modelinfo_t *modelinfo;
|
||||
/* these take precedence the values in modelinfo */
|
||||
lightsample_t minlight;
|
||||
qboolean nodirt;
|
||||
|
||||
plane_t plane;
|
||||
vec3_t snormal;
|
||||
vec3_t tnormal;
|
||||
|
|
@ -243,6 +247,7 @@ extern qboolean onlyents;
|
|||
extern qboolean parse_escape_sequences;
|
||||
extern qboolean scaledonly;
|
||||
extern unsigned int lightturb;
|
||||
extern uint32_t *extended_texinfo_flags;
|
||||
|
||||
void SetupDirt();
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ qboolean onlyents = false;
|
|||
qboolean phongDebug = false;
|
||||
qboolean parse_escape_sequences = false;
|
||||
|
||||
uint32_t *extended_texinfo_flags = NULL;
|
||||
|
||||
char mapfilename[1024];
|
||||
|
||||
void
|
||||
|
|
@ -380,7 +382,7 @@ CalcualateVertexNormals(const bsp2_t *bsp)
|
|||
Face_Normal(bsp, f, f_norm);
|
||||
|
||||
// any face normal within this many degrees can be smoothed with this face
|
||||
const int f_smoothangle = (bsp->texinfo[f->texinfo].flags & TEX_PHONG_ANGLE_MASK) >> TEX_PHONG_ANGLE_SHIFT;
|
||||
const int f_smoothangle = (extended_texinfo_flags[f->texinfo] & TEX_PHONG_ANGLE_MASK) >> TEX_PHONG_ANGLE_SHIFT;
|
||||
if (!f_smoothangle)
|
||||
continue;
|
||||
|
||||
|
|
@ -391,7 +393,7 @@ CalcualateVertexNormals(const bsp2_t *bsp)
|
|||
if (f2 == f)
|
||||
continue;
|
||||
|
||||
const int f2_smoothangle = (bsp->texinfo[f2->texinfo].flags & TEX_PHONG_ANGLE_MASK) >> TEX_PHONG_ANGLE_SHIFT;
|
||||
const int f2_smoothangle = (extended_texinfo_flags[f2->texinfo] & TEX_PHONG_ANGLE_MASK) >> TEX_PHONG_ANGLE_SHIFT;
|
||||
if (!f2_smoothangle)
|
||||
continue;
|
||||
|
||||
|
|
@ -569,6 +571,36 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
LoadExtendedTexinfoFlags(const char *sourcefilename, const bsp2_t *bsp)
|
||||
{
|
||||
char filename[1024];
|
||||
|
||||
// always create the zero'ed array
|
||||
extended_texinfo_flags = (uint32_t *) calloc(bsp->numtexinfo, sizeof(uint32_t));
|
||||
|
||||
strcpy(filename, sourcefilename);
|
||||
StripExtension(filename);
|
||||
DefaultExtension(filename, ".texinfo");
|
||||
|
||||
FILE *texinfofile = fopen(filename, "rt");
|
||||
if (!texinfofile)
|
||||
return;
|
||||
|
||||
logprint("Loaded extended texinfo flags from %s\n", filename);
|
||||
|
||||
for (int i = 0; i < bsp->numtexinfo; i++) {
|
||||
int cnt = fscanf(texinfofile, "%u\n", &extended_texinfo_flags[i]);
|
||||
if (cnt != 1) {
|
||||
logprint("Error reading extended texinfo flags from %s\n", filename);
|
||||
fclose(texinfofile);
|
||||
memset(extended_texinfo_flags, 0, bsp->numtexinfo * sizeof(uint32_t));
|
||||
return;
|
||||
}
|
||||
}
|
||||
fclose(texinfofile);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==================
|
||||
* main
|
||||
|
|
@ -785,6 +817,7 @@ main(int argc, const char **argv)
|
|||
if (bspdata.version != BSP2VERSION)
|
||||
ConvertBSPFormat(BSP2VERSION, &bspdata);
|
||||
|
||||
LoadExtendedTexinfoFlags(source, bsp);
|
||||
LoadEntities(bsp);
|
||||
|
||||
modelinfo = (modelinfo_t *)malloc(bsp->nummodels * sizeof(*modelinfo));
|
||||
|
|
|
|||
|
|
@ -715,11 +715,15 @@ Lightsurf_Init(const modelinfo_t *modelinfo, const bsp2_dface_t *face,
|
|||
else
|
||||
lightsurf->lightmapscale = modelinfo->lightmapscale;
|
||||
|
||||
if (bsp->texinfo[face->texinfo].flags & TEX_PHONG_ANGLE_MASK)
|
||||
lightsurf->curved = true;
|
||||
else
|
||||
lightsurf->curved = false;
|
||||
|
||||
lightsurf->curved = !!(extended_texinfo_flags[face->texinfo] & TEX_PHONG_ANGLE_MASK);
|
||||
lightsurf->nodirt = !!(extended_texinfo_flags[face->texinfo] & TEX_NODIRT);
|
||||
lightsurf->minlight = modelinfo->minlight;
|
||||
lightsurf->minlight.light = (extended_texinfo_flags[face->texinfo] & TEX_MINLIGHT_MASK) >> TEX_MINLIGHT_SHIFT;
|
||||
/* fixup minlight color */
|
||||
if (lightsurf->minlight.light > 0 && VectorCompare(lightsurf->minlight.color, vec3_origin)) {
|
||||
VectorSet(lightsurf->minlight.color, 255, 255, 255);
|
||||
}
|
||||
|
||||
/* Set up the plane, including model offset */
|
||||
plane = &lightsurf->plane;
|
||||
VectorCopy(bsp->dplanes[face->planenum].normal, plane->normal);
|
||||
|
|
@ -950,7 +954,7 @@ Light_ClampMin(lightsample_t *sample, const vec_t light, const vec3_t color)
|
|||
* ============
|
||||
*/
|
||||
static inline vec_t
|
||||
Dirt_GetScaleFactor(vec_t occlusion, const entity_t *entity, const modelinfo_t *modelinfo)
|
||||
Dirt_GetScaleFactor(vec_t occlusion, const entity_t *entity, const lightsurf_t *surf)
|
||||
{
|
||||
vec_t light_dirtgain = dirtGain;
|
||||
vec_t light_dirtscale = dirtScale;
|
||||
|
|
@ -960,7 +964,7 @@ Dirt_GetScaleFactor(vec_t occlusion, const entity_t *entity, const modelinfo_t *
|
|||
/* is dirt processing disabled entirely? */
|
||||
if (!dirty)
|
||||
return 1.0f;
|
||||
if (modelinfo != NULL && modelinfo->nodirt)
|
||||
if (surf->nodirt)
|
||||
return 1.0f;
|
||||
|
||||
/* should this light be affected by dirt? */
|
||||
|
|
@ -1204,7 +1208,7 @@ LightFace_Entity(const entity_t *entity, const lightsample_t *light,
|
|||
if (dist >= 0) //anglescale normally lights the surface more than it otherwise should, meaning the dark side would be visible if there were no occlusion. naturally, this doesn't work when we're relaxing occlusion to faciliate curves.
|
||||
angle = (1.0 - entity->anglescale) + entity->anglescale * angle;
|
||||
add = GetLightValue(light, entity, dist) * angle * spotscale;
|
||||
add *= Dirt_GetScaleFactor(lightsurf->occlusion[i], entity, modelinfo);
|
||||
add *= Dirt_GetScaleFactor(lightsurf->occlusion[i], entity, lightsurf);
|
||||
|
||||
if (entity->projectedmip)
|
||||
{
|
||||
|
|
@ -1275,7 +1279,7 @@ LightFace_Sky(const sun_t *sun, const lightsurf_t *lightsurf, lightmap_t *lightm
|
|||
angle = (1.0 - sun->anglescale) + sun->anglescale * angle;
|
||||
value = angle * sun->sunlight.light;
|
||||
if (sun->dirt)
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, modelinfo);
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, lightsurf);
|
||||
Light_Add(sample, value, sun->sunlight.color, sun->sunvec);
|
||||
if (!hit/* && (sample->light >= 1)*/)
|
||||
hit = true;
|
||||
|
|
@ -1311,7 +1315,7 @@ LightFace_Min(const lightsample_t *light,
|
|||
for (i = 0; i < lightsurf->numpoints; i++, sample++) {
|
||||
vec_t value = light->light;
|
||||
if (minlightDirt)
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, modelinfo);
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, lightsurf);
|
||||
if (addminlight)
|
||||
Light_Add(sample, value, light->color, vec3_origin);
|
||||
else
|
||||
|
|
@ -1340,7 +1344,7 @@ LightFace_Min(const lightsample_t *light,
|
|||
trace = TestLight((*entity)->origin, surfpoint, shadowself);
|
||||
if (!trace)
|
||||
continue;
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[j], (*entity), modelinfo);
|
||||
value *= Dirt_GetScaleFactor(lightsurf->occlusion[j], (*entity), lightsurf);
|
||||
if (addminlight)
|
||||
Light_Add(sample, value, (*entity)->light.color, vec3_origin);
|
||||
else
|
||||
|
|
@ -1374,7 +1378,7 @@ LightFace_DirtDebug(const lightsurf_t *lightsurf, lightmap_t *lightmaps)
|
|||
/* Overwrite each point with the dirt value for that sample... */
|
||||
sample = lightmap->samples;
|
||||
for (i = 0; i < lightsurf->numpoints; i++, sample++) {
|
||||
sample->light = 255 * Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, modelinfo);
|
||||
sample->light = 255 * Dirt_GetScaleFactor(lightsurf->occlusion[i], NULL, lightsurf);
|
||||
VectorSet(sample->color, sample->light, sample->light, sample->light);
|
||||
}
|
||||
|
||||
|
|
@ -1864,8 +1868,8 @@ LightFace(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo,
|
|||
LightFace_Sky (sun, lightsurf, lightmaps);
|
||||
|
||||
/* minlight - Use the greater of global or model minlight. */
|
||||
if (modelinfo->minlight.light > minlight.light)
|
||||
LightFace_Min(&modelinfo->minlight, lightsurf, lightmaps);
|
||||
if (lightsurf->minlight.light > minlight.light)
|
||||
LightFace_Min(&lightsurf->minlight, lightsurf, lightmaps);
|
||||
else
|
||||
LightFace_Min(&minlight, lightsurf, lightmaps);
|
||||
|
||||
|
|
|
|||
22
qbsp/map.c
22
qbsp/map.c
|
|
@ -201,21 +201,27 @@ FindTexinfoEnt(texinfo_t *texinfo, mapentity_t *entity)
|
|||
flags |= TEX_HINT;
|
||||
if (IsSplitName(texname))
|
||||
flags |= TEX_SPECIAL;
|
||||
|
||||
if (atoi(ValueForKey(entity, "_dirt")) == -1)
|
||||
flags |= TEX_NODIRT;
|
||||
|
||||
// handle "_phong" and "_phong_angle"
|
||||
vec_t phongangle = atof(ValueForKey(entity, "_phong_angle"));
|
||||
int phong = atoi(ValueForKey(entity, "_phong"));
|
||||
const int phong = atoi(ValueForKey(entity, "_phong"));
|
||||
|
||||
if (phong && (phongangle == 0.0)) {
|
||||
phongangle = 89.0; // default _phong_angle
|
||||
}
|
||||
|
||||
if (phongangle) {
|
||||
int phongangle_int = rint(phongangle);
|
||||
|
||||
if (phongangle_int < 0) phongangle_int = 0;
|
||||
if (phongangle_int > 255) phongangle_int = 255;
|
||||
|
||||
flags |= (phongangle_int << TEX_PHONG_ANGLE_SHIFT);
|
||||
const uint8_t phongangle_byte = (uint8_t) qmax(0, qmin(255, (int)rint(phongangle)));
|
||||
flags |= (phongangle_byte << TEX_PHONG_ANGLE_SHIFT);
|
||||
}
|
||||
|
||||
// handle "_minlight"
|
||||
const vec_t minlight = atof(ValueForKey(entity, "_minlight"));
|
||||
if (minlight > 0) {
|
||||
const uint8_t minlight_byte = (uint8_t) qmax(0, qmin(255, (int)rint(minlight)));
|
||||
flags |= (minlight_byte << TEX_MINLIGHT_SHIFT);
|
||||
}
|
||||
|
||||
return FindTexinfo(texinfo, flags);
|
||||
|
|
|
|||
|
|
@ -109,13 +109,15 @@
|
|||
// Special contents flags for the compiler only
|
||||
#define CFLAGS_DETAIL (1U << 0)
|
||||
|
||||
// Texture flags
|
||||
// Texture flags. Only TEX_SPECIAL is written to the .bsp.
|
||||
#define TEX_SPECIAL (1U << 0) /* sky or liquid (no lightmap or subdivision */
|
||||
#define TEX_SKIP (1U << 1) /* an invisible surface */
|
||||
#define TEX_HINT (1U << 2) /* hint surface */
|
||||
|
||||
#define TEX_PHONG_ANGLE_SHIFT 11
|
||||
#define TEX_NODIRT (1U << 3) /* don't receive dirtmapping */
|
||||
#define TEX_PHONG_ANGLE_SHIFT 4
|
||||
#define TEX_PHONG_ANGLE_MASK (255U << TEX_PHONG_ANGLE_SHIFT) /* 8 bit value. if non zero, enables phong shading and gives the angle threshold to use. */
|
||||
#define TEX_MINLIGHT_SHIFT 12
|
||||
#define TEX_MINLIGHT_MASK (255U << TEX_MINLIGHT_SHIFT) /* 8 bit value, minlight value for this face. */
|
||||
|
||||
/*
|
||||
* The quality of the bsp output is highly sensitive to these epsilon values.
|
||||
|
|
|
|||
|
|
@ -695,6 +695,42 @@ BeginBSPFile(void)
|
|||
map.cTotal[LUMP_LEAFS]++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes extended texinfo flags to a file so they can be read by the light tool.
|
||||
* Used for phong shading and other lighting settings on func_detail.
|
||||
*/
|
||||
static void
|
||||
WriteExtendedTexinfoFlags(void)
|
||||
{
|
||||
bool needwrite = false;
|
||||
const texinfo_t *texinfo = pWorldEnt->lumps[LUMP_TEXINFO].data;
|
||||
const int num_texinfo = pWorldEnt->lumps[LUMP_TEXINFO].index;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_texinfo; i++) {
|
||||
if (texinfo[i].flags & ~(TEX_SPECIAL | TEX_SKIP | TEX_HINT)) {
|
||||
// this texinfo uses some extended flags, write them to a file
|
||||
needwrite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needwrite)
|
||||
return;
|
||||
|
||||
FILE *texinfofile;
|
||||
StripExtension(options.szBSPName);
|
||||
strcat(options.szBSPName, ".texinfo");
|
||||
texinfofile = fopen(options.szBSPName, "wt");
|
||||
if (!texinfofile)
|
||||
Error("Failed to open %s: %s", options.szBSPName, strerror(errno));
|
||||
|
||||
for (i = 0; i < num_texinfo; i++) {
|
||||
fprintf(texinfofile, "%u\n", texinfo[i].flags);
|
||||
}
|
||||
fclose(texinfofile);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any extra texinfo flags we added that are not normally written
|
||||
* Standard quake utils only ever write the TEX_SPECIAL flag.
|
||||
|
|
@ -707,7 +743,7 @@ CleanBSPTexinfoFlags(void)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < num_texinfo; i++, texinfo++)
|
||||
texinfo->flags &= TEX_SPECIAL|TEX_PHONG_ANGLE_MASK; // still write TEX_PHONG_ANGLE_MASK
|
||||
texinfo->flags &= TEX_SPECIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -744,6 +780,7 @@ FinishBSPFile(void)
|
|||
texinfo->count = texinfo->index;
|
||||
}
|
||||
|
||||
WriteExtendedTexinfoFlags();
|
||||
CleanBSPTexinfoFlags();
|
||||
WriteBSPFile();
|
||||
PrintBSPFileSizes();
|
||||
|
|
|
|||
Loading…
Reference in New Issue