EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Attributes | Friends | List of all members
EBGeometry::Tape< T, UserPrimitives > Class Template Reference

A composed object compiled into a pool: a trivially copyable handle that evaluates the object's signed distance (or implicit function value) on the host or on a device. More...

#include <EBGeometry_Tape.hpp>

Inheritance diagram for EBGeometry::Tape< T, UserPrimitives >:
Inheritance graph
[legend]
Collaboration diagram for EBGeometry::Tape< T, UserPrimitives >:
Collaboration graph
[legend]

Classes

struct  Layout
 The tape's arrays as offsets into its pool, with no location (see PoolHandle). More...
 

Public Types

using Features = TapeDetail::FeaturesOf< UserPrimitives... >
 The features the tape compiles (see TapeFeature): its template arguments derived from TapeFeature::Tag.
 
using BV = BoundingVolumes::AABBT< T >
 Bounding box type.
 
using Primitives = TapeDetail::Primitives< T, UserPrimitives... >
 The primitive types: the built-in ones, then UserPrimitives.
 
using UnionRoot = BVH::PackedBVH< T, uint32_t, BranchingRatio >
 The BVH type over union operands.
 

Public Member Functions

 Tape ()=delete
 No empty tape.
 
 Tape (Pool &a_pool, const Expr< T > &a_expr, const TapeOptions &a_options=TapeOptions())
 Compile an expression into a pool.
 
 Tape (const Layout &a_layout, const PoolLocation &a_location) noexcept
 Rebuild a handle from a stored layout and the location of the pool that holds it.
 
T signedDistance (const Vec3T< T > &a_point) const noexcept
 The object's value at a point: negative inside, positive outside, zero on the surface.
 
PrimitiveRef< T > closestPrimitive (const Vec3T< T > &a_point) const noexcept
 The deciding leaf at a point: the primitive whose surface the value comes from there (see PrimitiveRef), with the point in its own frame.
 
HitT< T > firstHit (const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options=RayOptions< T >()) const noexcept
 The first crossing of the object's surface along a ray, entering or leaving.
 
HitT< T > firstHit (const Vec3T< T > &a_from, const Vec3T< T > &a_to, T a_tMin=T(0), const RayOptions< T > &a_options=RayOptions< T >()) const noexcept
 The first crossing of the object's surface on the segment from a_from to a_to.
 
HitStatus intersects (const RayT< T > &a_ray, T a_tMin, T a_tMax, const RayOptions< T > &a_options=RayOptions< T >()) const noexcept
 Whether a ray crosses the object's surface in [a_tMin, a_tMax].
 
HitStatus intersects (const Vec3T< T > &a_from, const Vec3T< T > &a_to, T a_tMin=T(0), const RayOptions< T > &a_options=RayOptions< T >()) const noexcept
 Whether the segment from a_from to a_to crosses the object's surface.
 
template<class P >
bool isPrimitive (const PrimitiveRef< T > &a_ref) const noexcept
 Whether a reference's leaf is a primitive of type P.
 
template<class P >
P primitive (const PrimitiveRef< T > &a_ref) const noexcept
 The primitive a reference names, by value: the shape itself, or for a pool-resident type (a mesh SDF, a BVH union, a tape) its handle, rebuilt with the tape's location, so that it resolves against the same pool (or mirror) the tape does.
 
template<class F >
void visitPrimitive (const PrimitiveRef< T > &a_ref, F &&a_f) const noexcept
 Call a function with the primitive a reference names, as primitive.
 
BV computeBoundingVolume () const noexcept
 A box enclosing the object.
 
DistanceQuality getDistanceQuality () const noexcept
 How far signedDistance() can be trusted as a distance.
 
uint32_t getNumPrograms () const noexcept
 Number of sub-programs (1 plus one per Blur, Mollify, FiniteRepetition and BVH union operand).
 
