131 lines
5 KiB
C++
131 lines
5 KiB
C++
// Copyright 2009-2021 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#include "../builders/bvh_builder_hair.h"
|
|
#include "../builders/primrefgen.h"
|
|
|
|
#include "../geometry/pointi.h"
|
|
#include "../geometry/linei.h"
|
|
#include "../geometry/curveNi.h"
|
|
#include "../geometry/curveNv.h"
|
|
|
|
#if defined(EMBREE_GEOMETRY_CURVE) || defined(EMBREE_GEOMETRY_POINT)
|
|
|
|
namespace embree
|
|
{
|
|
namespace isa
|
|
{
|
|
template<int N, typename CurvePrimitive, typename LinePrimitive, typename PointPrimitive>
|
|
struct BVHNHairBuilderSAH : public Builder
|
|
{
|
|
typedef BVHN<N> BVH;
|
|
typedef typename BVH::NodeRef NodeRef;
|
|
|
|
BVH* bvh;
|
|
Scene* scene;
|
|
mvector<PrimRef> prims;
|
|
BVHBuilderHair::Settings settings;
|
|
|
|
BVHNHairBuilderSAH (BVH* bvh, Scene* scene)
|
|
: bvh(bvh), scene(scene), prims(scene->device,0) {}
|
|
|
|
void build()
|
|
{
|
|
/* if we use the primrefarray for allocations we have to take it back from the BVH */
|
|
if (settings.finished_range_threshold != size_t(inf))
|
|
bvh->alloc.unshare(prims);
|
|
|
|
/* fast path for empty BVH */
|
|
const size_t numPrimitives = scene->getNumPrimitives(Geometry::MTY_CURVES,false);
|
|
if (numPrimitives == 0) {
|
|
bvh->clear();
|
|
prims.clear();
|
|
return;
|
|
}
|
|
|
|
double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "HairBuilderSAH");
|
|
|
|
/* create primref array */
|
|
prims.resize(numPrimitives);
|
|
const PrimInfo pinfo = createPrimRefArray(scene,Geometry::MTY_CURVES,false,numPrimitives,prims,scene->progressInterface);
|
|
|
|
/* estimate acceleration structure size */
|
|
const size_t node_bytes = pinfo.size()*sizeof(typename BVH::OBBNode)/(4*N);
|
|
const size_t leaf_bytes = CurvePrimitive::bytes(pinfo.size());
|
|
bvh->alloc.init_estimate(node_bytes+leaf_bytes);
|
|
|
|
/* builder settings */
|
|
settings.branchingFactor = N;
|
|
settings.maxDepth = BVH::maxBuildDepthLeaf;
|
|
settings.logBlockSize = bsf(CurvePrimitive::max_size());
|
|
settings.minLeafSize = CurvePrimitive::max_size();
|
|
settings.maxLeafSize = CurvePrimitive::max_size();
|
|
settings.finished_range_threshold = numPrimitives/1000;
|
|
if (settings.finished_range_threshold < 1000)
|
|
settings.finished_range_threshold = inf;
|
|
|
|
/* creates a leaf node */
|
|
auto createLeaf = [&] (const PrimRef* prims, const range<size_t>& set, const FastAllocator::CachedAllocator& alloc) -> NodeRef {
|
|
|
|
if (set.size() == 0)
|
|
return BVH::emptyNode;
|
|
|
|
const unsigned int geomID0 = prims[set.begin()].geomID();
|
|
if (scene->get(geomID0)->getTypeMask() & Geometry::MTY_POINTS)
|
|
return PointPrimitive::createLeaf(bvh,prims,set,alloc);
|
|
else if (scene->get(geomID0)->getCurveBasis() == Geometry::GTY_BASIS_LINEAR)
|
|
return LinePrimitive::createLeaf(bvh,prims,set,alloc);
|
|
else
|
|
return CurvePrimitive::createLeaf(bvh,prims,set,alloc);
|
|
};
|
|
|
|
auto reportFinishedRange = [&] (const range<size_t>& range) -> void
|
|
{
|
|
PrimRef* begin = prims.data()+range.begin();
|
|
PrimRef* end = prims.data()+range.end(); // FIXME: extended end for spatial split builder!!!!!
|
|
size_t bytes = (size_t)end - (size_t)begin;
|
|
bvh->alloc.addBlock(begin,bytes);
|
|
};
|
|
|
|
/* build hierarchy */
|
|
typename BVH::NodeRef root = BVHBuilderHair::build<NodeRef>
|
|
(typename BVH::CreateAlloc(bvh),
|
|
typename BVH::AABBNode::Create(),
|
|
typename BVH::AABBNode::Set(),
|
|
typename BVH::OBBNode::Create(),
|
|
typename BVH::OBBNode::Set(),
|
|
createLeaf,scene->progressInterface,
|
|
reportFinishedRange,
|
|
scene,prims.data(),pinfo,settings);
|
|
|
|
bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size());
|
|
|
|
/* if we allocated using the primrefarray we have to keep it alive */
|
|
if (settings.finished_range_threshold != size_t(inf))
|
|
bvh->alloc.share(prims);
|
|
|
|
/* clear temporary data for static geometry */
|
|
if (scene->isStaticAccel()) {
|
|
prims.clear();
|
|
}
|
|
bvh->cleanup();
|
|
bvh->postBuild(t0);
|
|
}
|
|
|
|
void clear() {
|
|
prims.clear();
|
|
}
|
|
};
|
|
|
|
/*! entry functions for the builder */
|
|
Builder* BVH4Curve4vBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve4v,Line4i,Point4i>((BVH4*)bvh,scene); }
|
|
Builder* BVH4Curve4iBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve4i,Line4i,Point4i>((BVH4*)bvh,scene); }
|
|
|
|
#if defined(__AVX__)
|
|
Builder* BVH8Curve8vBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<8,Curve8v,Line8i,Point8i>((BVH8*)bvh,scene); }
|
|
Builder* BVH4Curve8iBuilder_OBB_New (void* bvh, Scene* scene, size_t mode) { return new BVHNHairBuilderSAH<4,Curve8i,Line8i,Point8i>((BVH4*)bvh,scene); }
|
|
#endif
|
|
|
|
}
|
|
}
|
|
#endif
|