diff --git a/changelog.txt b/changelog.txt index 3e896b06..37271139 100644 --- a/changelog.txt +++ b/changelog.txt @@ -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 diff --git a/include/light/light.h b/include/light/light.h index c4efc1f6..c2cdeba0 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -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; diff --git a/light.txt b/light.txt index 04ce7b00..067a7bfd 100644 --- a/light.txt +++ b/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 diff --git a/light/light.c b/light/light.c index 847f93c1..4d6ce306 100644 --- a/light/light.c +++ b/light/light.c @@ -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"); diff --git a/light/ltface.c b/light/ltface.c index 1de3ae68..239a8638 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -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 */ diff --git a/light/trace.c b/light/trace.c index 533577ad..3ca23f68 100644 --- a/light/trace.c +++ b/light/trace.c @@ -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;