uint32_t getNumClauses () const noexcept
 Number of clauses over all sub-programs (the ray programs' not counted).
 
uint32_t getNumBVHUnions () const noexcept
 Number of unions evaluated with a BVH.
 
uint32_t getCallDepth () const noexcept
 How deep sub-program calls nest (0 if the tape has no Blur, Mollify, FiniteRepetition or BVH union).
 
const Layout & layout () const noexcept
 The tape's arrays, with no location: what an outer pool-resident object stores.
 
Tape rebasedView (const Pool &a_pool) const noexcept
 A view of this tape resolving against another pool of its mirror chain.
 
Tape deepCopy (Pool &a_dstPool) const
 Copy the tape, and every pool-resident primitive and BVH it holds, into another pool.
 
- Public Member Functions inherited from EBGeometry::PoolHandle
PoolLocation location () const noexcept
 Where this handle's arrays live.
 
bool isAttachedTo (const Pool &a_pool) const noexcept
 Check whether this handle's arrays were reserved from a_pool.
 

Static Public Attributes

template<class F >
static constexpr bool hasFeature = TapeDetail::IndexOf<F, Features>::value < Features::size
 Whether the tape compiles feature F (see TapeFeature).
 
static constexpr size_t BranchingRatio = 4
 Branching factor of the BVHs over union operands.
 
static constexpr unsigned MaxCallDepth = 4
 How deep Blur, Mollify, FiniteRepetition and BVH unions may nest.
 
static constexpr uint32_t ValueStackSize = 16
 Values a sub-program may hold at once.
 
static constexpr uint32_t PointStackSize = 8
 Points a sub-program may hold at once (its input point included).
 
static constexpr uint32_t RayStackSize = 4
 Span lists a ray program may hold at once; a subtree that would need more is marched.
 

Friends

struct RayForm< Tape >
 Tape's ray form follows the ray programs.
 

Additional Inherited Members

- Protected Member Functions inherited from EBGeometry::PoolHandle
 PoolHandle () noexcept=default
 An unset location; the first reservation attaches it.
 
 PoolHandle (const PoolLocation &a_location) noexcept
 Adopt a location, as a handle rebuilt from a stored layout does.
 
 PoolHandle (const PoolHandle &) noexcept=default
 Copy a handle, as a derived handle's copy does.
 
 PoolHandle (PoolHandle &&) noexcept=default
 Move a handle; the same as a copy.
 
PoolHandle & operator= (const PoolHandle &) noexcept=default
 Copy-assign a handle, as a derived handle's assignment does.
 
PoolHandle & operator= (PoolHandle &&) noexcept=default
 Move-assign a handle; the same as a copy.
 
 ~PoolHandle () noexcept=default
 Destructor; protected, since a PoolHandle exists only as the base of a handle.
 
void * base () noexcept
 The base address this handle's offsets resolve against; see PoolLocation::base().
 
const void * base () const noexcept
 The base address this handle's offsets resolve against, for read-only access.
 
void attach (const Pool &a_pool, const char *a_who) noexcept
 Follow a_pool, as the first reservation does; see PoolLocation::attach().
 
PoolLocation rebasedLocation (const Pool &a_pool, uint64_t a_endByte, const char *a_who) const noexcept
 The location of this handle's arrays in another pool of its mirror chain; see PoolLocation::rebasedOnto().
 
void setLocation (const PoolLocation &a_location) noexcept
 Replace the location, for a view or a copy made by a derived handle.
 

Detailed Description

template<class T, class... UserPrimitives>
class EBGeometry::Tape< T, UserPrimitives >

A composed object compiled into a pool: a trivially copyable handle that evaluates the object's signed distance (or implicit function value) on the host or on a device.

Build one from an Expr:

const auto shape = Difference(Union(SphereSDF<T>(c, r), Translate(BoxSDF<T>(lo, hi), shift)), mesh);
const Tape<T> tape(pool, shape);
const T d = tape.signedDistance(p);
Signed distance field for an axis-aligned box (AABB).
Definition EBGeometry_AnalyticDistanceFunctions.hpp:351
Growable bump arena over a MemoryResource.
Definition EBGeometry_Pool.hpp:183
Signed distance field for a sphere.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:199
A composed object compiled into a pool: a trivially copyable handle that evaluates the object's signe...
Definition EBGeometry_Tape.hpp:683
Expr< ExprPrecision< A > > Union(const A &a_first, const B &a_second)
Union of two objects: the minimum of their values.
Expr< ExprPrecision< A > > Difference(const A &a_first, const B &a_second)
Difference A \ B: max(A, -B), inside A and outside B.
HostMemoryResource & hostMemoryResource() noexcept
Process-wide default host memory resource.
Expr< ExprPrecision< A > > Translate(const A &a_operand, const Vec3T< ExprPrecision< A > > &a_shift)
Translate an object by a shift.

The analytic shapes and the mesh SDFs (FlatMeshSDF, and MeshSDF and TriMeshSDF with the default branching factor and width) are built-in primitive types; any other shape type, such as a BVHUnion, a MeshSDF with another branching factor, another Tape or a type of your own, is listed in UserPrimitives. A pool-resident primitive must live in the tape's pool. The pool must outlive the tape and every copy and view of it (see PoolHandle).

The compiler works out each sub-expression's bounding box and distance quality (see Expr). A union or smooth union of many objects is evaluated with a BVH over their boxes, pruned as BVHUnion is, unless an object is not a distance. With exact distances the value is the plain minimum; with operands that are only bounds (DistanceQuality::Bound) pruning can skip an operand whose value is below its box's distance, so the value can be larger than the plain minimum, but it keeps the sign and is still a bound. Blur, Mollify, FiniteRepetition and BVH unions evaluate a sub-program several times; they nest at most MaxCallDepth deep, and a sub-program needs at most ValueStackSize values and PointStackSize points at once; the constructor rejects an expression that needs more.

Optional features (see TapeFeature) are listed among the template arguments, before the user primitive types by convention: Tape<T, TapeFeature::ExactOffsets, MyUnion>. A tape compiles only the features it lists, and without one computes the same object by the general path.

Template Parameters
TFloating-point precision.
UserPrimitivesAdditional primitive types (each a shape of precision T), and features (see TapeFeature).

Constructor & Destructor Documentation

◆ Tape() [1/2]

template<class T , class... UserPrimitives>
EBGeometry::Tape< T, UserPrimitives >::Tape ( Pool &  a_pool,
const Expr< T > &  a_expr,
const TapeOptions &  a_options = TapeOptions() 
)

Compile an expression into a pool.

Parameters
[in,out]a_poolPool to compile into; pool-resident primitives must live in it too. Must outlive this object and every copy of it.
[in]a_exprExpression.
[in]a_optionsCompile settings.

◆ Tape() [2/2]

template<class T , class... UserPrimitives>
EBGeometry::Tape< T, UserPrimitives >::Tape ( const Layout &  a_layout,
const PoolLocation &  a_location 
)
inlinenoexcept

Rebuild a handle from a stored layout and the location of the pool that holds it.

How an outer pool-resident object evaluates a Tape it stores as a layout. a_location must belong to the pool the layout was reserved from, or to a mirror of it; nothing is checked, since a device has no pool to check against.

Parameters
[in]a_layoutThe arrays.
[in]a_locationWhere they live.

Member Function Documentation

◆ closestPrimitive()

template<class T , class... UserPrimitives>
PrimitiveRef< T > EBGeometry::Tape< T, UserPrimitives >::closestPrimitive ( const Vec3T< T > &  a_point) const
inlinenoexcept

The deciding leaf at a point: the primitive whose surface the value comes from there (see PrimitiveRef), with the point in its own frame.

Evaluates the tape as signedDistance() does, carrying with each value the leaf it comes from. The leaves are numbered in expression order, depth first, each occurrence counted. A primitive that is itself a composition (a fused one, a tape, a BVH union) is one leaf: the tape is the scene, its leaves the parts. Callable on a device, like signedDistance().

Parameters
[in]a_pointQuery point.
Returns
The leaf, its type and index in the tape, and the point in its frame.

◆ computeBoundingVolume()

template<class T , class... UserPrimitives>
BV EBGeometry::Tape< T, UserPrimitives >::computeBoundingVolume ( ) const
inlinenoexcept

A box enclosing the object.

Returns
The box (unbounded along directions where the object is).

◆ deepCopy()

template<class T , class... UserPrimitives>
Tape EBGeometry::Tape< T, UserPrimitives >::deepCopy ( Pool &  a_dstPool) const
inline

Copy the tape, and every pool-resident primitive and BVH it holds, into another pool.

Parameters
[in,out]a_dstPoolPool to copy into.
Returns
The copy, resolving against a_dstPool.

◆ firstHit() [1/2]

template<class T , class... UserPrimitives>
HitT< T > EBGeometry::Tape< T, UserPrimitives >::firstHit ( const RayT< T > &  a_ray,
T  a_tMin,
T  a_tMax,
const RayOptions< T > &  a_options = RayOptions< T >() 
) const
inlinenoexcept

The first crossing of the object's surface along a ray, entering or leaving.

The tape is traced along its ray program: exactly through its unions, intersections, complements and affine maps of primitives with ray forms, and marched in the parts that have anything else (see EBGeometry_Ray.hpp). HitT::m_primitive is the leaf crossed (see closestPrimitive()). The same as the free function firstHit(). Callable on a device.

Parameters
[in]a_rayThe ray, with a unit direction.
[in]a_tMinStart of the interval.
[in]a_tMaxEnd of the interval.
[in]a_optionsHow to march.
Returns
The crossing, a miss, or an unresolved query.

◆ firstHit() [2/2]

template<class T , class... UserPrimitives>
HitT< T > EBGeometry::Tape< T, UserPrimitives >::firstHit ( const Vec3T< T > &  a_from,
const Vec3T< T > &  a_to,
T  a_tMin = T(0),
const RayOptions< T > &  a_options = RayOptions< T >() 
) const
inlinenoexcept

The first crossing of the object's surface on the segment from a_from to a_to.

HitT::m_t is the distance from a_from. The same as the free function firstHit(). Callable on a device.

Parameters
[in]a_fromStart of the segment.
[in]a_toEnd of the segment.
[in]a_tMinDistance from a_from where the search starts.
[in]a_optionsHow to march.
Returns
The crossing, a miss, or an unresolved query.

◆ getCallDepth()

template<class T , class... UserPrimitives>
uint32_t EBGeometry::Tape< T, UserPrimitives >::getCallDepth ( ) const
inlinenoexcept

How deep sub-program calls nest (0 if the tape has no Blur, Mollify, FiniteRepetition or BVH union).

Returns
The depth.

◆ getDistanceQuality()

template<class T , class... UserPrimitives>
DistanceQuality EBGeometry::Tape< T, UserPrimitives >::getDistanceQuality ( ) const
inlinenoexcept

How far signedDistance() can be trusted as a distance.

A runtime value, unlike a shape's static distanceQuality; a Tape used as another object's primitive therefore counts as DistanceQuality::Bound there.

Returns
The quality.

◆ getNumBVHUnions()

template<class T , class... UserPrimitives>
uint32_t EBGeometry::Tape< T, UserPrimitives >::getNumBVHUnions ( ) const
inlinenoexcept

Number of unions evaluated with a BVH.

Returns
The count.

◆ getNumClauses()

template<class T , class... UserPrimitives>
uint32_t EBGeometry::Tape< T, UserPrimitives >::getNumClauses ( ) const
inlinenoexcept

Number of clauses over all sub-programs (the ray programs' not counted).

Returns
The count.

◆ getNumPrograms()

template<class T , class... UserPrimitives>
uint32_t EBGeometry::Tape< T, UserPrimitives >::getNumPrograms ( ) const
inlinenoexcept

Number of sub-programs (1 plus one per Blur, Mollify, FiniteRepetition and BVH union operand).

Returns
The count.

◆ intersects() [1/2]

template<class T , class... UserPrimitives>
HitStatus EBGeometry::Tape< T, UserPrimitives >::intersects ( const RayT< T > &  a_ray,
T  a_tMin,
T  a_tMax,
const RayOptions< T > &  a_options = RayOptions< T >() 
) const
inlinenoexcept

Whether a ray crosses the object's surface in [a_tMin, a_tMax].

The same as the free function intersects(). Callable on a device.

Parameters
[in]a_rayThe ray, with a unit direction.
[in]a_tMinStart of the interval.
[in]a_tMaxEnd of the interval.
[in]a_optionsHow to march.
Returns
Hit, Miss, or Unresolved.

◆ intersects() [2/2]

template<class T , class... UserPrimitives>
HitStatus EBGeometry::Tape< T, UserPrimitives >::intersects ( const Vec3T< T > &  a_from,
const Vec3T< T > &  a_to,
T  a_tMin = T(0),
const RayOptions< T > &  a_options = RayOptions< T >() 
) const
inlinenoexcept

Whether the segment from a_from to a_to crosses the object's surface.

The same as the free function intersects(). Callable on a device.

Parameters
[in]a_fromStart of the segment.
[in]a_toEnd of the segment.
[in]a_tMinDistance from a_from where the search starts.
[in]a_optionsHow to march.
Returns
Hit, Miss, or Unresolved.

◆ isPrimitive()

template<class T , class... UserPrimitives>
template<class P >
bool EBGeometry::Tape< T, UserPrimitives >::isPrimitive ( const PrimitiveRef< T > &  a_ref) const
inlinenoexcept

Whether a reference's leaf is a primitive of type P.

Template Parameters
PPrimitive type (one of the tape's types).
Parameters
[in]a_refReference from closestPrimitive().
Returns
True if it is.

◆ layout()

template<class T , class... UserPrimitives>
const Layout & EBGeometry::Tape< T, UserPrimitives >::layout ( ) const
inlinenoexcept

The tape's arrays, with no location: what an outer pool-resident object stores.

Returns
The layout.

◆ primitive()

template<class T , class... UserPrimitives>
template<class P >
P EBGeometry::Tape< T, UserPrimitives >::primitive ( const PrimitiveRef< T > &  a_ref) const
inlinenoexcept

The primitive a reference names, by value: the shape itself, or for a pool-resident type (a mesh SDF, a BVH union, a tape) its handle, rebuilt with the tape's location, so that it resolves against the same pool (or mirror) the tape does.

Template Parameters
PPrimitive type; the leaf must be one (isPrimitive<P>()).
Parameters
[in]a_refReference from closestPrimitive().
Returns
The primitive.

◆ rebasedView()

template<class T , class... UserPrimitives>
Tape EBGeometry::Tape< T, UserPrimitives >::rebasedView ( const Pool &  a_pool) const
inlinenoexcept

A view of this tape resolving against another pool of its mirror chain.

The pool must be this tape's own pool or a mirror of it (see PoolLocation::rebasedOnto()). Pool-resident primitives follow the view, since they are stored as layouts.

Parameters
[in]a_poolPool to resolve against.
Returns
The view.

◆ signedDistance()

template<class T , class... UserPrimitives>
T EBGeometry::Tape< T, UserPrimitives >::signedDistance ( const Vec3T< T > &  a_point) const
inlinenoexcept

The object's value at a point: negative inside, positive outside, zero on the surface.

The sign is always meaningful. The magnitude is what getDistanceQuality() says: the distance to the surface (Exact), at most that distance (Bound), or nothing (NotADistance). The name is the same for every shape whatever its quality; see isShape. Callable on a device through a view onto a mirrored pool (rebasedView()).

Parameters
[in]a_pointQuery point.
Returns
The value.

◆ visitPrimitive()

template<class T , class... UserPrimitives>
template<class F >
void EBGeometry::Tape< T, UserPrimitives >::visitPrimitive ( const PrimitiveRef< T > &  a_ref,
F &&  a_f 
) const
inlinenoexcept

Call a function with the primitive a reference names, as primitive.

() returns it, whatever its type.

Template Parameters
FCallable taking any of the tape's primitive types (a generic lambda in host code). In a CUDA or HIP translation unit, pass a functor whose call operator is EBGEOMETRY_HOST_DEVICE: the device compiler treats a lambda's call operator as a host function here.
Parameters
[in]a_refReference from closestPrimitive().
[in]a_fFunction.

Member Data Documentation

◆ hasFeature

template<class T , class... UserPrimitives>
template<class F >
constexpr bool EBGeometry::Tape< T, UserPrimitives >::hasFeature = TapeDetail::IndexOf<F, Features>::value < Features::size
staticconstexpr

Whether the tape compiles feature F (see TapeFeature).

Template Parameters
FFeature.

The documentation for this class was generated from the following file: