Path: blob/master/thirdparty/embree/kernels/common/accelset.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "default.h"6#include "builder.h"7#include "geometry.h"8#include "ray.h"9#include "hit.h"1011namespace embree12{13struct IntersectFunctionNArguments;14struct OccludedFunctionNArguments;1516struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments17{18Geometry* geometry;19RTCScene forward_scene;20RTCIntersectArguments* args;21};2223struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments24{25Geometry* geometry;26RTCScene forward_scene;27RTCIntersectArguments* args;28};2930/*! Base class for set of acceleration structures. */31class AccelSet : public Geometry32{33public:34typedef RTCIntersectFunctionN IntersectFuncN;35typedef RTCOccludedFunctionN OccludedFuncN;36typedef void (*ErrorFunc) ();3738struct IntersectorN39{40IntersectorN (ErrorFunc error = nullptr) ;41IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);4243operator bool() const { return name; }4445public:46static const char* type;47IntersectFuncN intersect;48OccludedFuncN occluded;49const char* name;50};5152public:5354/*! construction */55AccelSet (Device* device, Geometry::GType gtype, size_t items, size_t numTimeSteps);5657/*! makes the acceleration structure immutable */58virtual void immutable () {}5960/*! build accel */61virtual void build () = 0;6263/*! check if the i'th primitive is valid between the specified time range */64__forceinline bool valid(size_t i, const range<size_t>& itime_range) const65{66for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)67if (!isvalid_non_empty(bounds(i,itime))) return false;6869return true;70}7172/*! Calculates the bounds of an item */73__forceinline BBox3fa bounds(size_t i, size_t itime = 0) const74{75BBox3fa box;76assert(i < size());77RTCBoundsFunctionArguments args;78args.geometryUserPtr = userPtr;79args.primID = (unsigned int)i;80args.timeStep = (unsigned int)itime;81args.bounds_o = (RTCBounds*)&box;82boundsFunc(&args);83return box;84}8586/*! calculates the linear bounds of the i'th item at the itime'th time segment */87__forceinline LBBox3fa linearBounds(size_t i, size_t itime) const88{89BBox3fa box[2];90assert(i < size());91RTCBoundsFunctionArguments args;92args.geometryUserPtr = userPtr;93args.primID = (unsigned int)i;94args.timeStep = (unsigned int)(itime+0);95args.bounds_o = (RTCBounds*)&box[0];96boundsFunc(&args);97args.timeStep = (unsigned int)(itime+1);98args.bounds_o = (RTCBounds*)&box[1];99boundsFunc(&args);100return LBBox3fa(box[0],box[1]);101}102103/*! calculates the build bounds of the i'th item, if it's valid */104__forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const105{106const BBox3fa b = bounds(i);107if (bbox) *bbox = b;108return isvalid_non_empty(b);109}110111/*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */112__forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const113{114const LBBox3fa bounds = linearBounds(i,itime);115bbox = bounds.bounds0; // use bounding box of first timestep to build BVH116return isvalid_non_empty(bounds);117}118119/*! calculates the linear bounds of the i'th primitive for the specified time range */120__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {121return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);122}123124/*! calculates the linear bounds of the i'th primitive for the specified time range */125__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {126if (!valid(i, timeSegmentRange(time_range))) return false;127bbox = linearBounds(i, time_range);128return true;129}130131/* gets version info of topology */132unsigned int getTopologyVersion() const {133return numPrimitives;134}135136/* returns true if topology changed */137bool topologyChanged(unsigned int otherVersion) const {138return numPrimitives != otherVersion;139}140141public:142143/*! Intersects a single ray with the scene. */144__forceinline bool intersect (RayHit& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context)145{146assert(primID < size());147148int mask = -1;149IntersectFunctionNArguments args;150args.valid = &mask;151args.geometryUserPtr = userPtr;152args.context = context->user;153args.rayhit = (RTCRayHitN*)&ray;154args.N = 1;155args.geomID = geomID;156args.primID = primID;157args.geometry = this;158args.forward_scene = nullptr;159args.args = context->args;160161IntersectFuncN intersectFunc = nullptr;162intersectFunc = intersectorN.intersect;163164if (context->getIntersectFunction())165intersectFunc = context->getIntersectFunction();166167assert(intersectFunc);168intersectFunc(&args);169170return mask != 0;171}172173/*! Tests if single ray is occluded by the scene. */174__forceinline bool occluded (Ray& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context)175{176assert(primID < size());177178int mask = -1;179OccludedFunctionNArguments args;180args.valid = &mask;181args.geometryUserPtr = userPtr;182args.context = context->user;183args.ray = (RTCRayN*)&ray;184args.N = 1;185args.geomID = geomID;186args.primID = primID;187args.geometry = this;188args.forward_scene = nullptr;189args.args = context->args;190191OccludedFuncN occludedFunc = nullptr;192occludedFunc = intersectorN.occluded;193194if (context->getOccludedFunction())195occludedFunc = context->getOccludedFunction();196197assert(occludedFunc);198occludedFunc(&args);199200return mask != 0;201}202203/*! Intersects a single ray with the scene. */204__forceinline bool intersect (RayHit& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context, RTCScene& forward_scene)205{206assert(primID < size());207208int mask = -1;209IntersectFunctionNArguments args;210args.valid = &mask;211args.geometryUserPtr = userPtr;212args.context = context->user;213args.rayhit = (RTCRayHitN*)&ray;214args.N = 1;215args.geomID = geomID;216args.primID = primID;217args.geometry = this;218args.forward_scene = nullptr;219args.args = nullptr;220221typedef void (*RTCIntersectFunctionSYCL)(const void* args);222RTCIntersectFunctionSYCL intersectFunc = nullptr;223224#if EMBREE_SYCL_GEOMETRY_CALLBACK225if (context->args->feature_mask & RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY)226intersectFunc = (RTCIntersectFunctionSYCL) intersectorN.intersect;227#endif228229if (context->args->feature_mask & RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS)230if (context->getIntersectFunction())231intersectFunc = (RTCIntersectFunctionSYCL) context->getIntersectFunction();232233if (intersectFunc)234intersectFunc(&args);235236forward_scene = args.forward_scene;237return mask != 0;238}239240/*! Tests if single ray is occluded by the scene. */241__forceinline bool occluded (Ray& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context, RTCScene& forward_scene)242{243assert(primID < size());244245int mask = -1;246OccludedFunctionNArguments args;247args.valid = &mask;248args.geometryUserPtr = userPtr;249args.context = context->user;250args.ray = (RTCRayN*)&ray;251args.N = 1;252args.geomID = geomID;253args.primID = primID;254args.geometry = this;255args.forward_scene = nullptr;256args.args = nullptr;257258typedef void (*RTCOccludedFunctionSYCL)(const void* args);259RTCOccludedFunctionSYCL occludedFunc = nullptr;260261#if EMBREE_SYCL_GEOMETRY_CALLBACK262if (context->args->feature_mask & RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY)263occludedFunc = (RTCOccludedFunctionSYCL) intersectorN.occluded;264#endif265266if (context->args->feature_mask & RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS)267if (context->getOccludedFunction())268occludedFunc = (RTCOccludedFunctionSYCL) context->getOccludedFunction();269270if (occludedFunc)271occludedFunc(&args);272273forward_scene = args.forward_scene;274return mask != 0;275}276277/*! Intersects a packet of K rays with the scene. */278template<int K>279__forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context)280{281assert(primID < size());282283vint<K> mask = valid.mask32();284IntersectFunctionNArguments args;285args.valid = (int*)&mask;286args.geometryUserPtr = userPtr;287args.context = context->user;288args.rayhit = (RTCRayHitN*)&ray;289args.N = K;290args.geomID = geomID;291args.primID = primID;292args.geometry = this;293args.forward_scene = nullptr;294args.args = context->args;295296IntersectFuncN intersectFunc = nullptr;297intersectFunc = intersectorN.intersect;298299if (context->getIntersectFunction())300intersectFunc = context->getIntersectFunction();301302assert(intersectFunc);303intersectFunc(&args);304}305306/*! Tests if a packet of K rays is occluded by the scene. */307template<int K>308__forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, RayQueryContext* context)309{310assert(primID < size());311312vint<K> mask = valid.mask32();313OccludedFunctionNArguments args;314args.valid = (int*)&mask;315args.geometryUserPtr = userPtr;316args.context = context->user;317args.ray = (RTCRayN*)&ray;318args.N = K;319args.geomID = geomID;320args.primID = primID;321args.geometry = this;322args.forward_scene = nullptr;323args.args = context->args;324325OccludedFuncN occludedFunc = nullptr;326occludedFunc = intersectorN.occluded;327328if (context->getOccludedFunction())329occludedFunc = context->getOccludedFunction();330331assert(occludedFunc);332occludedFunc(&args);333}334335public:336RTCBoundsFunction boundsFunc;337IntersectorN intersectorN;338};339340#define DEFINE_SET_INTERSECTORN(symbol,intersector) \341AccelSet::IntersectorN symbol() { \342return AccelSet::IntersectorN(intersector::intersect, \343intersector::occluded, \344TOSTRING(isa) "::" TOSTRING(symbol)); \345}346}347348349