Path: blob/master/thirdparty/embree/kernels/bvh/bvh_builder_morton.cpp
9906 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#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"89#include "../builders/primrefgen.h"10#include "../builders/bvh_builder_morton.h"1112#include "../geometry/triangle.h"13#include "../geometry/trianglev.h"14#include "../geometry/trianglei.h"15#include "../geometry/quadv.h"16#include "../geometry/quadi.h"17#include "../geometry/object.h"18#include "../geometry/instance.h"19#include "../geometry/instance_array.h"2021#if defined(__64BIT__)22# define ROTATE_TREE 1 // specifies number of tree rotation rounds to perform23#else24# define ROTATE_TREE 0 // do not use tree rotations on 32 bit platforms, barrier bit in NodeRef will cause issues25#endif2627namespace embree28{29namespace isa30{31template<int N>32struct SetBVHNBounds33{34typedef BVHN<N> BVH;35typedef typename BVH::NodeRef NodeRef;36typedef typename BVH::NodeRecord NodeRecord;37typedef typename BVH::AABBNode AABBNode;3839BVH* bvh;40__forceinline SetBVHNBounds (BVH* bvh) : bvh(bvh) {}4142__forceinline NodeRecord operator() (NodeRef ref, const NodeRecord* children, size_t num)43{44AABBNode* node = ref.getAABBNode();4546BBox3fa res = empty;47for (size_t i=0; i<num; i++) {48const BBox3fa b = children[i].bounds;49res.extend(b);50node->setRef(i,children[i].ref);51node->setBounds(i,b);52}5354BBox3fx result = (BBox3fx&)res;55#if ROTATE_TREE56if (N == 4)57{58size_t n = 0;59for (size_t i=0; i<num; i++)60n += children[i].bounds.lower.a;6162if (n >= 4096) {63for (size_t i=0; i<num; i++) {64if (children[i].bounds.lower.a < 4096) {65for (int j=0; j<ROTATE_TREE; j++)66BVHNRotate<N>::rotate(node->child(i));67node->child(i).setBarrier();68}69}70}71result.lower.a = unsigned(n);72}73#endif7475return NodeRecord(ref,result);76}77};7879template<int N, typename Primitive>80struct CreateMortonLeaf;8182template<int N>83struct CreateMortonLeaf<N,Triangle4>84{85typedef BVHN<N> BVH;86typedef typename BVH::NodeRef NodeRef;87typedef typename BVH::NodeRecord NodeRecord;8889__forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)90: mesh(mesh), morton(morton), geomID_(geomID) {}9192__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)93{94vfloat4 lower(pos_inf);95vfloat4 upper(neg_inf);96size_t items = current.size();97size_t start = current.begin();98assert(items<=4);99100/* allocate leaf node */101Triangle4* accel = (Triangle4*) alloc.malloc1(sizeof(Triangle4),BVH::byteAlignment);102NodeRef ref = BVH::encodeLeaf((char*)accel,1);103vuint4 vgeomID = -1, vprimID = -1;104Vec3vf4 v0 = zero, v1 = zero, v2 = zero;105const TriangleMesh* __restrict__ const mesh = this->mesh;106107for (size_t i=0; i<items; i++)108{109const unsigned int primID = morton[start+i].index;110const TriangleMesh::Triangle& tri = mesh->triangle(primID);111const Vec3fa& p0 = mesh->vertex(tri.v[0]);112const Vec3fa& p1 = mesh->vertex(tri.v[1]);113const Vec3fa& p2 = mesh->vertex(tri.v[2]);114lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);115upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);116vgeomID [i] = geomID_;117vprimID [i] = primID;118v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;119v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;120v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;121}122123Triangle4::store_nt(accel,Triangle4(v0,v1,v2,vgeomID,vprimID));124BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);125#if ROTATE_TREE126if (N == 4)127box_o.lower.a = unsigned(current.size());128#endif129return NodeRecord(ref,box_o);130}131132private:133TriangleMesh* mesh;134BVHBuilderMorton::BuildPrim* morton;135unsigned int geomID_ = std::numeric_limits<unsigned int>::max();136};137138template<int N>139struct CreateMortonLeaf<N,Triangle4v>140{141typedef BVHN<N> BVH;142typedef typename BVH::NodeRef NodeRef;143typedef typename BVH::NodeRecord NodeRecord;144145__forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)146: mesh(mesh), morton(morton), geomID_(geomID) {}147148__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)149{150vfloat4 lower(pos_inf);151vfloat4 upper(neg_inf);152size_t items = current.size();153size_t start = current.begin();154assert(items<=4);155156/* allocate leaf node */157Triangle4v* accel = (Triangle4v*) alloc.malloc1(sizeof(Triangle4v),BVH::byteAlignment);158NodeRef ref = BVH::encodeLeaf((char*)accel,1);159vuint4 vgeomID = -1, vprimID = -1;160Vec3vf4 v0 = zero, v1 = zero, v2 = zero;161const TriangleMesh* __restrict__ mesh = this->mesh;162163for (size_t i=0; i<items; i++)164{165const unsigned int primID = morton[start+i].index;166const TriangleMesh::Triangle& tri = mesh->triangle(primID);167const Vec3fa& p0 = mesh->vertex(tri.v[0]);168const Vec3fa& p1 = mesh->vertex(tri.v[1]);169const Vec3fa& p2 = mesh->vertex(tri.v[2]);170lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);171upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);172vgeomID [i] = geomID_;173vprimID [i] = primID;174v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;175v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;176v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;177}178Triangle4v::store_nt(accel,Triangle4v(v0,v1,v2,vgeomID,vprimID));179BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);180#if ROTATE_TREE181if (N == 4)182box_o.lower.a = current.size();183#endif184return NodeRecord(ref,box_o);185}186private:187TriangleMesh* mesh;188BVHBuilderMorton::BuildPrim* morton;189unsigned int geomID_ = std::numeric_limits<unsigned int>::max();190};191192template<int N>193struct CreateMortonLeaf<N,Triangle4i>194{195typedef BVHN<N> BVH;196typedef typename BVH::NodeRef NodeRef;197typedef typename BVH::NodeRecord NodeRecord;198199__forceinline CreateMortonLeaf (TriangleMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)200: mesh(mesh), morton(morton), geomID_(geomID) {}201202__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)203{204vfloat4 lower(pos_inf);205vfloat4 upper(neg_inf);206size_t items = current.size();207size_t start = current.begin();208assert(items<=4);209210/* allocate leaf node */211Triangle4i* accel = (Triangle4i*) alloc.malloc1(sizeof(Triangle4i),BVH::byteAlignment);212NodeRef ref = BVH::encodeLeaf((char*)accel,1);213214vuint4 v0 = zero, v1 = zero, v2 = zero;215vuint4 vgeomID = -1, vprimID = -1;216const TriangleMesh* __restrict__ const mesh = this->mesh;217218for (size_t i=0; i<items; i++)219{220const unsigned int primID = morton[start+i].index;221const TriangleMesh::Triangle& tri = mesh->triangle(primID);222const Vec3fa& p0 = mesh->vertex(tri.v[0]);223const Vec3fa& p1 = mesh->vertex(tri.v[1]);224const Vec3fa& p2 = mesh->vertex(tri.v[2]);225lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);226upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2);227vgeomID[i] = geomID_;228vprimID[i] = primID;229unsigned int int_stride = mesh->vertices0.getStride()/4;230v0[i] = tri.v[0] * int_stride;231v1[i] = tri.v[1] * int_stride;232v2[i] = tri.v[2] * int_stride;233}234235for (size_t i=items; i<4; i++)236{237vgeomID[i] = vgeomID[0];238vprimID[i] = -1;239v0[i] = 0;240v1[i] = 0;241v2[i] = 0;242}243Triangle4i::store_nt(accel,Triangle4i(v0,v1,v2,vgeomID,vprimID));244BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);245#if ROTATE_TREE246if (N == 4)247box_o.lower.a = current.size();248#endif249return NodeRecord(ref,box_o);250}251private:252TriangleMesh* mesh;253BVHBuilderMorton::BuildPrim* morton;254unsigned int geomID_ = std::numeric_limits<unsigned int>::max();255};256257template<int N>258struct CreateMortonLeaf<N,Quad4v>259{260typedef BVHN<N> BVH;261typedef typename BVH::NodeRef NodeRef;262typedef typename BVH::NodeRecord NodeRecord;263264__forceinline CreateMortonLeaf (QuadMesh* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)265: mesh(mesh), morton(morton), geomID_(geomID) {}266267__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)268{269vfloat4 lower(pos_inf);270vfloat4 upper(neg_inf);271size_t items = current.size();272size_t start = current.begin();273assert(items<=4);274275/* allocate leaf node */276Quad4v* accel = (Quad4v*) alloc.malloc1(sizeof(Quad4v),BVH::byteAlignment);277NodeRef ref = BVH::encodeLeaf((char*)accel,1);278279vuint4 vgeomID = -1, vprimID = -1;280Vec3vf4 v0 = zero, v1 = zero, v2 = zero, v3 = zero;281const QuadMesh* __restrict__ mesh = this->mesh;282283for (size_t i=0; i<items; i++)284{285const unsigned int primID = morton[start+i].index;286const QuadMesh::Quad& tri = mesh->quad(primID);287const Vec3fa& p0 = mesh->vertex(tri.v[0]);288const Vec3fa& p1 = mesh->vertex(tri.v[1]);289const Vec3fa& p2 = mesh->vertex(tri.v[2]);290const Vec3fa& p3 = mesh->vertex(tri.v[3]);291lower = min(lower,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);292upper = max(upper,(vfloat4)p0,(vfloat4)p1,(vfloat4)p2,(vfloat4)p3);293vgeomID [i] = geomID_;294vprimID [i] = primID;295v0.x[i] = p0.x; v0.y[i] = p0.y; v0.z[i] = p0.z;296v1.x[i] = p1.x; v1.y[i] = p1.y; v1.z[i] = p1.z;297v2.x[i] = p2.x; v2.y[i] = p2.y; v2.z[i] = p2.z;298v3.x[i] = p3.x; v3.y[i] = p3.y; v3.z[i] = p3.z;299}300Quad4v::store_nt(accel,Quad4v(v0,v1,v2,v3,vgeomID,vprimID));301BBox3fx box_o = BBox3fx((Vec3fx)lower,(Vec3fx)upper);302#if ROTATE_TREE303if (N == 4)304box_o.lower.a = current.size();305#endif306return NodeRecord(ref,box_o);307}308private:309QuadMesh* mesh;310BVHBuilderMorton::BuildPrim* morton;311unsigned int geomID_ = std::numeric_limits<unsigned int>::max();312};313314template<int N>315struct CreateMortonLeaf<N,Object>316{317typedef BVHN<N> BVH;318typedef typename BVH::NodeRef NodeRef;319typedef typename BVH::NodeRecord NodeRecord;320321__forceinline CreateMortonLeaf (UserGeometry* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)322: mesh(mesh), morton(morton), geomID_(geomID) {}323324__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)325{326vfloat4 lower(pos_inf);327vfloat4 upper(neg_inf);328size_t items = current.size();329size_t start = current.begin();330331/* allocate leaf node */332Object* accel = (Object*) alloc.malloc1(items*sizeof(Object),BVH::byteAlignment);333NodeRef ref = BVH::encodeLeaf((char*)accel,items);334const UserGeometry* mesh = this->mesh;335336BBox3fa bounds = empty;337for (size_t i=0; i<items; i++)338{339const unsigned int index = morton[start+i].index;340const unsigned int primID = index;341bounds.extend(mesh->bounds(primID));342new (&accel[i]) Object(geomID_,primID);343}344345BBox3fx box_o = (BBox3fx&)bounds;346#if ROTATE_TREE347if (N == 4)348box_o.lower.a = current.size();349#endif350return NodeRecord(ref,box_o);351}352private:353UserGeometry* mesh;354BVHBuilderMorton::BuildPrim* morton;355unsigned int geomID_ = std::numeric_limits<unsigned int>::max();356};357358template<int N>359struct CreateMortonLeaf<N,InstancePrimitive>360{361typedef BVHN<N> BVH;362typedef typename BVH::NodeRef NodeRef;363typedef typename BVH::NodeRecord NodeRecord;364365__forceinline CreateMortonLeaf (Instance* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)366: mesh(mesh), morton(morton), geomID_(geomID) {}367368__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)369{370vfloat4 lower(pos_inf);371vfloat4 upper(neg_inf);372size_t items = current.size();373size_t start = current.begin();374assert(items <= 1);375376/* allocate leaf node */377InstancePrimitive* accel = (InstancePrimitive*) alloc.malloc1(items*sizeof(InstancePrimitive),BVH::byteAlignment);378NodeRef ref = BVH::encodeLeaf((char*)accel,items);379const Instance* instance = this->mesh;380381BBox3fa bounds = empty;382for (size_t i=0; i<items; i++)383{384const unsigned int primID = morton[start+i].index;385bounds.extend(instance->bounds(primID));386new (&accel[i]) InstancePrimitive(instance, geomID_);387}388389BBox3fx box_o = (BBox3fx&)bounds;390#if ROTATE_TREE391if (N == 4)392box_o.lower.a = current.size();393#endif394return NodeRecord(ref,box_o);395}396private:397Instance* mesh;398BVHBuilderMorton::BuildPrim* morton;399unsigned int geomID_ = std::numeric_limits<unsigned int>::max();400};401402template<int N>403struct CreateMortonLeaf<N,InstanceArrayPrimitive>404{405typedef BVHN<N> BVH;406typedef typename BVH::NodeRef NodeRef;407typedef typename BVH::NodeRecord NodeRecord;408409__forceinline CreateMortonLeaf (InstanceArray* mesh, unsigned int geomID, BVHBuilderMorton::BuildPrim* morton)410: mesh(mesh), morton(morton), geomID_(geomID) {}411412__noinline NodeRecord operator() (const range<unsigned>& current, const FastAllocator::CachedAllocator& alloc)413{414vfloat4 lower(pos_inf);415vfloat4 upper(neg_inf);416size_t items = current.size();417size_t start = current.begin();418assert(items <= 1);419420/* allocate leaf node */421InstanceArrayPrimitive* accel = (InstanceArrayPrimitive*) alloc.malloc1(items*sizeof(InstanceArrayPrimitive),BVH::byteAlignment);422NodeRef ref = BVH::encodeLeaf((char*)accel,items);423const InstanceArray* instance = this->mesh;424425BBox3fa bounds = empty;426for (size_t i=0; i<items; i++)427{428const unsigned int primID = morton[start+i].index;429bounds.extend(instance->bounds(primID));430new (&accel[i]) InstanceArrayPrimitive(geomID_, primID);431}432433BBox3fx box_o = (BBox3fx&)bounds;434#if ROTATE_TREE435if (N == 4)436box_o.lower.a = current.size();437#endif438return NodeRecord(ref,box_o);439}440private:441InstanceArray* mesh;442BVHBuilderMorton::BuildPrim* morton;443unsigned int geomID_ = std::numeric_limits<unsigned int>::max();444};445446template<typename Mesh>447struct CalculateMeshBounds448{449__forceinline CalculateMeshBounds (Mesh* mesh)450: mesh(mesh) {}451452__forceinline const BBox3fa operator() (const BVHBuilderMorton::BuildPrim& morton) {453return mesh->bounds(morton.index);454}455456private:457Mesh* mesh;458};459460template<int N, typename Mesh, typename Primitive>461class BVHNMeshBuilderMorton : public Builder462{463typedef BVHN<N> BVH;464typedef typename BVH::AABBNode AABBNode;465typedef typename BVH::NodeRef NodeRef;466typedef typename BVH::NodeRecord NodeRecord;467468public:469470BVHNMeshBuilderMorton (BVH* bvh, Mesh* mesh, unsigned int geomID, const size_t minLeafSize, const size_t maxLeafSize, const size_t singleThreadThreshold = DEFAULT_SINGLE_THREAD_THRESHOLD)471: bvh(bvh), mesh(mesh), morton(bvh->device,0), settings(N,BVH::maxBuildDepth,minLeafSize,min(maxLeafSize,Primitive::max_size()*BVH::maxLeafBlocks),singleThreadThreshold), geomID_(geomID) {}472473/* build function */474void build()475{476/* we reset the allocator when the mesh size changed */477if (mesh->numPrimitives != numPreviousPrimitives) {478bvh->alloc.clear();479morton.clear();480}481size_t numPrimitives = mesh->size();482numPreviousPrimitives = numPrimitives;483484/* skip build for empty scene */485if (numPrimitives == 0) {486bvh->set(BVH::emptyNode,empty,0);487return;488}489490/* preallocate arrays */491morton.resize(numPrimitives);492size_t bytesEstimated = numPrimitives*sizeof(AABBNode)/(4*N) + size_t(1.2f*Primitive::blocks(numPrimitives)*sizeof(Primitive));493size_t bytesMortonCodes = numPrimitives*sizeof(BVHBuilderMorton::BuildPrim);494bytesEstimated = max(bytesEstimated,bytesMortonCodes); // the first allocation block is reused to sort the morton codes495bvh->alloc.init(bytesMortonCodes,bytesMortonCodes,bytesEstimated);496497/* create morton code array */498BVHBuilderMorton::BuildPrim* dest = (BVHBuilderMorton::BuildPrim*) bvh->alloc.specialAlloc(bytesMortonCodes);499size_t numPrimitivesGen = createMortonCodeArray<Mesh>(mesh,morton,bvh->scene->progressInterface);500501/* create BVH */502SetBVHNBounds<N> setBounds(bvh);503CreateMortonLeaf<N,Primitive> createLeaf(mesh,geomID_,morton.data());504CalculateMeshBounds<Mesh> calculateBounds(mesh);505auto root = BVHBuilderMorton::build<NodeRecord>(506typename BVH::CreateAlloc(bvh),507typename BVH::AABBNode::Create(),508setBounds,createLeaf,calculateBounds,bvh->scene->progressInterface,509morton.data(),dest,numPrimitivesGen,settings);510511bvh->set(root.ref,LBBox3fa(root.bounds),numPrimitives);512513#if ROTATE_TREE514if (N == 4)515{516for (int i=0; i<ROTATE_TREE; i++)517BVHNRotate<N>::rotate(bvh->root);518bvh->clearBarrier(bvh->root);519}520#endif521522/* clear temporary data for static geometry */523if (bvh->scene->isStaticAccel()) {524morton.clear();525}526bvh->cleanup();527}528529void clear() {530morton.clear();531}532533private:534BVH* bvh;535Mesh* mesh;536mvector<BVHBuilderMorton::BuildPrim> morton;537BVHBuilderMorton::Settings settings;538unsigned int geomID_ = std::numeric_limits<unsigned int>::max();539unsigned int numPreviousPrimitives = 0;540};541542#if defined(EMBREE_GEOMETRY_TRIANGLE)543Builder* BVH4Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4> ((BVH4*)bvh,mesh,geomID,4,4); }544Builder* BVH4Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4v>((BVH4*)bvh,mesh,geomID,4,4); }545Builder* BVH4Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,TriangleMesh,Triangle4i>((BVH4*)bvh,mesh,geomID,4,4); }546#if defined(__AVX__)547Builder* BVH8Triangle4MeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4> ((BVH8*)bvh,mesh,geomID,4,4); }548Builder* BVH8Triangle4vMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4v>((BVH8*)bvh,mesh,geomID,4,4); }549Builder* BVH8Triangle4iMeshBuilderMortonGeneral (void* bvh, TriangleMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,TriangleMesh,Triangle4i>((BVH8*)bvh,mesh,geomID,4,4); }550#endif551#endif552553#if defined(EMBREE_GEOMETRY_QUAD)554Builder* BVH4Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<4,QuadMesh,Quad4v>((BVH4*)bvh,mesh,geomID,4,4); }555#if defined(__AVX__)556Builder* BVH8Quad4vMeshBuilderMortonGeneral (void* bvh, QuadMesh* mesh, unsigned int geomID, size_t mode) { return new class BVHNMeshBuilderMorton<8,QuadMesh,Quad4v>((BVH8*)bvh,mesh,geomID,4,4); }557#endif558#endif559560#if defined(EMBREE_GEOMETRY_USER)561Builder* 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); }562#if defined(__AVX__)563Builder* 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); }564#endif565#endif566567#if defined(EMBREE_GEOMETRY_INSTANCE)568Builder* 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); }569#if defined(__AVX__)570Builder* 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); }571#endif572#endif573574#if defined(EMBREE_GEOMETRY_INSTANCE_ARRAY)575Builder* 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); }576#if defined(__AVX__)577Builder* 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); }578#endif579#endif580581}582}583584585