1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "default.h"
7#include "builder.h"
8#include "geometry.h"
9#include "ray.h"
10#include "hit.h"
11
12namespace embree
13{
14 struct IntersectFunctionNArguments;
15 struct OccludedFunctionNArguments;
16
17 typedef void (*ReportIntersectionFunc) (IntersectFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
18 typedef void (*ReportOcclusionFunc) (OccludedFunctionNArguments* args, const RTCFilterFunctionNArguments* filter_args);
19
20 struct IntersectFunctionNArguments : public RTCIntersectFunctionNArguments
21 {
22 IntersectContext* internal_context;
23 Geometry* geometry;
24 ReportIntersectionFunc report;
25 };
26
27 struct OccludedFunctionNArguments : public RTCOccludedFunctionNArguments
28 {
29 IntersectContext* internal_context;
30 Geometry* geometry;
31 ReportOcclusionFunc report;
32 };
33
34 /*! Base class for set of acceleration structures. */
35 class AccelSet : public Geometry
36 {
37 public:
38 typedef RTCIntersectFunctionN IntersectFuncN;
39 typedef RTCOccludedFunctionN OccludedFuncN;
40 typedef void (*ErrorFunc) ();
41
42 struct IntersectorN
43 {
44 IntersectorN (ErrorFunc error = nullptr) ;
45 IntersectorN (IntersectFuncN intersect, OccludedFuncN occluded, const char* name);
46
47 operator bool() const { return name; }
48
49 public:
50 static const char* type;
51 IntersectFuncN intersect;
52 OccludedFuncN occluded;
53 const char* name;
54 };
55
56 public:
57
58 /*! construction */
59 AccelSet (Device* device, Geometry::GType gtype, size_t items, size_t numTimeSteps);
60
61 /*! makes the acceleration structure immutable */
62 virtual void immutable () {}
63
64 /*! build accel */
65 virtual void build () = 0;
66
67 /*! check if the i'th primitive is valid between the specified time range */
68 __forceinline bool valid(size_t i, const range<size_t>& itime_range) const
69 {
70 for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)
71 if (!isvalid_non_empty(v: bounds(i,itime))) return false;
72
73 return true;
74 }
75
76 /*! Calculates the bounds of an item */
77 __forceinline BBox3fa bounds(size_t i, size_t itime = 0) const
78 {
79 BBox3fa box;
80 assert(i < size());
81 RTCBoundsFunctionArguments args;
82 args.geometryUserPtr = userPtr;
83 args.primID = (unsigned int)i;
84 args.timeStep = (unsigned int)itime;
85 args.bounds_o = (RTCBounds*)&box;
86 boundsFunc(&args);
87 return box;
88 }
89
90 /*! calculates the linear bounds of the i'th item at the itime'th time segment */
91 __forceinline LBBox3fa linearBounds(size_t i, size_t itime) const
92 {
93 BBox3fa box[2];
94 assert(i < size());
95 RTCBoundsFunctionArguments args;
96 args.geometryUserPtr = userPtr;
97 args.primID = (unsigned int)i;
98 args.timeStep = (unsigned int)(itime+0);
99 args.bounds_o = (RTCBounds*)&box[0];
100 boundsFunc(&args);
101 args.timeStep = (unsigned int)(itime+1);
102 args.bounds_o = (RTCBounds*)&box[1];
103 boundsFunc(&args);
104 return LBBox3fa(box[0],box[1]);
105 }
106
107 /*! calculates the build bounds of the i'th item, if it's valid */
108 __forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const
109 {
110 const BBox3fa b = bounds(i);
111 if (bbox) *bbox = b;
112 return isvalid_non_empty(v: b);
113 }
114
115 /*! calculates the build bounds of the i'th item at the itime'th time segment, if it's valid */
116 __forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const
117 {
118 const LBBox3fa bounds = linearBounds(i,itime);
119 bbox = bounds.bounds0; // use bounding box of first timestep to build BVH
120 return isvalid_non_empty(v: bounds);
121 }
122
123 /*! calculates the linear bounds of the i'th primitive for the specified time range */
124 __forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {
125 return LBBox3fa([&] (size_t itime) { return bounds(i: primID, itime); }, dt, time_range, fnumTimeSegments);
126 }
127
128 /*! calculates the linear bounds of the i'th primitive for the specified time range */
129 __forceinline bool linearBounds(size_t i, const BBox1f& time_range, LBBox3fa& bbox) const {
130 if (!valid(i, itime_range: timeSegmentRange(range: time_range))) return false;
131 bbox = linearBounds(primID: i, dt: time_range);
132 return true;
133 }
134
135 /* gets version info of topology */
136 unsigned int getTopologyVersion() const {
137 return numPrimitives;
138 }
139
140 /* returns true if topology changed */
141 bool topologyChanged(unsigned int otherVersion) const {
142 return numPrimitives != otherVersion;
143 }
144
145 public:
146
147 /*! Intersects a single ray with the scene. */
148 __forceinline void intersect (RayHit& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
149 {
150 assert(primID < size());
151 assert(intersectorN.intersect);
152
153 int mask = -1;
154 IntersectFunctionNArguments args;
155 args.valid = &mask;
156 args.geometryUserPtr = userPtr;
157 args.context = context->user;
158 args.rayhit = (RTCRayHitN*)&ray;
159 args.N = 1;
160 args.geomID = geomID;
161 args.primID = primID;
162 args.internal_context = context;
163 args.geometry = this;
164 args.report = report;
165
166 intersectorN.intersect(&args);
167 }
168
169 /*! Tests if single ray is occluded by the scene. */
170 __forceinline void occluded (Ray& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
171 {
172 assert(primID < size());
173 assert(intersectorN.occluded);
174
175 int mask = -1;
176 OccludedFunctionNArguments args;
177 args.valid = &mask;
178 args.geometryUserPtr = userPtr;
179 args.context = context->user;
180 args.ray = (RTCRayN*)&ray;
181 args.N = 1;
182 args.geomID = geomID;
183 args.primID = primID;
184 args.internal_context = context;
185 args.geometry = this;
186 args.report = report;
187
188 intersectorN.occluded(&args);
189 }
190
191 /*! Intersects a packet of K rays with the scene. */
192 template<int K>
193 __forceinline void intersect (const vbool<K>& valid, RayHitK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportIntersectionFunc report)
194 {
195 assert(primID < size());
196 assert(intersectorN.intersect);
197
198 vint<K> mask = valid.mask32();
199 IntersectFunctionNArguments args;
200 args.valid = (int*)&mask;
201 args.geometryUserPtr = userPtr;
202 args.context = context->user;
203 args.rayhit = (RTCRayHitN*)&ray;
204 args.N = K;
205 args.geomID = geomID;
206 args.primID = primID;
207 args.internal_context = context;
208 args.geometry = this;
209 args.report = report;
210
211 intersectorN.intersect(&args);
212 }
213
214 /*! Tests if a packet of K rays is occluded by the scene. */
215 template<int K>
216 __forceinline void occluded (const vbool<K>& valid, RayK<K>& ray, unsigned int geomID, unsigned int primID, IntersectContext* context, ReportOcclusionFunc report)
217 {
218 assert(primID < size());
219 assert(intersectorN.occluded);
220
221 vint<K> mask = valid.mask32();
222 OccludedFunctionNArguments args;
223 args.valid = (int*)&mask;
224 args.geometryUserPtr = userPtr;
225 args.context = context->user;
226 args.ray = (RTCRayN*)&ray;
227 args.N = K;
228 args.geomID = geomID;
229 args.primID = primID;
230 args.internal_context = context;
231 args.geometry = this;
232 args.report = report;
233
234 intersectorN.occluded(&args);
235 }
236
237 public:
238 RTCBoundsFunction boundsFunc;
239 IntersectorN intersectorN;
240 };
241
242#define DEFINE_SET_INTERSECTORN(symbol,intersector) \
243 AccelSet::IntersectorN symbol() { \
244 return AccelSet::IntersectorN(intersector::intersect, \
245 intersector::occluded, \
246 TOSTRING(isa) "::" TOSTRING(symbol)); \
247 }
248}
249

source code of qtquick3d/src/3rdparty/embree/kernels/common/accelset.h