1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "default.h"
7#include "device.h"
8#include "builder.h"
9#include "../../common/algorithms/parallel_any_of.h"
10#include "scene_triangle_mesh.h"
11#include "scene_quad_mesh.h"
12#include "scene_user_geometry.h"
13#include "scene_instance.h"
14#include "scene_curves.h"
15#include "scene_line_segments.h"
16#include "scene_subdiv_mesh.h"
17#include "scene_grid_mesh.h"
18#include "scene_points.h"
19#include "../subdiv/tessellation_cache.h"
20
21#include "acceln.h"
22#include "geometry.h"
23
24namespace embree
25{
26 /*! Base class all scenes are derived from */
27 class Scene : public AccelN
28 {
29 ALIGNED_CLASS_(std::alignment_of<Scene>::value);
30
31 public:
32 template<typename Ty, bool mblur = false>
33 class Iterator
34 {
35 public:
36 Iterator () {}
37
38 Iterator (Scene* scene, bool all = false)
39 : scene(scene), all(all) {}
40
41 __forceinline Ty* at(const size_t i)
42 {
43 Geometry* geom = scene->geometries[i].ptr;
44 if (geom == nullptr) return nullptr;
45 if (!all && !geom->isEnabled()) return nullptr;
46 const size_t mask = geom->getTypeMask() & Ty::geom_type;
47 if (!(mask)) return nullptr;
48 if ((geom->numTimeSteps != 1) != mblur) return nullptr;
49 return (Ty*) geom;
50 }
51
52 __forceinline Ty* operator[] (const size_t i) {
53 return at(i);
54 }
55
56 __forceinline size_t size() const {
57 return scene->size();
58 }
59
60 __forceinline size_t numPrimitives() const {
61 return scene->getNumPrimitives(Ty::geom_type,mblur);
62 }
63
64 __forceinline size_t maxPrimitivesPerGeometry()
65 {
66 size_t ret = 0;
67 for (size_t i=0; i<scene->size(); i++) {
68 Ty* mesh = at(i);
69 if (mesh == nullptr) continue;
70 ret = max(ret,mesh->size());
71 }
72 return ret;
73 }
74
75 __forceinline unsigned int maxGeomID()
76 {
77 unsigned int ret = 0;
78 for (size_t i=0; i<scene->size(); i++) {
79 Ty* mesh = at(i);
80 if (mesh == nullptr) continue;
81 ret = max(ret,(unsigned int)i);
82 }
83 return ret;
84 }
85
86 __forceinline unsigned maxTimeStepsPerGeometry()
87 {
88 unsigned ret = 0;
89 for (size_t i=0; i<scene->size(); i++) {
90 Ty* mesh = at(i);
91 if (mesh == nullptr) continue;
92 ret = max(ret,mesh->numTimeSteps);
93 }
94 return ret;
95 }
96
97 private:
98 Scene* scene;
99 bool all;
100 };
101
102 class Iterator2
103 {
104 public:
105 Iterator2 () {}
106
107 Iterator2 (Scene* scene, Geometry::GTypeMask typemask, bool mblur)
108 : scene(scene), typemask(typemask), mblur(mblur) {}
109
110 __forceinline Geometry* at(const size_t i)
111 {
112 Geometry* geom = scene->geometries[i].ptr;
113 if (geom == nullptr) return nullptr;
114 if (!geom->isEnabled()) return nullptr;
115 if (!(geom->getTypeMask() & typemask)) return nullptr;
116 if ((geom->numTimeSteps != 1) != mblur) return nullptr;
117 return geom;
118 }
119
120 __forceinline Geometry* operator[] (const size_t i) {
121 return at(i);
122 }
123
124 __forceinline size_t size() const {
125 return scene->size();
126 }
127
128 private:
129 Scene* scene;
130 Geometry::GTypeMask typemask;
131 bool mblur;
132 };
133
134 public:
135
136 /*! Scene construction */
137 Scene (Device* device);
138
139 /*! Scene destruction */
140 ~Scene () noexcept;
141
142 private:
143 /*! class is non-copyable */
144 Scene (const Scene& other) DELETED; // do not implement
145 Scene& operator= (const Scene& other) DELETED; // do not implement
146
147 public:
148 void createTriangleAccel();
149 void createTriangleMBAccel();
150 void createQuadAccel();
151 void createQuadMBAccel();
152 void createHairAccel();
153 void createHairMBAccel();
154 void createSubdivAccel();
155 void createSubdivMBAccel();
156 void createUserGeometryAccel();
157 void createUserGeometryMBAccel();
158 void createInstanceAccel();
159 void createInstanceMBAccel();
160 void createInstanceExpensiveAccel();
161 void createInstanceExpensiveMBAccel();
162 void createGridAccel();
163 void createGridMBAccel();
164
165 /*! prints statistics about the scene */
166 void printStatistics();
167
168 /*! clears the scene */
169 void clear();
170
171 /*! detaches some geometry */
172 void detachGeometry(size_t geomID);
173
174 void setBuildQuality(RTCBuildQuality quality_flags);
175 RTCBuildQuality getBuildQuality() const;
176
177 void setSceneFlags(RTCSceneFlags scene_flags);
178 RTCSceneFlags getSceneFlags() const;
179
180 void commit (bool join);
181 void commit_task ();
182 void build () {}
183
184 void updateInterface();
185
186 /* return number of geometries */
187 __forceinline size_t size() const { return geometries.size(); }
188
189 /* bind geometry to the scene */
190 unsigned int bind (unsigned geomID, Ref<Geometry> geometry);
191
192 /* determines if scene is modified */
193 __forceinline bool isModified() const { return modified; }
194
195 /* sets modified flag */
196 __forceinline void setModified(bool f = true) {
197 modified = f;
198 }
199
200 __forceinline bool isGeometryModified(size_t geomID)
201 {
202 Ref<Geometry>& g = geometries[geomID];
203 if (!g) return false;
204 return g->getModCounter() > geometryModCounters_[geomID];
205 }
206
207 protected:
208
209 __forceinline void checkIfModifiedAndSet ()
210 {
211 if (isModified ()) return;
212
213 auto geometryIsModified = [this](size_t geomID)->bool {
214 return isGeometryModified(geomID);
215 };
216
217 if (parallel_any_of (size_t(0), geometries.size (), geometryIsModified)) {
218 setModified ();
219 }
220 }
221
222 public:
223
224 /* get mesh by ID */
225 __forceinline Geometry* get(size_t i) { assert(i < geometries.size()); return geometries[i].ptr; }
226 __forceinline const Geometry* get(size_t i) const { assert(i < geometries.size()); return geometries[i].ptr; }
227
228 template<typename Mesh>
229 __forceinline Mesh* get(size_t i) {
230 assert(i < geometries.size());
231 assert(geometries[i]->getTypeMask() & Mesh::geom_type);
232 return (Mesh*)geometries[i].ptr;
233 }
234 template<typename Mesh>
235 __forceinline const Mesh* get(size_t i) const {
236 assert(i < geometries.size());
237 assert(geometries[i]->getTypeMask() & Mesh::geom_type);
238 return (Mesh*)geometries[i].ptr;
239 }
240
241 template<typename Mesh>
242 __forceinline Mesh* getSafe(size_t i) {
243 assert(i < geometries.size());
244 if (geometries[i] == null) return nullptr;
245 if (!(geometries[i]->getTypeMask() & Mesh::geom_type)) return nullptr;
246 else return (Mesh*) geometries[i].ptr;
247 }
248
249 __forceinline Ref<Geometry> get_locked(size_t i) {
250 Lock<SpinLock> lock(geometriesMutex);
251 assert(i < geometries.size());
252 return geometries[i];
253 }
254
255 /* flag decoding */
256 __forceinline bool isFastAccel() const { return !isCompactAccel() && !isRobustAccel(); }
257 __forceinline bool isCompactAccel() const { return scene_flags & RTC_SCENE_FLAG_COMPACT; }
258 __forceinline bool isRobustAccel() const { return scene_flags & RTC_SCENE_FLAG_ROBUST; }
259 __forceinline bool isStaticAccel() const { return !(scene_flags & RTC_SCENE_FLAG_DYNAMIC); }
260 __forceinline bool isDynamicAccel() const { return scene_flags & RTC_SCENE_FLAG_DYNAMIC; }
261
262 __forceinline bool hasContextFilterFunction() const {
263 return scene_flags & RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION;
264 }
265
266 __forceinline bool hasGeometryFilterFunction() {
267 return world.numFilterFunctions != 0;
268 }
269
270 __forceinline bool hasFilterFunction() {
271 return hasContextFilterFunction() || hasGeometryFilterFunction();
272 }
273
274 /* test if scene got already build */
275 __forceinline bool isBuild() const { return is_build; }
276
277 public:
278 IDPool<unsigned,0xFFFFFFFE> id_pool;
279 vector<Ref<Geometry>> geometries; //!< list of all user geometries
280 vector<unsigned int> geometryModCounters_;
281 vector<float*> vertices;
282
283 public:
284 Device* device;
285
286 /* these are to detect if we need to recreate the acceleration structures */
287 bool flags_modified;
288 unsigned int enabled_geometry_types;
289
290 RTCSceneFlags scene_flags;
291 RTCBuildQuality quality_flags;
292 MutexSys buildMutex;
293 SpinLock geometriesMutex;
294 bool is_build;
295 private:
296 bool modified; //!< true if scene got modified
297
298 public:
299
300 /*! global lock step task scheduler */
301#if defined(TASKING_INTERNAL)
302 MutexSys schedulerMutex;
303 Ref<TaskScheduler> scheduler;
304#elif defined(TASKING_TBB) && TASKING_TBB_USE_TASK_ISOLATION
305 tbb::isolated_task_group group;
306#elif defined(TASKING_TBB)
307 tbb::task_group group;
308#elif defined(TASKING_PPL)
309 concurrency::task_group group;
310#endif
311
312 public:
313 struct BuildProgressMonitorInterface : public BuildProgressMonitor {
314 BuildProgressMonitorInterface(Scene* scene)
315 : scene(scene) {}
316 void operator() (size_t dn) const { scene->progressMonitor(double(dn)); }
317 private:
318 Scene* scene;
319 };
320 BuildProgressMonitorInterface progressInterface;
321 RTCProgressMonitorFunction progress_monitor_function;
322 void* progress_monitor_ptr;
323 std::atomic<size_t> progress_monitor_counter;
324 void progressMonitor(double nprims);
325 void setProgressMonitorFunction(RTCProgressMonitorFunction func, void* ptr);
326
327 private:
328 GeometryCounts world; //!< counts for geometry
329
330 public:
331
332 __forceinline size_t numPrimitives() const {
333 return world.size();
334 }
335
336 __forceinline size_t getNumPrimitives(Geometry::GTypeMask mask, bool mblur) const
337 {
338 size_t count = 0;
339
340 if (mask & Geometry::MTY_TRIANGLE_MESH)
341 count += mblur ? world.numMBTriangles : world.numTriangles;
342
343 if (mask & Geometry::MTY_QUAD_MESH)
344 count += mblur ? world.numMBQuads : world.numQuads;
345
346 if (mask & Geometry::MTY_CURVE2)
347 count += mblur ? world.numMBLineSegments : world.numLineSegments;
348
349 if (mask & Geometry::MTY_CURVE4)
350 count += mblur ? world.numMBBezierCurves : world.numBezierCurves;
351
352 if (mask & Geometry::MTY_POINTS)
353 count += mblur ? world.numMBPoints : world.numPoints;
354
355 if (mask & Geometry::MTY_SUBDIV_MESH)
356 count += mblur ? world.numMBSubdivPatches : world.numSubdivPatches;
357
358 if (mask & Geometry::MTY_USER_GEOMETRY)
359 count += mblur ? world.numMBUserGeometries : world.numUserGeometries;
360
361 if (mask & Geometry::MTY_INSTANCE_CHEAP)
362 count += mblur ? world.numMBInstancesCheap : world.numInstancesCheap;
363
364 if (mask & Geometry::MTY_INSTANCE_EXPENSIVE)
365 count += mblur ? world.numMBInstancesExpensive : world.numInstancesExpensive;
366
367 if (mask & Geometry::MTY_GRID_MESH)
368 count += mblur ? world.numMBGrids : world.numGrids;
369
370 return count;
371 }
372
373 template<typename Mesh, bool mblur>
374 __forceinline unsigned getNumTimeSteps()
375 {
376 if (!mblur)
377 return 1;
378
379 Scene::Iterator<Mesh,mblur> iter(this);
380 return iter.maxTimeStepsPerGeometry();
381 }
382
383 template<typename Mesh, bool mblur>
384 __forceinline unsigned int getMaxGeomID()
385 {
386 Scene::Iterator<Mesh,mblur> iter(this);
387 return iter.maxGeomID();
388 }
389 };
390}
391