light: implement self shadowing option for brush models
Brush models can now self shadow without casting shadows on their environment, using the "_shadowself" entity key. Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
parent
dc39137874
commit
d6ef23453a
|
|
@ -1,6 +1,6 @@
|
|||
Unreleased
|
||||
|
||||
* light: brush model entities with the "_shadow" key will cast shadows
|
||||
* light: implemented self shadowing and full shadows for brush models
|
||||
|
||||
2013-03-07 TyrUtils v0.6
|
||||
|
||||
|
|
|
|||
|
|
@ -33,13 +33,14 @@
|
|||
|
||||
#define MAXLIGHTS 1024
|
||||
|
||||
qboolean TestSky(const vec3_t start, const vec3_t dirn);
|
||||
qboolean TestSky(const vec3_t start, const vec3_t dirn, vec3_t skypoint);
|
||||
qboolean TestLine(const vec3_t start, const vec3_t stop);
|
||||
qboolean TestLineModel(const dmodel_t *model,
|
||||
const vec3_t start, const vec3_t stop);
|
||||
|
||||
typedef struct {
|
||||
const dmodel_t *model;
|
||||
qboolean shadowself;
|
||||
int minlight;
|
||||
vec3_t mincolor;
|
||||
vec3_t offset;
|
||||
|
|
|
|||
23
light.txt
23
light.txt
|
|
@ -68,6 +68,7 @@ ENTITY PARAMETERS
|
|||
Set the brightness of the sunlight coming from an unseen sun in the
|
||||
sky. Sky brushes (or more accurately bsp leafs with sky contents) will
|
||||
emit sunlight at an angle specified by the "_sun_mangle" paramter.
|
||||
Default 0.
|
||||
|
||||
"_sun_mangle" "x y z"
|
||||
|
||||
|
|
@ -75,12 +76,14 @@ ENTITY PARAMETERS
|
|||
in degrees. Yaw specifies the angle around the Z-axis from 0 to 359
|
||||
degrees and pitch specifies the angle from 90 (straight up) to -90
|
||||
(straight down). Roll has no effect, so use any value (e.g. 0).
|
||||
Default is straight down ("0 -90 0").
|
||||
|
||||
"_sunlight_color" "r g b"
|
||||
|
||||
Specify red(r), green(g) and blue(b) components for the colour of the
|
||||
sunlight. RGB component values are between -255 and 255. Negative
|
||||
values will cause colour subtraction from light cast by other entities.
|
||||
Default is white light ("255 255 255").
|
||||
|
||||
MODEL PARAMETERS
|
||||
|
||||
|
|
@ -89,17 +92,27 @@ ENTITY PARAMETERS
|
|||
"_minlight" "n"
|
||||
|
||||
Set the minimum light level for any surface of the brush model.
|
||||
Default 0.
|
||||
|
||||
"_mincolor" "r g b"
|
||||
|
||||
Specify red(r), green(g) and blue(b) components for the colour of the
|
||||
minlight. RGB component values are between 0 and 255.
|
||||
minlight. RGB component values are between 0 and 255. Default is
|
||||
white light ("255 255 255").
|
||||
|
||||
"_shadow" "1"
|
||||
"_shadow" "n"
|
||||
|
||||
This model will cast shadows. Note that this doesn't magically give
|
||||
Quake dynamic lighting powers, so the shadows will not move if the
|
||||
model moves.
|
||||
If n is 1, this model will cast shadows on other models and itself
|
||||
(i.e. "_shadow" implies "_shadowself"). Note that this doesn't
|
||||
magically give Quake dynamic lighting powers, so the shadows will
|
||||
not move if the model moves. Default 0.
|
||||
|
||||
"_shadowself" "n"
|
||||
|
||||
If n is 1, this model will cast shadows on itself if one part
|
||||
of the model blocks the light from another model surface. This
|
||||
can be a better compromise for moving models than full
|
||||
shadowing. Default 0.
|
||||
|
||||
LIGHT PARAMETERS
|
||||
|
||||
|
|
|
|||
|
|
@ -130,10 +130,15 @@ FindModelInfo(void)
|
|||
Error("%s: Couldn't find entity for model %s.\n", __func__,
|
||||
modelname);
|
||||
|
||||
/* Check if this model will cast shadows */
|
||||
/* Check if this model will cast shadows (shadow => shadowself) */
|
||||
shadow = atoi(ValueForKey(entity, "_shadow"));
|
||||
if (shadow)
|
||||
if (shadow) {
|
||||
shadowmodels[numshadowmodels++] = &dmodels[i];
|
||||
} else {
|
||||
shadow = atoi(ValueForKey(entity, "_shadowself"));
|
||||
if (shadow)
|
||||
modelinfo[i].shadowself = true;
|
||||
}
|
||||
|
||||
/* Set up the offset for rotate_* entities */
|
||||
attribute = ValueForKey(entity, "classname");
|
||||
|
|
|
|||
|
|
@ -125,9 +125,8 @@ solve3(const vec3_t mtx[3], const int r[3], const int c[3],
|
|||
#define SINGLEMAP (18*18*4*4)
|
||||
|
||||
typedef struct {
|
||||
vec_t *light;
|
||||
|
||||
dface_t *face;
|
||||
const modelinfo_t *modelinfo;
|
||||
const dface_t *face;
|
||||
vec_t facedist;
|
||||
vec3_t facenormal;
|
||||
|
||||
|
|
@ -270,7 +269,7 @@ face_centroid(const dface_t *f, vec3_t out)
|
|||
static void
|
||||
CalcFaceExtents(lightinfo_t *l, const vec3_t offset)
|
||||
{
|
||||
dface_t *s;
|
||||
const dface_t *s;
|
||||
vec_t mins[2], maxs[2], val;
|
||||
vec3_t centroid;
|
||||
int i, j, e;
|
||||
|
|
@ -526,6 +525,9 @@ SingleLightFace(const entity_t *light, lightinfo_t *l, const vec3_t colors)
|
|||
/* Test for line of sight */
|
||||
if (!TestLine(light->origin, surf))
|
||||
continue;
|
||||
if (l->modelinfo->shadowself)
|
||||
if (!TestLineModel(l->modelinfo->model, light->origin, surf))
|
||||
continue;
|
||||
|
||||
angle = (1.0 - scalecos) + scalecos * angle;
|
||||
add = GetLightValue(light, dist) * angle * spotscale;
|
||||
|
|
@ -637,12 +639,16 @@ SkyLightFace(lightinfo_t *l, const vec3_t colors)
|
|||
#else
|
||||
surf = l->surfpt[0];
|
||||
for (i = 0; i < l->numsurfpt; i++, surf += 3) {
|
||||
if (TestSky(surf, sunvec)) {
|
||||
lightmap[i] += angle * sunlight;
|
||||
if (colored)
|
||||
VectorMA(colormap[i], angle * sunlight / 255.0f, colors,
|
||||
colormap[i]);
|
||||
}
|
||||
vec3_t skypoint;
|
||||
if (!TestSky(surf, sunvec, skypoint))
|
||||
continue;
|
||||
if (l->modelinfo->shadowself)
|
||||
if (!TestLineModel(l->modelinfo->model, surf, skypoint))
|
||||
continue;
|
||||
lightmap[i] += angle * sunlight;
|
||||
if (colored)
|
||||
VectorMA(colormap[i], angle * sunlight / 255.0f, colors,
|
||||
colormap[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -726,16 +732,29 @@ FixMinlight(lightinfo_t *l, const int minlight, const vec3_t mincolor)
|
|||
trace = TestLine(entity->origin, l->surfpt[j]);
|
||||
if (!trace)
|
||||
continue;
|
||||
if (l->modelinfo->shadowself) {
|
||||
trace = TestLineModel(l->modelinfo->model, entity->origin, l->surfpt[j]);
|
||||
if (!trace)
|
||||
continue;
|
||||
}
|
||||
lightmap[j] = entity->light;
|
||||
}
|
||||
if (!colored)
|
||||
continue;
|
||||
for (k = 0; k < 3; k++) {
|
||||
if (colormap[j][k] < mincolor[k]) {
|
||||
if (!trace)
|
||||
if (!trace) {
|
||||
trace = TestLine(entity->origin, l->surfpt[j]);
|
||||
if (trace)
|
||||
colormap[j][k] = mincolor[k];
|
||||
if (!trace)
|
||||
break;
|
||||
if (l->modelinfo->shadowself) {
|
||||
trace = TestLineModel(l->modelinfo->model,
|
||||
entity->origin, l->surfpt[j]);
|
||||
if (!trace)
|
||||
break;
|
||||
}
|
||||
}
|
||||
colormap[j][k] = mincolor[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -829,6 +848,7 @@ LightFace(int surfnum, const modelinfo_t *modelinfo)
|
|||
return; /* non-lit texture */
|
||||
|
||||
memset(&l, 0, sizeof(l));
|
||||
l.modelinfo = modelinfo;
|
||||
l.face = face;
|
||||
|
||||
/* rotate plane */
|
||||
|
|
|
|||
|
|
@ -215,17 +215,16 @@ TestLineModel(const dmodel_t *model, const vec3_t start, const vec3_t stop)
|
|||
* a CONTENTS_SOLID node.
|
||||
*/
|
||||
qboolean
|
||||
TestSky(const vec3_t start, const vec3_t dirn)
|
||||
TestSky(const vec3_t start, const vec3_t dirn, vec3_t skypoint)
|
||||
{
|
||||
vec3_t stop;
|
||||
const dmodel_t *const *model;
|
||||
|
||||
VectorAdd(dirn, start, stop);
|
||||
if (!TestLineOrSky(tracelist[0], start, stop, true, stop))
|
||||
VectorAdd(dirn, start, skypoint);
|
||||
if (!TestLineOrSky(tracelist[0], start, skypoint, true, skypoint))
|
||||
return false;
|
||||
|
||||
for (model = tracelist + 1; *model; model++)
|
||||
if (!TestLineModel(*model, start, stop))
|
||||
if (!TestLineModel(*model, start, skypoint))
|
||||
break;
|
||||
|
||||
return !*model;
|
||||
|
|
|
|||
Loading…
Reference in New Issue