bvh_builder_morton.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include "bvh.h"
  4. #include "bvh_statistics.h"
  5. #include "bvh_rotate.h"
  6. #include "../common/profile.h"
  7. #include "../../common/algorithms/parallel_prefix_sum.h"
  8. #include "../builders/primrefgen.h"
  9. #include "../builders/bvh_builder_morton.h"
  10. #include "../geometry/triangle.h"
  11. #include "../geometry/trianglev.h"
  12. #include "../geometry/trianglei.h"
  13. #include "../geometry/quadv.h"
  14. #include "../geometry/quadi.h"
  15. #include "../geometry/object.h"
  16. #include "../geometry/instance.h"
  17. #include "../geometry/instance_array.h"
  18. #if defined(__64BIT__)
  19. # define ROTATE_TREE 1 // specifies number of tree rotation rounds to perform
  20. #else
  21. # define ROTATE_TREE 0 // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues
  22. #endif
  23. namespace embree
  24. {
  25. namespace isa
  26. {
  27. template<int N>
  28. struct SetBVHNBounds
  29. {
  30. typedef BVHN<N> BVH;
  31. typedef typename BVH::NodeRef NodeRef;
  32. typedef typename BVH::NodeRecord NodeRecord;
  33. typedef typename BVH::AABBNode AABBNode;
  34. BVH* bvh;
  35. __forceinline SetBVHNBounds (BVH* bvh) : bvh(bvh) {}
  36. __forceinline NodeRecord operator() (NodeRef ref, const NodeRecord* children, size_t num)
  37. {
  38. AABBNode* node = ref.getAABBNode();
  39. BBox3fa res = empty;
  40. for (size_t i=0; i<num; i++) {
  41. const BBox3fa b = children[i].bounds;
  42. res.extend(b);
  43. node->setRef(i,children[i].ref);
  44. node->setBounds(i,b);
  45. }
  46. BBox3fx result = (BBox3fx&)res;
  47. #if ROTATE_TREE
  48. if (N == 4)
  49. {
  50. size_t n = 0;
  51. for (size_t i=0; i<num; i++)
  52. n += children[i].bounds.lower.a;
  53. if (n >= 4096) {
  54. for (size_t i=0; i<num; i++) {
  55. if (children[i].bounds.lower.a < 4096) {
  56. for (int j=0; j<ROTATE_TREE; j++)
  57. BVHNRotate<N>::rotate(node->child(i));
  58. node->child(i).setBarrier();
  59. }
  60. }
  61. }
  62. result.lower.a = unsigned(n);
  63. }
  64. #endif
  65. return NodeRecord(ref,result);
  66. }
  67. };
  68. template<int N, typename Primitive>
  69. struct CreateMortonLeaf;
  70. template<int N>
  71. struct CreateMortonLeaf<N,Triangle4>
  72. {
  73. typedef BVHN<N> BVH;
  74. typedef typename BVH::NodeRef NodeRef;
  75. typedef typename BVH::NodeRecord NodeRecord;
  76. __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  77. : mesh(mesh), morton(morton), geomID_(geomID) {}
  78. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  79. {
  80. vfloat4 lower(pos_inf);
  81. vfloat4 upper(neg_inf);
  82. size_t items = current.size();
  83. size_t start = current.begin();
  84. assert(items<=4);
  85. /* allocate leaf node */
  86. Triangle4* accel = (Triangle4*) alloc.malloc1(sizeof(Triangle4),BVH::byteAlignment);
  87. NodeRef ref = BVH::encodeLeaf((char*)accel,1);
  88. vuint4 vgeomID = -1, vprimID = -1;
  89. Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
  90. const TriangleMesh* __restrict__ const mesh = this->mesh;
  91. for (size_t i=0; i<items; i++)
  92. {
  93. const unsigned int primID = morton[start+i].index;
  94. const TriangleMesh::Triangle& tri = mesh->triangle(primID);
  95. const Vec3fa& p0 = mesh->vertex(tri.v[0]);
  96. const Vec3fa& p1 = mesh->vertex(tri.v[1]);
  97. const Vec3fa& p2 = mesh->vertex(tri.v[2]);
  98. lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  99. upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  100. vgeomID [i] = geomID_;
  101. vprimID [i] = primID;
  102. v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
  103. v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
  104. v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
  105. }
  106. Triangle4::store_nt(accel,Triangle4(v0,v1,v2,vgeomID,vprimID));
  107. BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
  108. #if ROTATE_TREE
  109. if (N == 4)
  110. box_o.lower.a = unsigned(current.size());
  111. #endif
  112. return NodeRecord(ref,box_o);
  113. }
  114. private:
  115. TriangleMesh* mesh;
  116. BVHBuilderMorton::BuildPrim* morton;
  117. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  118. };
  119. template<int N>
  120. struct CreateMortonLeaf<N,Triangle4v>
  121. {
  122. typedef BVHN<N> BVH;
  123. typedef typename BVH::NodeRef NodeRef;
  124. typedef typename BVH::NodeRecord NodeRecord;
  125. __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  126. : mesh(mesh), morton(morton), geomID_(geomID) {}
  127. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  128. {
  129. vfloat4 lower(pos_inf);
  130. vfloat4 upper(neg_inf);
  131. size_t items = current.size();
  132. size_t start = current.begin();
  133. assert(items<=4);
  134. /* allocate leaf node */
  135. Triangle4v* accel = (Triangle4v*) alloc.malloc1(sizeof(Triangle4v),BVH::byteAlignment);
  136. NodeRef ref = BVH::encodeLeaf((char*)accel,1);
  137. vuint4 vgeomID = -1, vprimID = -1;
  138. Vec3vf4 v0 = zero, v1 = zero, v2 = zero;
  139. const TriangleMesh* __restrict__ mesh = this->mesh;
  140. for (size_t i=0; i<items; i++)
  141. {
  142. const unsigned int primID = morton[start+i].index;
  143. const TriangleMesh::Triangle& tri = mesh->triangle(primID);
  144. const Vec3fa& p0 = mesh->vertex(tri.v[0]);
  145. const Vec3fa& p1 = mesh->vertex(tri.v[1]);
  146. const Vec3fa& p2 = mesh->vertex(tri.v[2]);
  147. lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  148. upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  149. vgeomID [i] = geomID_;
  150. vprimID [i] = primID;
  151. v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
  152. v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
  153. v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
  154. }
  155. Triangle4v::store_nt(accel,Triangle4v(v0,v1,v2,vgeomID,vprimID));
  156. BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
  157. #if ROTATE_TREE
  158. if (N == 4)
  159. box_o.lower.a = current.size();
  160. #endif
  161. return NodeRecord(ref,box_o);
  162. }
  163. private:
  164. TriangleMesh* mesh;
  165. BVHBuilderMorton::BuildPrim* morton;
  166. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  167. };
  168. template<int N>
  169. struct CreateMortonLeaf<N,Triangle4i>
  170. {
  171. typedef BVHN<N> BVH;
  172. typedef typename BVH::NodeRef NodeRef;
  173. typedef typename BVH::NodeRecord NodeRecord;
  174. __forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  175. : mesh(mesh), morton(morton), geomID_(geomID) {}
  176. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  177. {
  178. vfloat4 lower(pos_inf);
  179. vfloat4 upper(neg_inf);
  180. size_t items = current.size();
  181. size_t start = current.begin();
  182. assert(items<=4);
  183. /* allocate leaf node */
  184. Triangle4i* accel = (Triangle4i*) alloc.malloc1(sizeof(Triangle4i),BVH::byteAlignment);
  185. NodeRef ref = BVH::encodeLeaf((char*)accel,1);
  186. vuint4 v0 = zero, v1 = zero, v2 = zero;
  187. vuint4 vgeomID = -1, vprimID = -1;
  188. const TriangleMesh* __restrict__ const mesh = this->mesh;
  189. for (size_t i=0; i<items; i++)
  190. {
  191. const unsigned int primID = morton[start+i].index;
  192. const TriangleMesh::Triangle& tri = mesh->triangle(primID);
  193. const Vec3fa& p0 = mesh->vertex(tri.v[0]);
  194. const Vec3fa& p1 = mesh->vertex(tri.v[1]);
  195. const Vec3fa& p2 = mesh->vertex(tri.v[2]);
  196. lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  197. upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);
  198. vgeomID[i] = geomID_;
  199. vprimID[i] = primID;
  200. unsigned int int_stride = mesh->vertices0.getStride()/4;
  201. v0[i] = tri.v[0] * int_stride;
  202. v1[i] = tri.v[1] * int_stride;
  203. v2[i] = tri.v[2] * int_stride;
  204. }
  205. for (size_t i=items; i<4; i++)
  206. {
  207. vgeomID[i] = vgeomID[0];
  208. vprimID[i] = -1;
  209. v0[i] = 0;
  210. v1[i] = 0;
  211. v2[i] = 0;
  212. }
  213. Triangle4i::store_nt(accel,Triangle4i(v0,v1,v2,vgeomID,vprimID));
  214. BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
  215. #if ROTATE_TREE
  216. if (N == 4)
  217. box_o.lower.a = current.size();
  218. #endif
  219. return NodeRecord(ref,box_o);
  220. }
  221. private:
  222. TriangleMesh* mesh;
  223. BVHBuilderMorton::BuildPrim* morton;
  224. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  225. };
  226. template<int N>
  227. struct CreateMortonLeaf<N,Quad4v>
  228. {
  229. typedef BVHN<N> BVH;
  230. typedef typename BVH::NodeRef NodeRef;
  231. typedef typename BVH::NodeRecord NodeRecord;
  232. __forceinline CreateMortonLeaf (QuadMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  233. : mesh(mesh), morton(morton), geomID_(geomID) {}
  234. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  235. {
  236. vfloat4 lower(pos_inf);
  237. vfloat4 upper(neg_inf);
  238. size_t items = current.size();
  239. size_t start = current.begin();
  240. assert(items<=4);
  241. /* allocate leaf node */
  242. Quad4v* accel = (Quad4v*) alloc.malloc1(sizeof(Quad4v),BVH::byteAlignment);
  243. NodeRef ref = BVH::encodeLeaf((char*)accel,1);
  244. vuint4 vgeomID = -1, vprimID = -1;
  245. Vec3vf4 v0 = zero, v1 = zero, v2 = zero, v3 = zero;
  246. const QuadMesh* __restrict__ mesh = this->mesh;
  247. for (size_t i=0; i<items; i++)
  248. {
  249. const unsigned int primID = morton[start+i].index;
  250. const QuadMesh::Quad& tri = mesh->quad(primID);
  251. const Vec3fa& p0 = mesh->vertex(tri.v[0]);
  252. const Vec3fa& p1 = mesh->vertex(tri.v[1]);
  253. const Vec3fa& p2 = mesh->vertex(tri.v[2]);
  254. const Vec3fa& p3 = mesh->vertex(tri.v[3]);
  255. lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
  256. upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);
  257. vgeomID [i] = geomID_;
  258. vprimID [i] = primID;
  259. v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;
  260. v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;
  261. v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;
  262. v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;
  263. }
  264. Quad4v::store_nt(accel,Quad4v(v0,v1,v2,v3,vgeomID,vprimID));
  265. BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);
  266. #if ROTATE_TREE
  267. if (N == 4)
  268. box_o.lower.a = current.size();
  269. #endif
  270. return NodeRecord(ref,box_o);
  271. }
  272. private:
  273. QuadMesh* mesh;
  274. BVHBuilderMorton::BuildPrim* morton;
  275. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  276. };
  277. template<int N>
  278. struct CreateMortonLeaf<N,Object>
  279. {
  280. typedef BVHN<N> BVH;
  281. typedef typename BVH::NodeRef NodeRef;
  282. typedef typename BVH::NodeRecord NodeRecord;
  283. __forceinline CreateMortonLeaf (UserGeometry* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  284. : mesh(mesh), morton(morton), geomID_(geomID) {}
  285. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  286. {
  287. vfloat4 lower(pos_inf);
  288. vfloat4 upper(neg_inf);
  289. size_t items = current.size();
  290. size_t start = current.begin();
  291. /* allocate leaf node */
  292. Object* accel = (Object*) alloc.malloc1(items*sizeof(Object),BVH::byteAlignment);
  293. NodeRef ref = BVH::encodeLeaf((char*)accel,items);
  294. const UserGeometry* mesh = this->mesh;
  295. BBox3fa bounds = empty;
  296. for (size_t i=0; i<items; i++)
  297. {
  298. const unsigned int index = morton[start+i].index;
  299. const unsigned int primID = index;
  300. bounds.extend(mesh->bounds(primID));
  301. new (&accel[i]) Object(geomID_,primID);
  302. }
  303. BBox3fx box_o = (BBox3fx&)bounds;
  304. #if ROTATE_TREE
  305. if (N == 4)
  306. box_o.lower.a = current.size();
  307. #endif
  308. return NodeRecord(ref,box_o);
  309. }
  310. private:
  311. UserGeometry* mesh;
  312. BVHBuilderMorton::BuildPrim* morton;
  313. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  314. };
  315. template<int N>
  316. struct CreateMortonLeaf<N,InstancePrimitive>
  317. {
  318. typedef BVHN<N> BVH;
  319. typedef typename BVH::NodeRef NodeRef;
  320. typedef typename BVH::NodeRecord NodeRecord;
  321. __forceinline CreateMortonLeaf (Instance* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  322. : mesh(mesh), morton(morton), geomID_(geomID) {}
  323. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  324. {
  325. vfloat4 lower(pos_inf);
  326. vfloat4 upper(neg_inf);
  327. size_t items = current.size();
  328. size_t start = current.begin();
  329. assert(items <= 1);
  330. /* allocate leaf node */
  331. InstancePrimitive* accel = (InstancePrimitive*) alloc.malloc1(items*sizeof(InstancePrimitive),BVH::byteAlignment);
  332. NodeRef ref = BVH::encodeLeaf((char*)accel,items);
  333. const Instance* instance = this->mesh;
  334. BBox3fa bounds = empty;
  335. for (size_t i=0; i<items; i++)
  336. {
  337. const unsigned int primID = morton[start+i].index;
  338. bounds.extend(instance->bounds(primID));
  339. new (&accel[i]) InstancePrimitive(instance, geomID_);
  340. }
  341. BBox3fx box_o = (BBox3fx&)bounds;
  342. #if ROTATE_TREE
  343. if (N == 4)
  344. box_o.lower.a = current.size();
  345. #endif
  346. return NodeRecord(ref,box_o);
  347. }
  348. private:
  349. Instance* mesh;
  350. BVHBuilderMorton::BuildPrim* morton;
  351. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  352. };
  353. template<int N>
  354. struct CreateMortonLeaf<N,InstanceArrayPrimitive>
  355. {
  356. typedef BVHN<N> BVH;
  357. typedef typename BVH::NodeRef NodeRef;
  358. typedef typename BVH::NodeRecord NodeRecord;
  359. __forceinline CreateMortonLeaf (InstanceArray* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)
  360. : mesh(mesh), morton(morton), geomID_(geomID) {}
  361. __noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)
  362. {
  363. vfloat4 lower(pos_inf);
  364. vfloat4 upper(neg_inf);
  365. size_t items = current.size();
  366. size_t start = current.begin();
  367. assert(items <= 1);
  368. /* allocate leaf node */
  369. InstanceArrayPrimitive* accel = (InstanceArrayPrimitive*) alloc.malloc1(items*sizeof(InstanceArrayPrimitive),BVH::byteAlignment);
  370. NodeRef ref = BVH::encodeLeaf((char*)accel,items);
  371. const InstanceArray* instance = this->mesh;
  372. BBox3fa bounds = empty;
  373. for (size_t i=0; i<items; i++)
  374. {
  375. const unsigned int primID = morton[start+i].index;
  376. bounds.extend(instance->bounds(primID));
  377. new (&accel[i]) InstanceArrayPrimitive(geomID_, primID);
  378. }
  379. BBox3fx box_o = (BBox3fx&)bounds;
  380. #if ROTATE_TREE
  381. if (N == 4)
  382. box_o.lower.a = current.size();
  383. #endif
  384. return NodeRecord(ref,box_o);
  385. }
  386. private:
  387. InstanceArray* mesh;
  388. BVHBuilderMorton::BuildPrim* morton;
  389. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  390. };
  391. template<typename Mesh>
  392. struct CalculateMeshBounds
  393. {
  394. __forceinline CalculateMeshBounds (Mesh* mesh)
  395. : mesh(mesh) {}
  396. __forceinline const BBox3fa operator() (const BVHBuilderMorton::BuildPrim& morton) {
  397. return mesh->bounds(morton.index);
  398. }
  399. private:
  400. Mesh* mesh;
  401. };
  402. template<int N, typename Mesh, typename Primitive>
  403. class BVHNMeshBuilderMorton : public Builder
  404. {
  405. typedef BVHN<N> BVH;
  406. typedef typename BVH::AABBNode AABBNode;
  407. typedef typename BVH::NodeRef NodeRef;
  408. typedef typename BVH::NodeRecord NodeRecord;
  409. public:
  410. BVHNMeshBuilderMorton (BVH* bvh, Mesh* mesh, unsigned int geomID, const size_t minLeafSize, const size_t maxLeafSize, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD)
  411. : bvh(bvh), mesh(mesh), morton(bvh->device,0), settings(N,BVH::maxBuildDepth,minLeafSize,min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks),singleThreadThreshold), geomID_(geomID) {}
  412. /* build function */
  413. void build()
  414. {
  415. /* we reset the allocator when the mesh size changed */
  416. if (mesh->numPrimitives != numPreviousPrimitives) {
  417. bvh->alloc.clear();
  418. morton.clear();
  419. }
  420. size_t numPrimitives = mesh->size();
  421. numPreviousPrimitives = numPrimitives;
  422. /* skip build for empty scene */
  423. if (numPrimitives == 0) {
  424. bvh->set(BVH::emptyNode,empty,0);
  425. return;
  426. }
  427. /* preallocate arrays */
  428. morton.resize(numPrimitives);
  429. size_t bytesEstimated = numPrimitives*sizeof(AABBNode)/(4*N) + size_t(1.2f*Primitive::blocks(numPrimitives)*sizeof(Primitive));
  430. size_t bytesMortonCodes = numPrimitives*sizeof(BVHBuilderMorton::BuildPrim);
  431. bytesEstimated = max(bytesEstimated,bytesMortonCodes); // the first allocation block is reused to sort the morton codes
  432. bvh->alloc.init(bytesMortonCodes,bytesMortonCodes,bytesEstimated);
  433. /* create morton code array */
  434. BVHBuilderMorton::BuildPrim* dest = (BVHBuilderMorton::BuildPrim*) bvh->alloc.specialAlloc(bytesMortonCodes);
  435. size_t numPrimitivesGen = createMortonCodeArray<Mesh>(mesh,morton,bvh->scene->progressInterface);
  436. /* create BVH */
  437. SetBVHNBounds<N> setBounds(bvh);
  438. CreateMortonLeaf<N,Primitive> createLeaf(mesh,geomID_,morton.data());
  439. CalculateMeshBounds<Mesh> calculateBounds(mesh);
  440. auto root = BVHBuilderMorton::build<NodeRecord>(
  441. typename BVH::CreateAlloc(bvh),
  442. typename BVH::AABBNode::Create(),
  443. setBounds,createLeaf,calculateBounds,bvh->scene->progressInterface,
  444. morton.data(),dest,numPrimitivesGen,settings);
  445. bvh->set(root.ref,LBBox3fa(root.bounds),numPrimitives);
  446. #if ROTATE_TREE
  447. if (N == 4)
  448. {
  449. for (int i=0; i<ROTATE_TREE; i++)
  450. BVHNRotate<N>::rotate(bvh->root);
  451. bvh->clearBarrier(bvh->root);
  452. }
  453. #endif
  454. /* clear temporary data for static geometry */
  455. if (bvh->scene->isStaticAccel()) {
  456. morton.clear();
  457. }
  458. bvh->cleanup();
  459. }
  460. void clear() {
  461. morton.clear();
  462. }
  463. private:
  464. BVH* bvh;
  465. Mesh* mesh;
  466. mvector<BVHBuilderMorton::BuildPrim> morton;
  467. BVHBuilderMorton::Settings settings;
  468. unsigned int geomID_ = std::numeric_limits<unsigned int>::max();
  469. unsigned int numPreviousPrimitives = 0;
  470. };
  471. #if defined(EMBREE_GEOMETRY_TRIANGLE)
  472. Builder* BVH4Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4> ((BVH4*)bvh,mesh,geomID,4,4); }
  473. Builder* BVH4Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4v>((BVH4*)bvh,mesh,geomID,4,4); }
  474. Builder* BVH4Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4i>((BVH4*)bvh,mesh,geomID,4,4); }
  475. #if defined(__AVX__)
  476. Builder* BVH8Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4> ((BVH8*)bvh,mesh,geomID,4,4); }
  477. Builder* BVH8Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4v>((BVH8*)bvh,mesh,geomID,4,4); }
  478. Builder* BVH8Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4i>((BVH8*)bvh,mesh,geomID,4,4); }
  479. #endif
  480. #endif
  481. #if defined(EMBREE_GEOMETRY_QUAD)
  482. Builder* BVH4Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,QuadMesh,Quad4v>((BVH4*)bvh,mesh,geomID,4,4); }
  483. #if defined(__AVX__)
  484. Builder* BVH8Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,QuadMesh,Quad4v>((BVH8*)bvh,mesh,geomID,4,4); }
  485. #endif
  486. #endif
  487. #if defined(EMBREE_GEOMETRY_USER)
  488. Builder* BVH4VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,UserGeometry,Object>((BVH4*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
  489. #if defined(__AVX__)
  490. Builder* BVH8VirtualMeshBuilderMortonGeneral (void* bvh, UserGeometry* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,UserGeometry,Object>((BVH8*)bvh,mesh,geomID,1,BVH4::maxLeafBlocks); }
  491. #endif
  492. #endif
  493. #if defined(EMBREE_GEOMETRY_INSTANCE)
  494. Builder* BVH4InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,Instance,InstancePrimitive>((BVH4*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
  495. #if defined(__AVX__)
  496. Builder* BVH8InstanceMeshBuilderMortonGeneral (void* bvh, Instance* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,Instance,InstancePrimitive>((BVH8*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
  497. #endif
  498. #endif
  499. #if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)
  500. Builder* BVH4InstanceArrayMeshBuilderMortonGeneral (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,InstanceArray,InstanceArrayPrimitive>((BVH4*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
  501. #if defined(__AVX__)
  502. Builder* BVH8InstanceArrayMeshBuilderMortonGeneral (void* bvh, InstanceArray* mesh, Geometry::GTypeMask gtype, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,InstanceArray,InstanceArrayPrimitive>((BVH8*)bvh,mesh,gtype,geomID,1,BVH4::maxLeafBlocks); }
  503. #endif
  504. #endif
  505. }
  506. }