diff --git a/include/light/light.h b/include/light/light.h index 86938c93..1960d530 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -53,6 +53,12 @@ typedef struct traceinfo_s { vec3_t dir; } traceinfo_t; +/* Stopped by solid and sky */ +bool TraceFaces (traceinfo_t *ti, int node, const vec3_t start, const vec3_t end); + + +int Light_PointContents( const vec3_t point ); + typedef struct { const dplane_t *dplane; int side; @@ -110,31 +116,7 @@ typedef struct { qboolean nodirt; vec_t phongangle; } modelinfo_t; - -void MakeTnodes_embree(const bsp2_t *bsp); - -// returns true if un-occluded. dir is the direction to trace in (doesn't need to be normalized) -qboolean -TestLight_embree(const vec3_t start, const vec3_t dir, vec_t dist, const modelinfo_t *model); -// returns true if sky is visible. dirn must be the normalized direction _away_ from the sun -qboolean -TestSky_embree(const vec3_t start, const vec3_t dirn, const modelinfo_t *model); - -// returns true if occluded -qboolean -DirtTrace_embree(const vec3_t start, const vec3_t dir, vec_t dist, vec_t *hitdist, vec_t *normal, const modelinfo_t *model); - -qboolean -FaceTrace_embree(const vec3_t start, const vec3_t dir, vec3_t hitpoint, const bsp2_dface_t **hitface); - - -// returns true if the trace from start to stop hits something solid. -// only tests the selfshadow model. -qboolean -CalcPointsTrace_embree(const vec3_t start, const vec3_t dir, vec_t dist, vec_t *hitdist, vec_t *normal, const modelinfo_t *model); - - typedef struct sun_s { vec3_t sunvec; lightsample_t sunlight; diff --git a/light/CMakeLists.txt b/light/CMakeLists.txt index 71b71cdc..aa6eebd0 100644 --- a/light/CMakeLists.txt +++ b/light/CMakeLists.txt @@ -10,7 +10,7 @@ set(LIGHT_SOURCES entities.c litfile.c ltface.c - trace_embree.cc + trace.c light.cc ${CMAKE_SOURCE_DIR}/common/bspfile.c ${CMAKE_SOURCE_DIR}/common/cmdlib.c @@ -20,11 +20,8 @@ set(LIGHT_SOURCES ${COMMON_INCLUDES} ${LIGHT_INCLUDES}) -FIND_PACKAGE(embree 2.0 REQUIRED) -INCLUDE_DIRECTORIES(${EMBREE_INCLUDE_DIRS}) - add_executable(light ${LIGHT_SOURCES}) -target_link_libraries (light ${CMAKE_THREAD_LIBS_INIT} ${EMBREE_LIBRARY}) +target_link_libraries (light ${CMAKE_THREAD_LIBS_INIT}) set_property(TARGET light PROPERTY CXX_STANDARD 11) set_property(TARGET light PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/light/light.cc b/light/light.cc index 23fafb4f..94a665d6 100644 --- a/light/light.cc +++ b/light/light.cc @@ -24,9 +24,6 @@ #include #include -#include -#include - #include #include #include @@ -161,9 +158,6 @@ LightThread(void *arg) const modelinfo_t *face_modelinfo; struct ltface_ctx *ctx; - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); - _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); - while (1) { facenum = GetThreadWork(); if (facenum == -1) @@ -898,7 +892,7 @@ main(int argc, const char **argv) if (dirty) SetupDirt(); - MakeTnodes_embree(bsp); + MakeTnodes(bsp); LightWorld(&bspdata, !!lmscaleoverride); /*invalidate any bspx lighting info early*/ diff --git a/light/ltface.c b/light/ltface.c index d63d5506..5a246b7e 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -593,14 +593,14 @@ CheckObstructed(const lightsurf_t *surf, const vec3_t offset, const vec_t us, co TexCoordToWorld(us + (x/10.0), ut + (y/10.0), &surf->texorg, testpoint); VectorAdd(testpoint, offset, testpoint); - vec3_t tracedir; - VectorSubtract(testpoint, surf->midpoint, tracedir); - const vec_t dist = VectorNormalize(tracedir); - - vec_t hitdist = 0; - vec3_t hitnormal = {0}; - if (CalcPointsTrace_embree(surf->midpoint, tracedir, dist, &hitdist, hitnormal, surf->modelinfo)) { + vec3_t hitpoint = {0}; + if (DirtTrace(surf->midpoint, testpoint, surf->modelinfo->model, hitpoint)) { // make a corrected point + + vec3_t tracedir; + VectorSubtract(hitpoint, surf->midpoint, tracedir); + const vec_t hitdist = VectorNormalize(tracedir); + VectorMA(surf->midpoint, qmax(0.0f, hitdist - 0.1f), tracedir, corrected); return true; } @@ -1163,7 +1163,7 @@ LightFace_Entity(const entity_t *entity, const lightsample_t *light, /* HACK: support lights lying exactly on a face by only tracing up to 0.1 units from the light */ surfpointToLightDist = qmax(0.0f, surfpointToLightDist - 0.01f); - if (!TestLight_embree(surfpoint, surfpointToLightDir, surfpointToLightDist, modelinfo)) + if (!TestLight(entity->origin, surfpoint, shadowself)) continue; angle = (1.0 - entity->anglescale) + entity->anglescale * angle; @@ -1230,17 +1230,13 @@ LightFace_Sky(const sun_t *sun, const lightsurf_t *lightsurf, lightmap_t *lightm surfnorm = lightsurf->normals[0]; for (i = 0; i < lightsurf->numpoints; i++, sample++, surfpoint += 3, surfnorm += 3) { vec_t value; - - // FIXME: slow - vec3_t sundir; - VectorCopy(sun->sunvec, sundir); - VectorNormalize(sundir); - if (!TestSky_embree(surfpoint, sundir, modelinfo)) - continue; angle = DotProduct(incoming, surfnorm); if (angle < 0) continue; + + if (!TestSky(surfpoint, sun->sunvec, shadowself)) + continue; angle = (1.0 - sun->anglescale) + sun->anglescale * angle; value = angle * sun->sunlight.light; @@ -1307,10 +1303,7 @@ LightFace_Min(const lightsample_t *light, for (j = 0; j < lightsurf->numpoints; j++, sample++, surfpoint += 3) { if (addminlight || sample->light < (*entity)->light.light) { vec_t value = (*entity)->light.light; - vec3_t ray; - VectorSubtract(surfpoint, (*entity)->origin, ray); - vec_t dist = VectorNormalize(ray); - trace = TestLight_embree((*entity)->origin, ray, dist, modelinfo); + trace = TestLight((*entity)->origin, surfpoint, shadowself); if (!trace) continue; value *= Dirt_GetScaleFactor(lightsurf->occlusion[j], (*entity), lightsurf); @@ -1438,16 +1431,54 @@ void SetupDirt( void ) { logprint("%9d dirtmap vectors\n", numDirtVectors ); } +/* + * ============ + * DirtTrace + * + * returns true if the trace from start to stop hits something solid, + * or if it started in the void. + * ============ + */ +qboolean +DirtTrace(const vec3_t start, const vec3_t stop, const dmodel_t *self, vec3_t hitpoint_out) +{ + const modelinfo_t *const *model; + traceinfo_t ti = {0}; + + VectorSubtract(stop, start, ti.dir); + VectorNormalize(ti.dir); + + if (self) { + if (TraceFaces (&ti, self->headnode[0], start, stop)) { + VectorCopy(ti.point, hitpoint_out); + return !ti.hitsky; + } + } + + /* Check against the list of global shadow casters */ + for (model = tracelist; *model; model++) { + if ((*model)->model == self) + continue; + if (TraceFaces (&ti, (*model)->model->headnode[0], start, stop)) { + VectorCopy(ti.point, hitpoint_out); + return !ti.hitsky; + } + } + + return false; +} + /* * ============ * DirtForSample * ============ */ static vec_t -DirtForSample(const modelinfo_t *modelinfo, const vec3_t origin, const vec3_t normal){ +DirtForSample(const dmodel_t *model, const vec3_t origin, const vec3_t normal){ int i; float gatherDirt, angle, elevation, ooDepth; - vec3_t worldUp, myUp, myRt, temp, direction; + vec3_t worldUp, myUp, myRt, temp, direction, displacement; + vec3_t traceEnd, traceHitpoint; /* dummy check */ if ( !dirty ) { @@ -1491,10 +1522,13 @@ DirtForSample(const modelinfo_t *modelinfo, const vec3_t origin, const vec3_t no direction[ 1 ] = myRt[ 1 ] * temp[ 0 ] + myUp[ 1 ] * temp[ 1 ] + normal[ 1 ] * temp[ 2 ]; direction[ 2 ] = myRt[ 2 ] * temp[ 0 ] + myUp[ 2 ] * temp[ 1 ] + normal[ 2 ] * temp[ 2 ]; + /* set endpoint */ + VectorMA( origin, dirtDepth, direction, traceEnd ); + /* trace */ - vec_t displacement_len; - if (DirtTrace_embree(origin, direction, dirtDepth, &displacement_len, NULL, modelinfo)) { - gatherDirt += 1.0f - ooDepth * displacement_len; + if (DirtTrace(origin, traceEnd, model, traceHitpoint)) { + VectorSubtract( traceHitpoint, origin, displacement ); + gatherDirt += 1.0f - ooDepth * VectorLength( displacement ); } } } else { @@ -1505,18 +1539,24 @@ DirtForSample(const modelinfo_t *modelinfo, const vec3_t origin, const vec3_t no direction[ 1 ] = myRt[ 1 ] * dirtVectors[ i ][ 0 ] + myUp[ 1 ] * dirtVectors[ i ][ 1 ] + normal[ 1 ] * dirtVectors[ i ][ 2 ]; direction[ 2 ] = myRt[ 2 ] * dirtVectors[ i ][ 0 ] + myUp[ 2 ] * dirtVectors[ i ][ 1 ] + normal[ 2 ] * dirtVectors[ i ][ 2 ]; + /* set endpoint */ + VectorMA( origin, dirtDepth, direction, traceEnd ); + /* trace */ - vec_t displacement_len; - if (DirtTrace_embree(origin, direction, dirtDepth, &displacement_len, NULL, modelinfo)) { - gatherDirt += 1.0f - ooDepth * displacement_len; + if (DirtTrace(origin, traceEnd, model, traceHitpoint)) { + VectorSubtract( traceHitpoint, origin, displacement ); + gatherDirt += 1.0f - ooDepth * VectorLength( displacement ); } } } /* direct ray */ - vec_t displacement_len; - if (DirtTrace_embree(origin, normal, dirtDepth, &displacement_len, NULL, modelinfo)) { - gatherDirt += 1.0f - ooDepth * displacement_len; + VectorMA( origin, dirtDepth, normal, traceEnd ); + + /* trace */ + if (DirtTrace(origin, traceEnd, model, traceHitpoint)) { + VectorSubtract( traceHitpoint, origin, displacement ); + gatherDirt += 1.0f - ooDepth * VectorLength( displacement ); } /* save gatherDirt, the rest of the scaling of the dirt value is done @@ -1542,7 +1582,7 @@ LightFace_CalculateDirt(lightsurf_t *lightsurf) /* Check each point... */ surfpoint = lightsurf->points[0]; for (i = 0; i < lightsurf->numpoints; i++, surfpoint += 3) { - lightsurf->occlusion[i] = DirtForSample(modelinfo, surfpoint, plane->normal); + lightsurf->occlusion[i] = DirtForSample(modelinfo->model, surfpoint, plane->normal); } } diff --git a/light/trace.c b/light/trace.c index 36a5a430..42227bb6 100644 --- a/light/trace.c +++ b/light/trace.c @@ -500,15 +500,15 @@ TraceLine(const dmodel_t *model, const int traceflags, qboolean TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self) { - const dmodel_t *const *model; + const modelinfo_t *const *model; const int traceflags = TRACE_HIT_SOLID; int result = TRACE_HIT_NONE; /* Check against the list of global shadow casters */ for (model = tracelist; *model; model++) { - if (*model == self) + if ((*model)->model == self) continue; - result = TraceLine(*model, traceflags, start, stop, NULL); + result = TraceLine((*model)->model, traceflags, start, stop, NULL); if (result != TRACE_HIT_NONE) break; } @@ -523,7 +523,7 @@ TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self) qboolean TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self) { - const dmodel_t *const *model; + const modelinfo_t *const *model; int traceflags = TRACE_HIT_SKY | TRACE_HIT_SOLID; int result = TRACE_HIT_NONE; vec3_t stop; @@ -531,16 +531,16 @@ TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self) /* Trace towards the sunlight for a sky brush */ VectorAdd(dirn, start, stop); - result = TraceLine(tracelist[0], traceflags, start, stop, &hit); + result = TraceLine(tracelist[0]->model, traceflags, start, stop, &hit); if (result != TRACE_HIT_SKY) return false; /* If good, check it isn't shadowed by another model */ traceflags = TRACE_HIT_SOLID; for (model = tracelist + 1; *model; model++) { - if (*model == self) + if ((*model)->model == self) continue; - result = TraceLine(*model, traceflags, start, hit.point, NULL); + result = TraceLine((*model)->model, traceflags, start, hit.point, NULL); if (result != TRACE_HIT_NONE) return false; }