20 #if !defined(__MITSUBA_CORE_OCTREE_H_)
21 #define __MITSUBA_CORE_OCTREE_H_
23 #include <mitsuba/mitsuba.h>
47 value(value), next(NULL) { }
53 ListItem *cur = m_head;
55 ListItem *next = cur->next;
61 inline const ListItem *
head()
const {
66 ListItem *item =
new ListItem(value);
67 ListItem **cur = &m_head;
69 while (!atomicCompareAndExchangePtr<ListItem>(cur, item, NULL))
70 cur = &((*cur)->next);
106 for (
int i=0; i<8; ++i) {
124 m_aabb(aabb), m_maxDepth(maxDepth), m_maxItems(maxItems), m_root(NULL) { }
134 m_items.size(),
memString(m_items.size() *
sizeof(Item)).c_str());
137 std::vector<uint32_t> perm(m_items.size()), temp(m_items.size());
139 for (
uint32_t i=0; i<m_items.size(); ++i)
143 m_root = build(m_aabb, 0, &perm[0], &temp[0], &perm[0], &perm[0] + m_items.size());
148 SLog(
EDebug,
"Done (took %i ms)" , timer->getMilliseconds());
152 struct LabelOrdering :
public std::binary_function<uint32_t, uint32_t, bool> {
156 return m_items[a].label < m_items[b].label;
165 childAABB.
min.x = (child & 4) ? center.x : nodeAABB.
min.x;
166 childAABB.
max.x = (child & 4) ? nodeAABB.
max.x : center.x;
167 childAABB.
min.y = (child & 2) ? center.y : nodeAABB.
min.y;
168 childAABB.
max.y = (child & 2) ? nodeAABB.
max.y : center.y;
169 childAABB.
min.z = (child & 1) ? center.z : nodeAABB.
min.z;
170 childAABB.
max.z = (child & 1) ? nodeAABB.
max.z : center.z;
178 }
else if ((
uint32_t) (end-start) < m_maxItems || depth > m_maxDepth) {
188 memset(nestedCounts, 0,
sizeof(
uint32_t)*8);
191 for (
uint32_t *it = start; it != end; ++it) {
192 Item &item = m_items[*it];
193 const Point &p = item.getPosition();
196 if (p.x > center.x) label |= 4;
197 if (p.y > center.y) label |= 2;
198 if (p.z > center.z) label |= 1;
200 AABB bounds = childBounds(label, aabb, center);
204 nestedCounts[label]++;
208 nestedOffsets[0] = 0;
209 for (
int i=1; i<=8; ++i)
210 nestedOffsets[i] = nestedOffsets[i-1] + nestedCounts[i-1];
213 for (
uint32_t *it = start; it != end; ++it) {
214 int offset = nestedOffsets[m_items[*it].label]++;
217 memcpy(start, temp, (end-start) *
sizeof(
uint32_t));
221 for (
int i=0; i<8; i++) {
222 AABB bounds = childBounds(i, aabb, center);
224 uint32_t *it = start + nestedCounts[i];
225 result->
children[i] = build(bounds, depth+1, base, temp, start, it);
229 result->
leaf =
false;
261 : m_aabb(aabb), m_maxDepth(maxDepth) {
265 inline void insert(
const Item &value,
const AABB &coverage) {
266 insert(&m_root, m_aabb, value, coverage,
271 template <
typename Functor>
inline void lookup(
const Point &p, Functor &functor)
const {
272 if (!m_aabb.contains(p))
274 lookup(&m_root, m_aabb, p, functor);
279 if (!m_aabb.overlaps(sphere))
281 searchSphere(&m_root, m_aabb, sphere, functor);
289 for (
int i=0; i<8; ++i)
294 for (
int i=0; i<8; ++i) {
300 OctreeNode *children[8];
301 LockFreeList<Item> data;
305 inline AABB childBounds(
int child,
const AABB &nodeAABB,
const Point ¢er)
const {
307 childAABB.
min.x = (child & 4) ? center.x : nodeAABB.min.x;
308 childAABB.max.x = (child & 4) ? nodeAABB.max.x : center.x;
309 childAABB.min.y = (child & 2) ? center.y : nodeAABB.min.y;
310 childAABB.max.y = (child & 2) ? nodeAABB.max.y : center.y;
311 childAABB.min.z = (child & 1) ? center.z : nodeAABB.min.z;
312 childAABB.max.z = (child & 1) ? nodeAABB.max.z : center.z;
316 void insert(OctreeNode *node,
const AABB &nodeAABB,
const Item &value,
321 if (depth == m_maxDepth ||
322 (nodeAABB.getExtents().lengthSquared() < diag2)) {
323 node->data.append(value);
328 const Point center = nodeAABB.getCenter();
331 bool x[2] = { coverage.min.x <= center.x, coverage.max.x > center.x };
332 bool y[2] = { coverage.min.y <= center.y, coverage.max.y > center.y };
333 bool z[2] = { coverage.min.z <= center.z, coverage.max.z > center.z };
334 bool over[8] = { x[0] && y[0] && z[0], x[0] && y[0] && z[1],
335 x[0] && y[1] && z[0], x[0] && y[1] && z[1],
336 x[1] && y[0] && z[0], x[1] && y[0] && z[1],
337 x[1] && y[1] && z[0], x[1] && y[1] && z[1] };
340 for (
int child=0; child<8; ++child) {
343 if (!node->children[child]) {
344 OctreeNode *newNode =
new OctreeNode();
345 if (!atomicCompareAndExchangePtr<OctreeNode>(&node->children[child], newNode, NULL))
348 const AABB childAABB(childBounds(child, nodeAABB, center));
349 insert(node->children[child], childAABB,
350 value, coverage, diag2, depth+1);
355 template <
typename Functor>
inline void lookup(
const OctreeNode *node,
356 const AABB &nodeAABB,
const Point &p, Functor &functor)
const {
357 const Point center = nodeAABB.getCenter();
359 const typename LockFreeList<Item>::ListItem *item = node->data.head();
361 functor(item->value);
365 int child = (p.x > center.x ? 4 : 0)
366 + (p.y > center.y ? 2 : 0)
367 + (p.z > center.z ? 1 : 0);
369 OctreeNode *childNode = node->children[child];
372 const AABB childAABB(childBounds(child, nodeAABB, center));
373 lookup(node->children[child], childAABB, p, functor);
377 template <
typename Functor>
inline void searchSphere(OctreeNode *node,
378 const AABB &nodeAABB,
const BSphere &sphere,
380 const Point center = nodeAABB.getCenter();
382 const typename LockFreeList<Item>::ListItem *item = node->data.head();
384 functor(item->value);
389 for (
int child=0; child<8; ++child) {
390 if (node->children[child]) {
391 const AABB childAABB(childBounds(child, nodeAABB, center));
392 if (childAABB.overlaps(sphere))
393 searchSphere(node->children[child], childAABB, sphere, functor);
Generic multiple-reference octree with support for parallel dynamic updates.
Definition: octree.h:253
bool leaf
Definition: octree.h:90
NodeData data
Definition: octree.h:91
uint32_t count
Definition: octree.h:100
void permute_inplace(DataType *data, std::vector< IndexType > &perm)
Apply an arbitrary permutation to an array in linear time.
Definition: util.h:238
PointType max
Component-wise maximum.
Definition: aabb.h:425
void append(const T &value)
Definition: octree.h:65
const ListItem * head() const
Definition: octree.h:61
OctreeNode * children[8]
Definition: octree.h:95
~OctreeNode()
Definition: octree.h:104
void searchSphere(const BSphere &sphere, Functor &functor)
Execute functor.operator() on all records, which potentially overlap bsphere.
Definition: octree.h:278
Lock-free linked list data structure.
Definition: octree.h:40
Bounding sphere data structure in three dimensions.
Definition: bsphere.h:32
Generic single-reference static octree.
Definition: octree.h:87
const AABB & getAABB() const
Definition: octree.h:284
#define SLog(level, fmt,...)
Write a Log message to the console (static version - to be used outside of classes that derive from O...
Definition: logger.h:49
Debug message, usually turned off.
Definition: formatter.h:30
AABB m_aabb
Definition: octree.h:236
StaticOctree()
Definition: octree.h:234
uint32_t m_maxDepth
Definition: octree.h:238
uint32_t m_maxItems
Definition: octree.h:239
Axis-aligned bounding box data structure in three dimensions.
Definition: aabb.h:437
std::vector< Item > m_items
Definition: octree.h:237
OctreeNode * build(const AABB &aabb, uint32_t depth, uint32_t *base, uint32_t *temp, uint32_t *start, uint32_t *end)
Definition: octree.h:174
#define SAssert(cond)
``Static'' assertion (to be used outside of classes that derive from Object)
Definition: logger.h:79
T value
Definition: octree.h:43
OctreeNode * m_root
Definition: octree.h:240
Reference counting helper.
Definition: ref.h:40
ListItem(const T &value)
Definition: octree.h:46
AABB childBounds(int child, const AABB &nodeAABB, const Point ¢er) const
Return the AABB for a child of the specified index.
Definition: octree.h:163
~LockFreeList()
Definition: octree.h:52
MTS_EXPORT_CORE std::string memString(size_t size, bool precise=false)
Turn a memory size into a human-readable string.
Platform independent milli/micro/nanosecond timerThis class implements a simple cross-platform timer ...
Definition: timer.h:37
PointType getCenter() const
Return the center point.
Definition: aabb.h:132
VectorType getExtents() const
Calculate the bounding box extents.
Definition: aabb.h:292
uint32_t offset
Definition: octree.h:99
void build()
Definition: octree.h:132
DynamicOctree(const AABB &aabb, uint32_t maxDepth=24)
Create a new octree.
Definition: octree.h:260
PointType min
Component-wise minimum.
Definition: aabb.h:424
void insert(const Item &value, const AABB &coverage)
Insert an item with the specified cell coverage.
Definition: octree.h:265
LabelOrdering(const std::vector< Item > &items)
Definition: octree.h:153
bool contains(const PointType &p) const
Check whether a point lies on or inside the bounding box.
Definition: aabb.h:163
void lookup(const Point &p, Functor &functor) const
Execute functor.operator() on all records, which potentially overlap p.
Definition: octree.h:271
~StaticOctree()
Release all memory.
Definition: octree.h:127
LockFreeList()
Definition: octree.h:50
const std::vector< Item > & m_items
Definition: octree.h:159
bool operator()(uint32_t a, uint32_t b) const
Definition: octree.h:155
StaticOctree(const AABB &aabb, uint32_t maxDepth=24, uint32_t maxItems=8)
Create a new octree.
Definition: octree.h:123
ListItem * next
Definition: octree.h:44