godot/thirdparty/embree/kernels/common/accelset.h
jfons a69cc9f13d
Upgrade Embree to the latest official release.
Since Embree v3.13.0 supports AARCH64, switch back to the
official repo instead of using Embree-aarch64.

`thirdparty/embree/patches/godot-changes.patch` should now contain
an accurate diff of the changes done to the library.

(cherry picked from commit 767e374dce)
2021-05-22 15:14:07 +02:00

249 lines
8.2 KiB
C++

// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "default.h"
#include "builder.h"
#include "geometry.h"
#include "ray.h"
#include "hit.h"
namespace embree
{
struct IntersectFunctionNArguments;
struct OccludedFunctionNArguments;
typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments
{
IntersectContext* internal_context;
Geometry* geometry;
ReportIntersectionFunc report;
};
struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments
{
IntersectContext* internal_context;
Geometry* geometry;
ReportOcclusionFunc report;
};
/*! Base class for set of acceleration structures. */
class AccelSet : public Geometry
{
public:
typedef RTCIntersectFunctionN IntersectFuncN;
typedef RTCOccludedFunctionN OccludedFuncN;
typedef void (*ErrorFunc) ();
struct IntersectorN
{
IntersectorN (ErrorFunc error = nullptr) ;
IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);
operator bool() const { return name; }
public:
static const char* type;
IntersectFuncN intersect;
OccludedFuncN occluded;
const char* name;
};
public:
/*! construction */
AccelSet (Device* device, Geometry::GType gtype, size_t items, size_t numTimeSteps);
/*! makes the acceleration structure immutable */
virtual void immutable () {}
/*! build accel */
virtual void build () = 0;
/*! check if the i'th primitive is valid between the specified time range */
__forceinline bool valid(size_t i, const range<size_t>& itime_range) const
{
for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
if (!isvalid_non_empty(bounds(i,itime))) return false;
return true;
}
/*! Calculates the bounds of an item */
__forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
{
BBox3fa box;
assert(i < size());
RTCBoundsFunctionArguments args;
args.geometryUserPtr = userPtr;
args.primID = (unsigned int)i;
args.timeStep = (unsigned int)itime;
args.bounds_o = (RTCBounds*)&box;
boundsFunc(&args);
return box;
}
/*! calculates the linear bounds of the i'th item at the itime'th time segment */
__forceinline LBBox3fa linearBounds(size_t i, size_t itime) const
{
BBox3fa box[2];
assert(i < size());
RTCBoundsFunctionArguments args;
args.geometryUserPtr = userPtr;
args.primID = (unsigned int)i;
args.timeStep = (unsigned int)(itime+0);
args.bounds_o = (RTCBounds*)&box[0];
boundsFunc(&args);
args.timeStep = (unsigned int)(itime+1);
args.bounds_o = (RTCBounds*)&box[1];
boundsFunc(&args);
return LBBox3fa(box[0],box[1]);
}
/*! calculates the build bounds of the i'th item, if it's valid */
__forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
{
const BBox3fa b = bounds(i);
if (bbox) *bbox = b;
return isvalid_non_empty(b);
}
/*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
__forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
{
const LBBox3fa bounds = linearBounds(i,itime);
bbox = bounds.bounds0; // use bounding box of first timestep to build BVH
return isvalid_non_empty(bounds);
}
/*! calculates the linear bounds of the i'th primitive for the specified time range */
__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);
}
/*! calculates the linear bounds of the i'th primitive for the specified time range */
__forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
if (!valid(i, timeSegmentRange(time_range))) return false;
bbox = linearBounds(i, time_range);
return true;
}
/* gets version info of topology */
unsigned int getTopologyVersion() const {
return numPrimitives;
}
/* returns true if topology changed */
bool topologyChanged(unsigned int otherVersion) const {
return numPrimitives != otherVersion;
}
public:
/*! Intersects a single ray with the scene. */
__forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
{
assert(primID < size());
assert(intersectorN.intersect);
int mask = -1;
IntersectFunctionNArguments args;
args.valid = &mask;
args.geometryUserPtr = userPtr;
args.context = context->user;
args.rayhit = (RTCRayHitN*)&ray;
args.N = 1;
args.geomID = geomID;
args.primID = primID;
args.internal_context = context;
args.geometry = this;
args.report = report;
intersectorN.intersect(&args);
}
/*! Tests if single ray is occluded by the scene. */
__forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
{
assert(primID < size());
assert(intersectorN.occluded);
int mask = -1;
OccludedFunctionNArguments args;
args.valid = &mask;
args.geometryUserPtr = userPtr;
args.context = context->user;
args.ray = (RTCRayN*)&ray;
args.N = 1;
args.geomID = geomID;
args.primID = primID;
args.internal_context = context;
args.geometry = this;
args.report = report;
intersectorN.occluded(&args);
}
/*! Intersects a packet of K rays with the scene. */
template<int K>
__forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
{
assert(primID < size());
assert(intersectorN.intersect);
vint<K> mask = valid.mask32();
IntersectFunctionNArguments args;
args.valid = (int*)&mask;
args.geometryUserPtr = userPtr;
args.context = context->user;
args.rayhit = (RTCRayHitN*)&ray;
args.N = K;
args.geomID = geomID;
args.primID = primID;
args.internal_context = context;
args.geometry = this;
args.report = report;
intersectorN.intersect(&args);
}
/*! Tests if a packet of K rays is occluded by the scene. */
template<int K>
__forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
{
assert(primID < size());
assert(intersectorN.occluded);
vint<K> mask = valid.mask32();
OccludedFunctionNArguments args;
args.valid = (int*)&mask;
args.geometryUserPtr = userPtr;
args.context = context->user;
args.ray = (RTCRayN*)&ray;
args.N = K;
args.geomID = geomID;
args.primID = primID;
args.internal_context = context;
args.geometry = this;
args.report = report;
intersectorN.occluded(&args);
}
public:
RTCBoundsFunction boundsFunc;
IntersectorN intersectorN;
};
#define DEFINE_SET_INTERSECTORN(symbol,intersector) \
AccelSet::IntersectorN symbol() { \
return AccelSet::IntersectorN(intersector::intersect, \
intersector::occluded, \
TOSTRING(isa) "::" TOSTRING(symbol)); \
}
}