rendering-in-cgi/Framework/external/embree/kernels/bvh/bvh_builder_hair.cpp
2024-04-23 10:14:24 +02:00

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