wip
This commit is contained in:
parent
7b5824ad2b
commit
b63a5e64ac
|
|
@ -37,7 +37,7 @@ set(LIGHT_SOURCES
|
||||||
${LIGHT_INCLUDES})
|
${LIGHT_INCLUDES})
|
||||||
|
|
||||||
|
|
||||||
FIND_PACKAGE(embree 2.0 REQUIRED)
|
FIND_PACKAGE(embree 3.0 REQUIRED)
|
||||||
|
|
||||||
if (embree_FOUND)
|
if (embree_FOUND)
|
||||||
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
#include <light/ltface.hh>
|
#include <light/ltface.hh>
|
||||||
#include <common/bsputils.hh>
|
#include <common/bsputils.hh>
|
||||||
#include <common/polylib.hh>
|
#include <common/polylib.hh>
|
||||||
#include <embree2/rtcore.h>
|
#include <embree3/rtcore.h>
|
||||||
#include <embree2/rtcore_ray.h>
|
#include <embree3/rtcore_ray.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
@ -48,13 +48,29 @@ public:
|
||||||
class raystream_embree_t;
|
class raystream_embree_t;
|
||||||
|
|
||||||
struct ray_source_info {
|
struct ray_source_info {
|
||||||
|
RTCIntersectContext embreeCtx;
|
||||||
|
|
||||||
|
static struct ray_source_info* getRaySourceInfoFromEmbreeCtx(const RTCIntersectContext* ctx) {
|
||||||
|
static_assert(std::is_standard_layout<ray_source_info>(), "");
|
||||||
|
// standard layout classes allow this conversion because embreeCtx is the first member
|
||||||
|
return reinterpret_cast<ray_source_info *>(const_cast<RTCIntersectContext*>(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCIntersectContext* castToEmbreeContext() {
|
||||||
|
return reinterpret_cast<RTCIntersectContext*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
raystream_embree_t *raystream; // may be null if this ray is not from a ray stream
|
raystream_embree_t *raystream; // may be null if this ray is not from a ray stream
|
||||||
const modelinfo_t *self;
|
const modelinfo_t *self;
|
||||||
|
|
||||||
ray_source_info(raystream_embree_t *raystream_,
|
ray_source_info(enum RTCIntersectContextFlags intersectionFlags,
|
||||||
|
raystream_embree_t *raystream_,
|
||||||
const modelinfo_t *self_) :
|
const modelinfo_t *self_) :
|
||||||
raystream(raystream_),
|
raystream(raystream_),
|
||||||
self(self_) {}
|
self(self_) {
|
||||||
|
rtcInitIntersectContext(&embreeCtx);
|
||||||
|
embreeCtx.flags = intersectionFlags;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -78,7 +94,7 @@ Face_Alpha(const modelinfo_t *modelinfo, const bsp2_dface_t *face)
|
||||||
}
|
}
|
||||||
|
|
||||||
sceneinfo
|
sceneinfo
|
||||||
CreateGeometry(const mbsp_t *bsp, RTCScene scene, const std::vector<const bsp2_dface_t *> &faces)
|
CreateGeometry(const mbsp_t *bsp, RTCDevice device, RTCScene scene, const std::vector<const bsp2_dface_t *> &faces)
|
||||||
{
|
{
|
||||||
// count triangles
|
// count triangles
|
||||||
int numtris = 0;
|
int numtris = 0;
|
||||||
|
|
@ -88,13 +104,18 @@ CreateGeometry(const mbsp_t *bsp, RTCScene scene, const std::vector<const bsp2_d
|
||||||
numtris += (face->numedges - 2);
|
numtris += (face->numedges - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned geomID = rtcNewTriangleMesh(scene, RTC_GEOMETRY_STATIC, numtris, bsp->numvertexes);
|
unsigned int geomID;
|
||||||
|
RTCGeometry geom_0 = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
||||||
|
rtcSetGeometryBuildQuality(geom_0,RTC_BUILD_QUALITY_MEDIUM);
|
||||||
|
rtcSetGeometryTimeStepCount(geom_0,1);
|
||||||
|
geomID = rtcAttachGeometry(scene,geom_0);
|
||||||
|
rtcReleaseGeometry(geom_0);
|
||||||
|
|
||||||
struct Vertex { float point[4]; }; //4th element is padding
|
struct Vertex { float point[4]; }; //4th element is padding
|
||||||
struct Triangle { int v0, v1, v2; };
|
struct Triangle { int v0, v1, v2; };
|
||||||
|
|
||||||
// fill in vertices
|
// fill in vertices
|
||||||
Vertex* vertices = (Vertex*) rtcMapBuffer(scene, geomID, RTC_VERTEX_BUFFER);
|
Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),bsp->numvertexes);
|
||||||
for (int i=0; i<bsp->numvertexes; i++) {
|
for (int i=0; i<bsp->numvertexes; i++) {
|
||||||
const dvertex_t *dvertex = &bsp->dvertexes[i];
|
const dvertex_t *dvertex = &bsp->dvertexes[i];
|
||||||
Vertex *vert = &vertices[i];
|
Vertex *vert = &vertices[i];
|
||||||
|
|
@ -102,13 +123,13 @@ CreateGeometry(const mbsp_t *bsp, RTCScene scene, const std::vector<const bsp2_d
|
||||||
vert->point[j] = dvertex->point[j];
|
vert->point[j] = dvertex->point[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtcUnmapBuffer(scene, geomID, RTC_VERTEX_BUFFER);
|
|
||||||
|
|
||||||
sceneinfo s;
|
sceneinfo s;
|
||||||
s.geomID = geomID;
|
s.geomID = geomID;
|
||||||
|
|
||||||
// fill in triangles
|
// fill in triangles
|
||||||
Triangle* triangles = (Triangle*) rtcMapBuffer(scene, geomID, RTC_INDEX_BUFFER);
|
Triangle* triangles = (Triangle*) rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,3*sizeof(int),numtris);
|
||||||
int tri_index = 0;
|
int tri_index = 0;
|
||||||
for (const bsp2_dface_t *face : faces) {
|
for (const bsp2_dface_t *face : faces) {
|
||||||
if (face->numedges < 3)
|
if (face->numedges < 3)
|
||||||
|
|
@ -127,13 +148,14 @@ CreateGeometry(const mbsp_t *bsp, RTCScene scene, const std::vector<const bsp2_d
|
||||||
s.triToModelinfo.push_back(modelinfo);
|
s.triToModelinfo.push_back(modelinfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtcUnmapBuffer(scene, geomID, RTC_INDEX_BUFFER);
|
|
||||||
|
|
||||||
|
|
||||||
|
rtcCommitGeometry(geom_0);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateGeometryFromWindings(RTCScene scene, const std::vector<winding_t *> &windings)
|
CreateGeometryFromWindings(RTCDevice device, RTCScene scene, const std::vector<winding_t *> &windings)
|
||||||
{
|
{
|
||||||
if (windings.empty())
|
if (windings.empty())
|
||||||
return;
|
return;
|
||||||
|
|
@ -147,13 +169,17 @@ CreateGeometryFromWindings(RTCScene scene, const std::vector<winding_t *> &windi
|
||||||
numverts += winding->numpoints;
|
numverts += winding->numpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned geomID = rtcNewTriangleMesh(scene, RTC_GEOMETRY_STATIC, numtris, numverts);
|
RTCGeometry geom_1 = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
|
||||||
|
rtcSetGeometryBuildQuality(geom_1,RTC_BUILD_QUALITY_MEDIUM);
|
||||||
|
rtcSetGeometryTimeStepCount(geom_1,1);
|
||||||
|
const unsigned int geomID = rtcAttachGeometry(scene,geom_1);
|
||||||
|
rtcReleaseGeometry(geom_1);
|
||||||
|
|
||||||
struct Vertex { float point[4]; }; //4th element is padding
|
struct Vertex { float point[4]; }; //4th element is padding
|
||||||
struct Triangle { int v0, v1, v2; };
|
struct Triangle { int v0, v1, v2; };
|
||||||
|
|
||||||
// fill in vertices
|
// fill in vertices
|
||||||
Vertex* vertices = (Vertex*) rtcMapBuffer(scene, geomID, RTC_VERTEX_BUFFER);
|
Vertex* vertices = (Vertex*) rtcSetNewGeometryBuffer(geom_1,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),numverts);
|
||||||
{
|
{
|
||||||
int vert_index = 0;
|
int vert_index = 0;
|
||||||
for (const auto &winding : windings) {
|
for (const auto &winding : windings) {
|
||||||
|
|
@ -165,10 +191,10 @@ CreateGeometryFromWindings(RTCScene scene, const std::vector<winding_t *> &windi
|
||||||
vert_index += winding->numpoints;
|
vert_index += winding->numpoints;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtcUnmapBuffer(scene, geomID, RTC_VERTEX_BUFFER);
|
|
||||||
|
|
||||||
// fill in triangles
|
// fill in triangles
|
||||||
Triangle* triangles = (Triangle*) rtcMapBuffer(scene, geomID, RTC_INDEX_BUFFER);
|
Triangle* triangles = (Triangle*) rtcSetNewGeometryBuffer(geom_1,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,3*sizeof(int),numtris);
|
||||||
int tri_index = 0;
|
int tri_index = 0;
|
||||||
int vert_index = 0;
|
int vert_index = 0;
|
||||||
for (const auto &winding : windings) {
|
for (const auto &winding : windings) {
|
||||||
|
|
@ -183,7 +209,7 @@ CreateGeometryFromWindings(RTCScene scene, const std::vector<winding_t *> &windi
|
||||||
}
|
}
|
||||||
Q_assert(vert_index == numverts);
|
Q_assert(vert_index == numverts);
|
||||||
Q_assert(tri_index == numtris);
|
Q_assert(tri_index == numtris);
|
||||||
rtcUnmapBuffer(scene, geomID, RTC_INDEX_BUFFER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RTCDevice device;
|
RTCDevice device;
|
||||||
|
|
@ -242,8 +268,8 @@ Embree_RayEndpoint(struct RTCRayN* ray, const struct RTCHitN* potentialHit, size
|
||||||
org[1] = RTCRayN_org_y(ray, N, i);
|
org[1] = RTCRayN_org_y(ray, N, i);
|
||||||
org[2] = RTCRayN_org_z(ray, N, i);
|
org[2] = RTCRayN_org_z(ray, N, i);
|
||||||
|
|
||||||
// N.B.: we want the distance to the potential hit, not RTCRayN_tfar (stopping dist?)
|
// N.B.: we want the distance to the potential hit
|
||||||
float tfar = RTCHitN_t(potentialHit, N, i);
|
float tfar = RTCRayN_tfar(ray, N, i);
|
||||||
|
|
||||||
VectorMA(org, tfar, dir, endpoint);
|
VectorMA(org, tfar, dir, endpoint);
|
||||||
}
|
}
|
||||||
|
|
@ -259,17 +285,20 @@ void AddDynamicOccluderToRay(const RTCIntersectContext* context, unsigned rayInd
|
||||||
// called to evaluate transparency
|
// called to evaluate transparency
|
||||||
template<filtertype_t filtertype>
|
template<filtertype_t filtertype>
|
||||||
static void
|
static void
|
||||||
Embree_FilterFuncN(int* valid,
|
Embree_FilterFuncN(const struct RTCFilterFunctionNArguments* args)
|
||||||
void* userDataPtr,
|
|
||||||
const RTCIntersectContext* context,
|
|
||||||
struct RTCRayN* ray,
|
|
||||||
const struct RTCHitN* potentialHit,
|
|
||||||
const size_t N)
|
|
||||||
{
|
{
|
||||||
|
// unpack arguments
|
||||||
|
int* valid = args->valid;
|
||||||
|
void* userDataPtr = args->geometryUserPtr;
|
||||||
|
const struct RTCIntersectContext* context = args->context;
|
||||||
|
struct RTCRayN* ray = args->ray;
|
||||||
|
struct RTCHitN* potentialHit = args->hit;
|
||||||
|
const size_t N = args->N;
|
||||||
|
|
||||||
const int VALID = -1;
|
const int VALID = -1;
|
||||||
const int INVALID = 0;
|
const int INVALID = 0;
|
||||||
|
|
||||||
const ray_source_info *rsi = static_cast<const ray_source_info *>(context->userRayExt);
|
const ray_source_info *rsi = ray_source_info::getRaySourceInfoFromEmbreeCtx(context);
|
||||||
|
|
||||||
for (size_t i=0; i<N; i++) {
|
for (size_t i=0; i<N; i++) {
|
||||||
if (valid[i] != VALID) {
|
if (valid[i] != VALID) {
|
||||||
|
|
@ -388,22 +417,7 @@ Embree_FilterFuncN(int* valid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept hit
|
// accept hit (do nothing)
|
||||||
if (filtertype == filtertype_t::OCCLUSION) {
|
|
||||||
RTCRayN_geomID(ray, N, i) = 0;
|
|
||||||
} else {
|
|
||||||
RTCRayN_Ng_x(ray, N, i) = RTCHitN_Ng_x(potentialHit, N, i);
|
|
||||||
RTCRayN_Ng_y(ray, N, i) = RTCHitN_Ng_y(potentialHit, N, i);
|
|
||||||
RTCRayN_Ng_z(ray, N, i) = RTCHitN_Ng_z(potentialHit, N, i);
|
|
||||||
|
|
||||||
RTCRayN_instID(ray, N, i) = RTCHitN_instID(potentialHit, N, i);
|
|
||||||
RTCRayN_geomID(ray, N, i) = RTCHitN_geomID(potentialHit, N, i);
|
|
||||||
RTCRayN_primID(ray, N, i) = RTCHitN_primID(potentialHit, N, i);
|
|
||||||
|
|
||||||
RTCRayN_u(ray, N, i) = RTCHitN_u(potentialHit, N, i);
|
|
||||||
RTCRayN_v(ray, N, i) = RTCHitN_v(potentialHit, N, i);
|
|
||||||
RTCRayN_tfar(ray, N, i) = RTCHitN_t(potentialHit, N, i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -673,31 +687,33 @@ Embree_TraceInit(const mbsp_t *bsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
device = rtcNewDevice();
|
device = rtcNewDevice (NULL);
|
||||||
rtcDeviceSetErrorFunction2(device, ErrorCallback, nullptr); //mxd. Changed from rtcDeviceSetErrorFunction to silence compiler warning...
|
rtcSetDeviceErrorFunction(device,ErrorCallback,nullptr); //mxd. Changed from rtcDeviceSetErrorFunction to silence compiler warning...
|
||||||
|
|
||||||
// log version
|
// log version
|
||||||
const size_t ver_maj = rtcDeviceGetParameter1i(device, RTC_CONFIG_VERSION_MAJOR);
|
const size_t ver_maj = rtcGetDeviceProperty (device,RTC_DEVICE_PROPERTY_VERSION_MAJOR);
|
||||||
const size_t ver_min = rtcDeviceGetParameter1i(device, RTC_CONFIG_VERSION_MINOR);
|
const size_t ver_min = rtcGetDeviceProperty (device,RTC_DEVICE_PROPERTY_VERSION_MINOR);
|
||||||
const size_t ver_pat = rtcDeviceGetParameter1i(device, RTC_CONFIG_VERSION_PATCH);
|
const size_t ver_pat = rtcGetDeviceProperty (device,RTC_DEVICE_PROPERTY_VERSION_PATCH);
|
||||||
logprint("Embree_TraceInit: Embree version: %d.%d.%d\n",
|
logprint("Embree_TraceInit: Embree version: %d.%d.%d\n",
|
||||||
static_cast<int>(ver_maj), static_cast<int>(ver_min), static_cast<int>(ver_pat));
|
static_cast<int>(ver_maj), static_cast<int>(ver_min), static_cast<int>(ver_pat));
|
||||||
|
|
||||||
// we use the ray mask field to store the dmodel index of the self-shadow model
|
// we use the ray mask field to store the dmodel index of the self-shadow model
|
||||||
if (0 != rtcDeviceGetParameter1i(device, RTC_CONFIG_RAY_MASK)) {
|
if (0 != rtcGetDeviceProperty (device,RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED)) {
|
||||||
Error("embree must be built with ray masks disabled");
|
Error("embree must be built with ray masks disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
scene = rtcDeviceNewScene(device, RTC_SCENE_STATIC | RTC_SCENE_COHERENT, RTC_INTERSECT1 | RTC_INTERSECT_STREAM);
|
scene = rtcNewScene(device);
|
||||||
skygeom = CreateGeometry(bsp, scene, skyfaces);
|
rtcSetSceneFlags(scene, RTC_SCENE_FLAG_NONE);
|
||||||
solidgeom = CreateGeometry(bsp, scene, solidfaces);
|
rtcSetSceneBuildQuality(scene, RTC_BUILD_QUALITY_MEDIUM);
|
||||||
filtergeom = CreateGeometry(bsp, scene, filterfaces);
|
skygeom = CreateGeometry(bsp, device, scene, skyfaces);
|
||||||
CreateGeometryFromWindings(scene, skipwindings);
|
solidgeom = CreateGeometry(bsp, device, scene, solidfaces);
|
||||||
|
filtergeom = CreateGeometry(bsp, device, scene, filterfaces);
|
||||||
|
CreateGeometryFromWindings(device, scene, skipwindings);
|
||||||
|
|
||||||
rtcSetIntersectionFilterFunctionN(scene, filtergeom.geomID, Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
rtcSetGeometryIntersectFilterFunction(rtcGetGeometry(scene,filtergeom.geomID),Embree_FilterFuncN<filtertype_t::INTERSECTION>);
|
||||||
rtcSetOcclusionFilterFunctionN(scene, filtergeom.geomID, Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
rtcSetGeometryOccludedFilterFunction(rtcGetGeometry(scene,filtergeom.geomID),Embree_FilterFuncN<filtertype_t::OCCLUSION>);
|
||||||
|
|
||||||
rtcCommit (scene);
|
rtcCommitScene(scene);
|
||||||
|
|
||||||
logprint("Embree_TraceInit:\n");
|
logprint("Embree_TraceInit:\n");
|
||||||
logprint("\t%d sky faces\n", (int)skyfaces.size());
|
logprint("\t%d sky faces\n", (int)skyfaces.size());
|
||||||
|
|
@ -708,16 +724,20 @@ Embree_TraceInit(const mbsp_t *bsp)
|
||||||
FreeWindings(skipwindings);
|
FreeWindings(skipwindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RTCRay SetupRay(unsigned rayindex, const vec3_t start, const vec3_t dir, vec_t dist)
|
static RTCRay SetupOcclusionRay(unsigned rayindex, const vec3_t start, const vec3_t dir, vec_t dist)
|
||||||
{
|
{
|
||||||
RTCRay ray;
|
RTCRay ray;
|
||||||
VectorCopy(start, ray.org);
|
ray.flags = 0;
|
||||||
VectorCopy(dir, ray.dir); // can be un-normalized
|
ray.org_x = start[0];
|
||||||
|
ray.org_y = start[1];
|
||||||
|
ray.org_z = start[2];
|
||||||
|
ray.dir_x = dir[0]; // can be un-normalized
|
||||||
|
ray.dir_y = dir[1]; // can be un-normalized
|
||||||
|
ray.dir_z = dir[2]; // can be un-normalized
|
||||||
ray.tnear = 0.f;
|
ray.tnear = 0.f;
|
||||||
ray.tfar = dist;
|
ray.tfar = dist;
|
||||||
ray.geomID = RTC_INVALID_GEOMETRY_ID;
|
ray.id = 0;
|
||||||
ray.primID = RTC_INVALID_GEOMETRY_ID;
|
ray.flags = 0;
|
||||||
ray.instID = RTC_INVALID_GEOMETRY_ID;
|
|
||||||
|
|
||||||
// NOTE: we are not using the ray masking feature of embree, but just using
|
// NOTE: we are not using the ray masking feature of embree, but just using
|
||||||
// this field to store the ray index
|
// this field to store the ray index
|
||||||
|
|
@ -727,13 +747,21 @@ static RTCRay SetupRay(unsigned rayindex, const vec3_t start, const vec3_t dir,
|
||||||
return ray;
|
return ray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RTCRayHit SetupIntersectionRay(unsigned rayindex, const vec3_t start, const vec3_t dir, vec_t dist)
|
||||||
|
{
|
||||||
|
RTCRayHit rayhit;
|
||||||
|
rayhit.ray = SetupOcclusionRay(rayindex, start, dir, dist);
|
||||||
|
rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
|
||||||
|
return rayhit;
|
||||||
|
}
|
||||||
|
|
||||||
static RTCRay SetupRay_StartStop(const vec3_t start, const vec3_t stop)
|
static RTCRay SetupRay_StartStop(const vec3_t start, const vec3_t stop)
|
||||||
{
|
{
|
||||||
vec3_t dir;
|
vec3_t dir;
|
||||||
VectorSubtract(stop, start, dir);
|
VectorSubtract(stop, start, dir);
|
||||||
vec_t dist = VectorNormalize(dir);
|
vec_t dist = VectorNormalize(dir);
|
||||||
|
|
||||||
return SetupRay(0, start, dir, dist);
|
return SetupOcclusionRay(0, start, dir, dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
//public
|
//public
|
||||||
|
|
@ -741,15 +769,13 @@ qboolean Embree_TestLight(const vec3_t start, const vec3_t stop, const modelinfo
|
||||||
{
|
{
|
||||||
RTCRay ray = SetupRay_StartStop(start, stop);
|
RTCRay ray = SetupRay_StartStop(start, stop);
|
||||||
|
|
||||||
ray_source_info ctx2(nullptr, self);
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, nullptr, self);
|
||||||
const RTCIntersectContext ctx = {
|
rtcOccluded1(scene, ctx2.castToEmbreeContext(), &ray);
|
||||||
RTC_INTERSECT_COHERENT,
|
|
||||||
static_cast<void *>(&ctx2)
|
|
||||||
};
|
|
||||||
|
|
||||||
rtcOccluded1Ex(scene, &ctx, ray);
|
// from embree2 to 3 migration:
|
||||||
|
const bool occluded = ray.tfar < 0.0f;
|
||||||
|
|
||||||
if (ray.geomID != RTC_INVALID_GEOMETRY_ID)
|
if (occluded)
|
||||||
return false; //hit
|
return false; //hit
|
||||||
|
|
||||||
// no obstruction
|
// no obstruction
|
||||||
|
|
@ -766,21 +792,20 @@ qboolean Embree_TestSky(const vec3_t start, const vec3_t dirn, const modelinfo_t
|
||||||
VectorCopy(dirn, dir_normalized);
|
VectorCopy(dirn, dir_normalized);
|
||||||
VectorNormalize(dir_normalized);
|
VectorNormalize(dir_normalized);
|
||||||
|
|
||||||
RTCRay ray = SetupRay(0, start, dir_normalized, MAX_SKY_DIST);
|
RTCRayHit ray = SetupIntersectionRay(0, start, dir_normalized, MAX_SKY_DIST);
|
||||||
|
|
||||||
ray_source_info ctx2(nullptr, self);
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, nullptr, self);
|
||||||
const RTCIntersectContext ctx = {
|
rtcIntersect1(scene,ctx2.castToEmbreeContext(),&ray);
|
||||||
RTC_INTERSECT_COHERENT,
|
ray.hit.Ng_x = -ray.hit.Ng_x;
|
||||||
static_cast<void *>(&ctx2)
|
ray.hit.Ng_y = -ray.hit.Ng_y;
|
||||||
};
|
ray.hit.Ng_z = -ray.hit.Ng_z;
|
||||||
rtcIntersect1Ex(scene, &ctx, ray);
|
|
||||||
|
|
||||||
qboolean hit_sky = (ray.geomID == skygeom.geomID);
|
qboolean hit_sky = (ray.hit.geomID == skygeom.geomID);
|
||||||
|
|
||||||
if (face_out) {
|
if (face_out) {
|
||||||
if (hit_sky) {
|
if (hit_sky) {
|
||||||
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.geomID);
|
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.hit.geomID);
|
||||||
*face_out = si.triToFace.at(ray.primID);
|
*face_out = si.triToFace.at(ray.hit.primID);
|
||||||
} else {
|
} else {
|
||||||
*face_out = nullptr;
|
*face_out = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -792,34 +817,33 @@ qboolean Embree_TestSky(const vec3_t start, const vec3_t dirn, const modelinfo_t
|
||||||
//public
|
//public
|
||||||
hittype_t Embree_DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, const modelinfo_t *self, vec_t *hitdist_out, plane_t *hitplane_out, const bsp2_dface_t **face_out)
|
hittype_t Embree_DirtTrace(const vec3_t start, const vec3_t dirn, vec_t dist, const modelinfo_t *self, vec_t *hitdist_out, plane_t *hitplane_out, const bsp2_dface_t **face_out)
|
||||||
{
|
{
|
||||||
RTCRay ray = SetupRay(0, start, dirn, dist);
|
RTCRayHit ray = SetupIntersectionRay(0, start, dirn, dist);
|
||||||
ray_source_info ctx2(nullptr, self);
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, nullptr, self);
|
||||||
const RTCIntersectContext ctx = {
|
rtcIntersect1(scene,ctx2.castToEmbreeContext(),&ray);
|
||||||
RTC_INTERSECT_COHERENT,
|
ray.hit.Ng_x = -ray.hit.Ng_x;
|
||||||
static_cast<void *>(&ctx2)
|
ray.hit.Ng_y = -ray.hit.Ng_y;
|
||||||
};
|
ray.hit.Ng_z = -ray.hit.Ng_z;
|
||||||
rtcIntersect1Ex(scene, &ctx, ray);
|
|
||||||
|
|
||||||
if (ray.geomID == RTC_INVALID_GEOMETRY_ID)
|
if (ray.hit.geomID == RTC_INVALID_GEOMETRY_ID)
|
||||||
return hittype_t::NONE;
|
return hittype_t::NONE;
|
||||||
|
|
||||||
if (hitdist_out) {
|
if (hitdist_out) {
|
||||||
*hitdist_out = ray.tfar;
|
*hitdist_out = ray.ray.tfar;
|
||||||
}
|
}
|
||||||
if (hitplane_out) {
|
if (hitplane_out) {
|
||||||
for (int i=0; i<3; i++) {
|
hitplane_out->normal[0] = ray.hit.Ng_x;
|
||||||
hitplane_out->normal[i] = ray.Ng[i];
|
hitplane_out->normal[1] = ray.hit.Ng_y;
|
||||||
}
|
hitplane_out->normal[2] = ray.hit.Ng_z;
|
||||||
VectorNormalize(hitplane_out->normal);
|
VectorNormalize(hitplane_out->normal);
|
||||||
|
|
||||||
vec3_t hitpoint;
|
vec3_t hitpoint;
|
||||||
VectorMA(start, ray.tfar, dirn, hitpoint);
|
VectorMA(start, ray.ray.tfar, dirn, hitpoint);
|
||||||
|
|
||||||
hitplane_out->dist = DotProduct(hitplane_out->normal, hitpoint);
|
hitplane_out->dist = DotProduct(hitplane_out->normal, hitpoint);
|
||||||
}
|
}
|
||||||
if (face_out) {
|
if (face_out) {
|
||||||
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.geomID);
|
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.hit.geomID);
|
||||||
*face_out = si.triToFace.at(ray.primID);
|
*face_out = si.triToFace.at(ray.hit.primID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ray.geomID == skygeom.geomID) {
|
if (ray.geomID == skygeom.geomID) {
|
||||||
|
|
@ -855,9 +879,9 @@ static void q_aligned_free(void *ptr)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class raystream_embree_t : public raystream_t {
|
class occlusion_raystream_embree_t {
|
||||||
public:
|
public:
|
||||||
RTCRay *_rays;
|
RTCRay *_occlusion_rays;
|
||||||
float *_rays_maxdist;
|
float *_rays_maxdist;
|
||||||
int *_point_indices;
|
int *_point_indices;
|
||||||
vec3_t *_ray_colors;
|
vec3_t *_ray_colors;
|
||||||
|
|
@ -871,11 +895,10 @@ public:
|
||||||
|
|
||||||
int _numrays;
|
int _numrays;
|
||||||
int _maxrays;
|
int _maxrays;
|
||||||
// streamstate_t _state;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
raystream_embree_t(int maxRays) :
|
raystream_embree_t(int maxRays) :
|
||||||
_rays { static_cast<RTCRay *>(q_aligned_malloc(16, sizeof(RTCRay) * maxRays)) },
|
_occlusion_rays { static_cast<RTCRay *>(q_aligned_malloc(16, sizeof(RTCRay) * maxRays)) },
|
||||||
_rays_maxdist { new float[maxRays] },
|
_rays_maxdist { new float[maxRays] },
|
||||||
_point_indices { new int[maxRays] },
|
_point_indices { new int[maxRays] },
|
||||||
_ray_colors { static_cast<vec3_t *>(calloc(maxRays, sizeof(vec3_t))) },
|
_ray_colors { static_cast<vec3_t *>(calloc(maxRays, sizeof(vec3_t))) },
|
||||||
|
|
@ -883,11 +906,10 @@ public:
|
||||||
_ray_dynamic_styles { new int[maxRays] },
|
_ray_dynamic_styles { new int[maxRays] },
|
||||||
_numrays { 0 },
|
_numrays { 0 },
|
||||||
_maxrays { maxRays } {}
|
_maxrays { maxRays } {}
|
||||||
//,
|
|
||||||
//_state { streamstate_t::READY } {}
|
|
||||||
|
|
||||||
~raystream_embree_t() {
|
~raystream_embree_t() {
|
||||||
q_aligned_free(_rays);
|
q_aligned_free(_intersection_rays);
|
||||||
|
q_aligned_free(_occlusion_rays);
|
||||||
delete[] _rays_maxdist;
|
delete[] _rays_maxdist;
|
||||||
delete[] _point_indices;
|
delete[] _point_indices;
|
||||||
free(_ray_colors);
|
free(_ray_colors);
|
||||||
|
|
@ -895,7 +917,7 @@ public:
|
||||||
delete[] _ray_dynamic_styles;
|
delete[] _ray_dynamic_styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pushRay(int i, const vec_t *origin, const vec3_t dir, float dist, const vec_t *color = nullptr, const vec_t *normalcontrib = nullptr) {
|
virtual void pushRay(RayType type, int i, const vec_t *origin, const vec3_t dir, float dist, const vec_t *color = nullptr, const vec_t *normalcontrib = nullptr) {
|
||||||
Q_assert(_numrays<_maxrays);
|
Q_assert(_numrays<_maxrays);
|
||||||
_rays[_numrays] = SetupRay(_numrays, origin, dir, dist);
|
_rays[_numrays] = SetupRay(_numrays, origin, dir, dist);
|
||||||
_rays_maxdist[_numrays] = dist;
|
_rays_maxdist[_numrays] = dist;
|
||||||
|
|
@ -920,31 +942,173 @@ public:
|
||||||
if (!_numrays)
|
if (!_numrays)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ray_source_info ctx2(this, self);
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, this, self);
|
||||||
const RTCIntersectContext ctx = {
|
rtcOccluded1M(scene, ctx2.castToEmbreeContext(), _rays, _numrays, sizeof(RTCRay));
|
||||||
RTC_INTERSECT_COHERENT,
|
|
||||||
static_cast<void *>(&ctx2)
|
|
||||||
};
|
|
||||||
|
|
||||||
rtcOccluded1M(scene, &ctx, _rays, _numrays, sizeof(RTCRay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void tracePushedRaysIntersection(const modelinfo_t *self) {
|
virtual void tracePushedRaysIntersection(const modelinfo_t *self) {
|
||||||
if (!_numrays)
|
if (!_numrays)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ray_source_info ctx2(this, self);
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, this, self);
|
||||||
const RTCIntersectContext ctx = {
|
rtcIntersect1M(scene, ctx2.castToEmbreeContext(), _rays, _numrays, sizeof(RTCRay));
|
||||||
RTC_INTERSECT_COHERENT,
|
|
||||||
static_cast<void *>(&ctx2)
|
|
||||||
};
|
|
||||||
|
|
||||||
rtcIntersect1M(scene, &ctx, _rays, _numrays, sizeof(RTCRay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool getPushedRayOccluded(size_t j) {
|
virtual bool getPushedRayOccluded(size_t j) {
|
||||||
Q_assert(j < _maxrays);
|
Q_assert(j < _maxrays);
|
||||||
return (_rays[j].geomID != RTC_INVALID_GEOMETRY_ID);
|
return ray.tfar < 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float getPushedRayDist(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
return _rays_maxdist[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float getPushedRayHitDist(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
return _rays[j].tfar;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual hittype_t getPushedRayHitType(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
|
||||||
|
if (_rays[j].geomID == RTC_INVALID_GEOMETRY_ID) {
|
||||||
|
return hittype_t::NONE;
|
||||||
|
} else if (_rays[j].geomID == skygeom.geomID) {
|
||||||
|
return hittype_t::SKY;
|
||||||
|
} else {
|
||||||
|
return hittype_t::SOLID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const bsp2_dface_t *getPushedRayHitFace(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
|
||||||
|
const RTCRay &ray = _rays[j];
|
||||||
|
|
||||||
|
if (ray.geomID == RTC_INVALID_GEOMETRY_ID)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const sceneinfo &si = Embree_SceneinfoForGeomID(ray.geomID);
|
||||||
|
const bsp2_dface_t *face = si.triToFace.at(ray.primID);
|
||||||
|
Q_assert(face != nullptr);
|
||||||
|
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getPushedRayDir(size_t j, vec3_t out) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
out[i] = _rays[j].dir[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getPushedRayPointIndex(size_t j) {
|
||||||
|
// Q_assert(_state != streamstate_t::READY);
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
return _point_indices[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getPushedRayColor(size_t j, vec3_t out) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
VectorCopy(_ray_colors[j], out);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getPushedRayNormalContrib(size_t j, vec3_t out) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
VectorCopy(_ray_normalcontribs[j], out);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getPushedRayDynamicStyle(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
return _ray_dynamic_styles[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearPushedRays() {
|
||||||
|
_numrays = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class raystream_embree_t : public raystream_t {
|
||||||
|
public:
|
||||||
|
RTCRayHit *_intersection_rays;
|
||||||
|
RTCRay *_occlusion_rays;
|
||||||
|
float *_rays_maxdist;
|
||||||
|
int *_point_indices;
|
||||||
|
vec3_t *_ray_colors;
|
||||||
|
vec3_t *_ray_normalcontribs;
|
||||||
|
|
||||||
|
// This is set to the modelinfo's switchshadstyle if the ray hit
|
||||||
|
// a dynamic shadow caster. (note that for rays that hit dynamic
|
||||||
|
// shadow casters, all of the other hit data is assuming the ray went
|
||||||
|
// straight through).
|
||||||
|
int *_ray_dynamic_styles;
|
||||||
|
|
||||||
|
int _numrays;
|
||||||
|
int _maxrays;
|
||||||
|
|
||||||
|
public:
|
||||||
|
raystream_embree_t(int maxRays) :
|
||||||
|
_intersection_rays { static_cast<RTCRayHit *>(q_aligned_malloc(16, sizeof(RTCRayHit) * maxRays)) },
|
||||||
|
_occlusion_rays { static_cast<RTCRay *>(q_aligned_malloc(16, sizeof(RTCRay) * maxRays)) },
|
||||||
|
_rays_maxdist { new float[maxRays] },
|
||||||
|
_point_indices { new int[maxRays] },
|
||||||
|
_ray_colors { static_cast<vec3_t *>(calloc(maxRays, sizeof(vec3_t))) },
|
||||||
|
_ray_normalcontribs { static_cast<vec3_t *>(calloc(maxRays, sizeof(vec3_t))) },
|
||||||
|
_ray_dynamic_styles { new int[maxRays] },
|
||||||
|
_numrays { 0 },
|
||||||
|
_maxrays { maxRays } {}
|
||||||
|
|
||||||
|
~raystream_embree_t() {
|
||||||
|
q_aligned_free(_intersection_rays);
|
||||||
|
q_aligned_free(_occlusion_rays);
|
||||||
|
delete[] _rays_maxdist;
|
||||||
|
delete[] _point_indices;
|
||||||
|
free(_ray_colors);
|
||||||
|
free(_ray_normalcontribs);
|
||||||
|
delete[] _ray_dynamic_styles;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void pushRay(RayType type, int i, const vec_t *origin, const vec3_t dir, float dist, const vec_t *color = nullptr, const vec_t *normalcontrib = nullptr) {
|
||||||
|
Q_assert(_numrays<_maxrays);
|
||||||
|
_rays[_numrays] = SetupRay(_numrays, origin, dir, dist);
|
||||||
|
_rays_maxdist[_numrays] = dist;
|
||||||
|
_point_indices[_numrays] = i;
|
||||||
|
if (color) {
|
||||||
|
VectorCopy(color, _ray_colors[_numrays]);
|
||||||
|
}
|
||||||
|
if (normalcontrib) {
|
||||||
|
VectorCopy(normalcontrib, _ray_normalcontribs[_numrays]);
|
||||||
|
}
|
||||||
|
_ray_dynamic_styles[_numrays] = 0;
|
||||||
|
_numrays++;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t numPushedRays() {
|
||||||
|
return _numrays;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void tracePushedRaysOcclusion(const modelinfo_t *self) {
|
||||||
|
//Q_assert(_state == streamstate_t::READY);
|
||||||
|
|
||||||
|
if (!_numrays)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, this, self);
|
||||||
|
rtcOccluded1M(scene, ctx2.castToEmbreeContext(), _rays, _numrays, sizeof(RTCRay));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void tracePushedRaysIntersection(const modelinfo_t *self) {
|
||||||
|
if (!_numrays)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ray_source_info ctx2(RTC_INTERSECT_CONTEXT_FLAG_COHERENT, this, self);
|
||||||
|
rtcIntersect1M(scene, ctx2.castToEmbreeContext(), _rays, _numrays, sizeof(RTCRay));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool getPushedRayOccluded(size_t j) {
|
||||||
|
Q_assert(j < _maxrays);
|
||||||
|
return ray.tfar < 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual float getPushedRayDist(size_t j) {
|
virtual float getPushedRayDist(size_t j) {
|
||||||
|
|
@ -1018,13 +1182,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
raystream_t *Embree_MakeRayStream(int maxrays)
|
|
||||||
{
|
|
||||||
return new raystream_embree_t{maxrays};
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddGlassToRay(const RTCIntersectContext* context, unsigned rayIndex, float opacity, const vec3_t glasscolor) {
|
void AddGlassToRay(const RTCIntersectContext* context, unsigned rayIndex, float opacity, const vec3_t glasscolor) {
|
||||||
ray_source_info *ctx = static_cast<ray_source_info *>(context->userRayExt);
|
ray_source_info *ctx = ray_source_info::getRaySourceInfoFromEmbreeCtx(context);
|
||||||
raystream_embree_t *rs = ctx->raystream;
|
raystream_embree_t *rs = ctx->raystream;
|
||||||
|
|
||||||
if (rs == nullptr) {
|
if (rs == nullptr) {
|
||||||
|
|
@ -1062,7 +1222,7 @@ void AddGlassToRay(const RTCIntersectContext* context, unsigned rayIndex, float
|
||||||
|
|
||||||
void AddDynamicOccluderToRay(const RTCIntersectContext* context, unsigned rayIndex, int style)
|
void AddDynamicOccluderToRay(const RTCIntersectContext* context, unsigned rayIndex, int style)
|
||||||
{
|
{
|
||||||
ray_source_info *ctx = static_cast<ray_source_info *>(context->userRayExt);
|
ray_source_info *ctx = ray_source_info::getRaySourceInfoFromEmbreeCtx(context);
|
||||||
raystream_embree_t *rs = ctx->raystream;
|
raystream_embree_t *rs = ctx->raystream;
|
||||||
|
|
||||||
rs->_ray_dynamic_styles[rayIndex] = style;
|
rs->_ray_dynamic_styles[rayIndex] = style;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue