light: change CalcPoints to only trace the model the face belongs to

This commit is contained in:
Eric Wasylishen 2016-08-04 12:24:07 -06:00
parent 2a3b87bf1f
commit fcc54c547f
4 changed files with 87 additions and 5 deletions

View File

@ -54,6 +54,9 @@ qboolean TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self);
qboolean TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self);
hittype_t DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, const dmodel_t *self, vec_t *hitdist_out, plane_t *hitplane_out, const bsp2_dface_t **face_out);
// used for CalcPoints
bool IntersectSingleModel(const vec3_t start, const vec3_t dir, vec_t dist, const dmodel_t *self, vec_t *hitdist_out);
class raystream_t {
public:
virtual void pushRay(int i, const vec_t *origin, const vec3_t dir, float dist, const dmodel_t *selfshadow, const vec_t *color = nullptr) = 0;
@ -77,6 +80,7 @@ void Embree_TraceInit(const bsp2_t *bsp);
qboolean Embree_TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self);
qboolean Embree_TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self);
hittype_t Embree_DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, const dmodel_t *self, vec_t *hitdist_out, plane_t *hitplane_out, const bsp2_dface_t **face_out);
bool Embree_IntersectSingleModel(const vec3_t start, const vec3_t dir, vec_t dist, const dmodel_t *self, vec_t *hitdist_out);
raystream_t *Embree_MakeRayStream(int maxrays);

View File

@ -591,10 +591,6 @@ 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);
plane_t hitplane = {0};
const dmodel_t *selfshadow = (surf->modelinfo->shadowself.boolValue()) ? surf->modelinfo->model : NULL;
vec3_t dirn;
VectorSubtract(testpoint, surf->midpoint, dirn);
vec_t dist = VectorNormalize(dirn);
@ -604,7 +600,7 @@ CheckObstructed(const lightsurf_t *surf, const vec3_t offset, const vec_t us, co
// trace from surf->midpoint to testpoint
vec_t hitdist = 0;
if (hittype_t::SOLID == DirtTrace(surf->midpoint, dirn, dist, selfshadow, &hitdist, &hitplane, NULL)) {
if (IntersectSingleModel(surf->midpoint, dirn, dist, surf->modelinfo->model, &hitdist)) {
// make a corrected point
VectorMA(surf->midpoint, qmax(0.0f, hitdist - 0.25f), dirn, corrected);
return true;

View File

@ -694,6 +694,24 @@ BSP_DirtTrace(const vec3_t start, const vec3_t dirn, const vec_t dist, const dmo
return hittype_t::NONE;
}
bool BSP_IntersectSingleModel(const vec3_t start, const vec3_t dirn, vec_t dist, const dmodel_t *self, vec_t *hitdist_out)
{
vec3_t stop;
VectorMA(start, dist, dirn, stop);
traceinfo_t ti = {0};
VectorCopy(dirn, ti.dir);
if (TraceFaces (&ti, self->headnode[0], start, stop)) {
if (hitdist_out) {
vec3_t delta;
VectorSubtract(ti.point, start, delta);
*hitdist_out = VectorLength(delta);
}
return true;
}
return false;
}
/*
=============
@ -822,6 +840,19 @@ hittype_t DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, const dmo
Error("no backend available");
}
bool IntersectSingleModel(const vec3_t start, const vec3_t dir, vec_t dist, const dmodel_t *self, vec_t *hitdist_out)
{
#ifdef HAVE_EMBREE
if (rtbackend == backend_embree) {
return Embree_IntersectSingleModel(start, dir, dist, self, hitdist_out);
}
#endif
if (rtbackend == backend_bsp) {
return BSP_IntersectSingleModel(start, dir, dist, self, hitdist_out);
}
Error("no backend available");
}
class bsp_ray_t {
public:
int _pointindex;

View File

@ -29,6 +29,8 @@
#include <malloc.h>
#endif
using namespace std;
static constexpr float MAX_SKY_RAY_DEPTH = 8192.0f;
/**
@ -101,6 +103,29 @@ CreateGeometry(const bsp2_t *bsp, RTCScene scene, const std::vector<const bsp2_d
return s;
}
// Creates a scene with just the faces in this model,
// used by CalcPoints.
// Liquids are left out but sky faces are included
RTCScene CreatePerModelScene(RTCDevice device, const bsp2_t *bsp, const dmodel_t *model) {
std::vector<const bsp2_dface_t *> faces;
for (int i=0; i<model->numfaces; i++) {
const bsp2_dface_t *face = &bsp->dfaces[model->firstface + i];
const char *texname = Face_TextureName(bsp, face);
if (texname[0] == '*') {
// ignore liquids
} else {
faces.push_back(face);
}
}
RTCScene scene = rtcDeviceNewScene(device, RTC_SCENE_STATIC | RTC_SCENE_COHERENT, RTC_INTERSECT1);
sceneinfo geom = CreateGeometry(bsp, scene, faces);
rtcCommit(scene);
return scene;
}
RTCDevice device;
RTCScene scene;
/* global shadow casters */
@ -225,6 +250,8 @@ Embree_FilterFuncN(int* valid,
}
}
vector<RTCScene> perModelScenes;
void
Embree_TraceInit(const bsp2_t *bsp)
{
@ -267,6 +294,12 @@ Embree_TraceInit(const bsp2_t *bsp)
Error("embree must be built with ray masks disabled");
}
// set up per-model scenes, used for CalcPoints
for (int i=0; i<bsp->nummodels; i++) {
perModelScenes.push_back(CreatePerModelScene(device, bsp, &bsp->dmodels[i]));
}
assert(perModelScenes.size() == bsp->nummodels);
scene = rtcDeviceNewScene(device, RTC_SCENE_STATIC | RTC_SCENE_COHERENT, RTC_INTERSECT1 | RTC_INTERSECT_STREAM);
skygeom = CreateGeometry(bsp, scene, skyfaces);
solidgeom = CreateGeometry(bsp, scene, solidfaces);
@ -380,6 +413,24 @@ hittype_t Embree_DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, co
}
}
// used for CalcPoints
bool Embree_IntersectSingleModel(const vec3_t start, const vec3_t dir, vec_t dist, const dmodel_t *self, vec_t *hitdist_out)
{
const int modelnum = self - bsp_static->dmodels;
RTCScene singleModelScene = perModelScenes.at(modelnum);
RTCRay ray = SetupRay(start, dir, dist, nullptr);
rtcIntersect(singleModelScene, ray);
if (ray.geomID == RTC_INVALID_GEOMETRY_ID)
return false; // no obstruction
if (hitdist_out) {
*hitdist_out = ray.tfar;
}
return true;
}
//enum class streamstate_t {
// READY, DID_OCCLUDE, DID_INTERSECT
//};