From 2fae6878e1d959acfc9ec6655f658cc4bc07e01f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Sun, 3 Nov 2024 00:42:47 +0000 Subject: [PATCH] build based on c4184e0 --- dev/.documenter-siteinfo.json | 2 +- dev/{static => assets}/bunny.png | Bin dev/assets/logo.png | Bin 0 -> 139622 bytes dev/bounding_volumes/index.html | 12 ++++++------ dev/implicit_tree/index.html | 4 ++-- dev/index.html | 10 +++++----- dev/morton/index.html | 12 ++++++------ dev/objects.inv | Bin 658 -> 643 bytes dev/search_index.js | 2 +- dev/utilities/index.html | 31 +++---------------------------- 10 files changed, 24 insertions(+), 49 deletions(-) rename dev/{static => assets}/bunny.png (100%) create mode 100644 dev/assets/logo.png diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 68f9d70..ed4edc9 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-10-30T14:09:43","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-03T00:42:41","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/static/bunny.png b/dev/assets/bunny.png similarity index 100% rename from dev/static/bunny.png rename to dev/assets/bunny.png diff --git a/dev/assets/logo.png b/dev/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2207d6e7947d252c4909d30de4631a9297bc8efe GIT binary patch literal 139622 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�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 -Bounding Volumes · ImplicitBVH.jl

diff --git a/dev/implicit_tree/index.html b/dev/implicit_tree/index.html index 6f72b56..5c0756e 100644 --- a/dev/implicit_tree/index.html +++ b/dev/implicit_tree/index.html @@ -1,5 +1,5 @@ -Implicit Binary Tree · ImplicitBVH.jl

Implicit Binary Tree

ImplicitBVH.ImplicitTreeType
struct ImplicitTree{T<:Integer}

Implicit binary tree for num_leaves elements, where nodes are labelled according to a breadth-first search.

Methods

ImplicitTree(num_leaves::Integer)
+Implicit Binary Tree · ImplicitBVH.jl

Implicit Binary Tree

ImplicitBVH.ImplicitTreeType
struct ImplicitTree{T<:Integer}

Implicit binary tree for num_leaves elements, where nodes are labelled according to a breadth-first search.

Methods

ImplicitTree(num_leaves::Integer)
 ImplicitTree{T}(num_leaves::Integer)

Fields

  • levels::Integer: Number of levels in the tree.

  • real_leaves::Integer: Number of real leaves - i.e. the elements from which the tree was constructed.

  • real_nodes::Integer: Total number of real nodes in tree.

  • virtual_leaves::Integer: Number of virtual leaves needed at the bottom level to have a perfect binary tree.

  • virtual_nodes::Integer: Total number of virtual nodes in tree needed for a complete binary tree.

Examples

julia> using ImplicitBVH
 
 # Given 5 geometric elements (e.g. bounding boxes) we construct the following implicit tree
@@ -32,4 +32,4 @@
 false
 
 julia> isvirtual(tree, 7)
-true
source
ImplicitBVH.memory_indexFunction
memory_index(tree::ImplicitTree, implicit_index::Integer)

Return actual memory index for a node at implicit index i in a perfect BFS-labelled tree.

source
ImplicitBVH.level_indicesFunction
level_indices(tree::ImplicitTree, level::Integer)

Return range Tuple{Int64, Int64} of memory indices of elements at level.

source
ImplicitBVH.isvirtualFunction
isvirtual(tree::ImplicitTree, implicit_index::Integer)

Check if given implicit_index corresponds to a virtual node.

source
+true
source
ImplicitBVH.memory_indexFunction
memory_index(tree::ImplicitTree, implicit_index::Integer)

Return actual memory index for a node at implicit index i in a perfect BFS-labelled tree.

source
ImplicitBVH.level_indicesFunction
level_indices(tree::ImplicitTree, level::Integer)

Return range Tuple{Int64, Int64} of memory indices of elements at level.

source
ImplicitBVH.isvirtualFunction
isvirtual(tree::ImplicitTree, implicit_index::Integer)

Check if given implicit_index corresponds to a virtual node.

source
diff --git a/dev/index.html b/dev/index.html index 5dd4b7d..ac3bf36 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,5 +1,5 @@ -ImplicitBVH.jl Documentation · ImplicitBVH.jl

ImplicitBVH.jl Documentation

BVH Construction & Traversal

ImplicitBVH.BVHType
struct BVH{I<:Integer, VN<:(AbstractVector), VL<:(AbstractVector), VM<:(AbstractVector), VO<:(AbstractVector)}

Implicit bounding volume hierarchy constructed from an iterable of some geometric primitives' (e.g. triangles in a mesh) bounding volumes forming the ImplicitTree leaves. The leaves and merged nodes above them can have different types - e.g. BSphere{Float64} for leaves merged into larger BBox{Float64}.

The initial geometric primitives are sorted according to their Morton-encoded coordinates; the unsigned integer type used for the Morton encoding can be chosen between Union{UInt16, UInt32, UInt64}.

Finally, the tree can be incompletely-built up to a given built_level and later start contact detection downwards from this level, e.g.:

Implicit tree from 5 bounding volumes - i.e. the real leaves
+ImplicitBVH.jl Documentation · ImplicitBVH.jl

ImplicitBVH.jl Documentation

BVH Construction & Traversal

ImplicitBVH.BVHType
struct BVH{I<:Integer, VN<:(AbstractVector), VL<:(AbstractVector), VM<:(AbstractVector), VO<:(AbstractVector)}

Implicit bounding volume hierarchy constructed from an iterable of some geometric primitives' (e.g. triangles in a mesh) bounding volumes forming the ImplicitTree leaves. The leaves and merged nodes above them can have different types - e.g. BSphere{Float64} for leaves merged into larger BBox{Float64}.

The initial geometric primitives are sorted according to their Morton-encoded coordinates; the unsigned integer type used for the Morton encoding can be chosen between Union{UInt16, UInt32, UInt64}.

Finally, the tree can be incompletely-built up to a given built_level and later start contact detection downwards from this level, e.g.:

Implicit tree from 5 bounding volumes - i.e. the real leaves
 
 Tree Level          Nodes & Leaves               Build Up    Traverse Down
     1                     1                         Ʌ              |
@@ -66,7 +66,7 @@
 # output
 traversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]

Build BVH up to level 2 and start traversing down from level 3, reusing the previous traversal cache:

bvh = BVH(bounding_spheres, BBox{Float32}, UInt32, 2)
 traversal = traverse(bvh, 3, traversal)

Update previous BVH bounding volumes' positions and rebuild BVH reusing previous memory:

new_positions = rand(3, 5)
-bvh_rebuilt = BVH(bvh, new_positions)
source
ImplicitBVH.traverseFunction
traverse(
     bvh::BVH,
     start_level::Int=default_start_level(bvh),
     cache::Union{Nothing, BVHTraversal}=nothing;
@@ -95,7 +95,7 @@
 ;
 
 # output
-traversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]
source
traverse(
+traversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]
source
traverse(
     bvh1::BVH,
     bvh2::BVH,
     start_level1::Int=default_start_level(bvh1),
@@ -130,5 +130,5 @@
 ;
 
 # output
-traversal.contacts = Tuple{Int32, Int32}[(1, 1), (2, 3)]
source
ImplicitBVH.BVHTraversalType
struct BVHTraversal{C1<:(AbstractVector), C2<:(AbstractVector)}

Collected BVH traversal contacts vector, some stats, plus the two buffers cache1 and cache2 which can be reused for future traversals to minimise memory allocations.

Fields

  • start_level1::Int: the level at which the single/pair-tree traversal started for the first BVH.
  • start_level2::Int: the level at which the pair-tree traversal started for the second BVH.
  • num_checks::Int: the total number of contact checks done.
  • num_contacts::Int: the number of contacts found.
  • contacts::view(cache1, 1:num_contacts): the contacting pairs found, as a view into cache1.
  • cache1::C1{IndexPair} <: AbstractVector: first BVH traversal buffer.
  • cache2::C2{IndexPair} <: AbstractVector: second BVH traversal buffer.
source
ImplicitBVH.default_start_levelFunction
default_start_level(bvh::BVH)::Int
-default_start_level(num_leaves::Integer)::Int

Compute the default start level when traversing a single BVH tree.

source

Index

+traversal.contacts = Tuple{Int32, Int32}[(1, 1), (2, 3)]
source
ImplicitBVH.BVHTraversalType
struct BVHTraversal{C1<:(AbstractVector), C2<:(AbstractVector)}

Collected BVH traversal contacts vector, some stats, plus the two buffers cache1 and cache2 which can be reused for future traversals to minimise memory allocations.

Fields

  • start_level1::Int: the level at which the single/pair-tree traversal started for the first BVH.
  • start_level2::Int: the level at which the pair-tree traversal started for the second BVH.
  • num_checks::Int: the total number of contact checks done.
  • num_contacts::Int: the number of contacts found.
  • contacts::view(cache1, 1:num_contacts): the contacting pairs found, as a view into cache1.
  • cache1::C1{IndexPair} <: AbstractVector: first BVH traversal buffer.
  • cache2::C2{IndexPair} <: AbstractVector: second BVH traversal buffer.
source
ImplicitBVH.default_start_levelFunction
default_start_level(bvh::BVH)::Int
+default_start_level(num_leaves::Integer)::Int

Compute the default start level when traversing a single BVH tree.

source
ImplicitBVH.IndexPairType
const IndexPair{I} = Tuple{I, I}

Alias for a tuple of two indices representing e.g. a contacting pair.

source

Index

diff --git a/dev/morton/index.html b/dev/morton/index.html index e7afa20..c7fafec 100644 --- a/dev/morton/index.html +++ b/dev/morton/index.html @@ -1,9 +1,9 @@ -Morton Encoding · ImplicitBVH.jl

Morton Encoding

ImplicitBVH.morton_encodeFunction
morton_encode(
+Morton Encoding · ImplicitBVH.jl

Morton Encoding

ImplicitBVH.morton_encode!Function
morton_encode!(
     mortons::AbstractVector{U},
     bounding_volumes,
     options=BVHOptions(),
@@ -15,10 +15,10 @@
     mins,
     maxs,
     options=BVHOptions(),
-) where {U <: MortonUnsigned}

Encode each bounding volume into vector of corresponding Morton codes such that they uniformly cover the maximum Morton range given an unsigned integer type U <: MortonUnsigned.

Warning

The dimension-wise exclusive mins and maxs must be correct; if any bounding volume center is equal to, or beyond mins / maxs, the results will be silently incorrect.

source
ImplicitBVH.morton_encode_singleFunction
morton_encode_single(centre, mins, maxs, U::MortonUnsignedType=UInt32)

Return Morton code for a single 3D position centre scaled uniformly between mins and maxs. Works transparently for SVector, Vector, etc. with eltype UInt16, UInt32 or UInt64.

source
ImplicitBVH.morton_scalingFunction
morton_scaling(::Type{UInt16}) = 2^5
+) where {U <: MortonUnsigned}

Encode each bounding volume into vector of corresponding Morton codes such that they uniformly cover the maximum Morton range given an unsigned integer type U <: MortonUnsigned.

Warning

The dimension-wise exclusive mins and maxs must be correct; if any bounding volume center is equal to, or beyond mins / maxs, the results will be silently incorrect.

source
ImplicitBVH.morton_encode_singleFunction
morton_encode_single(centre, mins, maxs, U::MortonUnsignedType=UInt32)

Return Morton code for a single 3D position centre scaled uniformly between mins and maxs. Works transparently for SVector, Vector, etc. with eltype UInt16, UInt32 or UInt64.

source
ImplicitBVH.morton_scalingFunction
morton_scaling(::Type{UInt16}) = 2^5
 morton_scaling(::Type{UInt32}) = 2^10
-morton_scaling(::Type{UInt64}) = 2^21

Exclusive maximum number possible to use for 3D Morton encoding for each type.

source
ImplicitBVH.morton_split3Function
morton_split3(v::UInt16)
+morton_scaling(::Type{UInt64}) = 2^21

Exclusive maximum number possible to use for 3D Morton encoding for each type.

source
ImplicitBVH.morton_split3Function
morton_split3(v::UInt16)
 morton_split3(v::UInt32)
-morton_split3(v::UInt64)

Shift a number's individual bits such that they have two zeros between them.

source
ImplicitBVH.relative_precisionFunction
relative_precision(::Type{Float16}) = 1e-2
+morton_split3(v::UInt64)

Shift a number's individual bits such that they have two zeros between them.

source
ImplicitBVH.relative_precisionFunction
relative_precision(::Type{Float16}) = 1e-2
 relative_precision(::Type{Float32}) = 1e-5
-relative_precision(::Type{Float64}) = 1e-14

Relative precision value for floating-point types.

source
+relative_precision(::Type{Float64}) = 1e-14

Relative precision value for floating-point types.

source
diff --git a/dev/objects.inv b/dev/objects.inv index baaff2b3ec78f1efc568165abd6895d3f99cd2e3..b4ecf279a72f2cef0bb2f09ace27a407084b9544 100644 GIT binary patch delta 523 zcmV+m0`&co1%m~UgMZ78+#nFV`zwg@xRKE&w>?ghRrat-qRh+{vAB1Z6$T5iHS_mr z8$ZDFvU5XCS9eucgVZ@3i1YbMZOzR6`(!$(&+5jR63V> z&uXJE>|*5fZbjBzgzQ2jlU;4*EkKM-E>;5vvX+|LBiUdyD}RjjM#rcSS&^r3^Fs^M zw96_lmGm;DHw0H?+aI%@A>BoK6n_SFR?+(pr<(p$V2|{n(xRErj0!D)41nxOIsr;? z4W^m_r&;O{O&m(`n10nx4AO7N!P}}OL%GiB#_}4h{Oa z;dcDLD&~-!nk%k@I>A-r`#ew%FT7HoInS+UtsN8OIe*{B)xYAc1%K*O?Q++S=hXr^RnC zaCqih?c`oV9;vz1YFd)P0reJqCR6;Q4gQ+KFJ>z6w*|Wxw*Fhbf`vt|dJjH4Y1Ts0 NmXpQ!2L#cy$qX`h24VmJ delta 538 zcmV+#0_FXK1(F4jgMZ16+b|5h`zus*xv9alw>i2CI)_20Xp*a;kvXZRvSdiIk^FsW z%Zp@Zv3oNpKJq<2nnLApB-Z8kx#oo45%N%!QgGqY{g02Yl6=*?DnL2rgjUJ3u2e46 zA*;2-unm#Zw+%_V2-*8cBD&g{GXNnrde{scNGcRFC$hz8Qh#XUv zP$4!s;1=2ZFn?@h*qSEZWZIh?XLOr@iPK%!MY}Kn#%-95v{Csg@7<{c()A9XTYgVW zm}^NAYLJ;g^Eh_K#Fx%)a%K!M)Jw^r5dahDD04zN)yII&?X@WYOPv~ma9l@E*jgA@ z;dcDLs>~uexl~*SwVcVu_hq0QURWhvW*svwYwegI&wu$ouKpEo4M_ZZYRF0hT-c`C zDj|LbZ!Ul?0^WbRn-l(7`lB<_y|UQ-cl&3Kh#Ss1Ka;6jv%D>{f1hyJqDcU=j8g9{ zM%?FxV?;vAq6Je%x3}KkhMltFpdb$zUTQThnZXf{%JD?|8Lon* czso;hU=!6TIDqqaAZsCU%ZYXW04xRDh1?|wl>h($ diff --git a/dev/search_index.js b/dev/search_index.js index d746d1a..419ba3f 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"morton/#Morton-Encoding","page":"Morton Encoding","title":"Morton Encoding","text":"","category":"section"},{"location":"morton/","page":"Morton Encoding","title":"Morton Encoding","text":"ImplicitBVH.MortonUnsigned\nImplicitBVH.morton_encode\nImplicitBVH.morton_encode!\nImplicitBVH.morton_encode_single\nImplicitBVH.morton_scaling\nImplicitBVH.morton_split3\nImplicitBVH.bounding_volumes_extrema\nImplicitBVH.relative_precision","category":"page"},{"location":"morton/#ImplicitBVH.MortonUnsigned","page":"Morton Encoding","title":"ImplicitBVH.MortonUnsigned","text":"Acceptable unsigned integer types for Morton encoding: Union{UInt16, UInt32, UInt64}.\n\n\n\n\n\n","category":"type"},{"location":"morton/#ImplicitBVH.morton_encode","page":"Morton Encoding","title":"ImplicitBVH.morton_encode","text":"morton_encode(\n bounding_volumes,\n ::Type{U}=UInt,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nEncode the centers of some bounding_volumes as Morton codes of type U <: MortonUnsigned. See morton_encode! for full details. \n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_encode!","page":"Morton Encoding","title":"ImplicitBVH.morton_encode!","text":"morton_encode!(\n mortons::AbstractVector{U},\n bounding_volumes,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nmorton_encode!(\n mortons::AbstractVector{U},\n bounding_volumes::AbstractVector,\n mins,\n maxs,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nEncode each bounding volume into vector of corresponding Morton codes such that they uniformly cover the maximum Morton range given an unsigned integer type U <: MortonUnsigned.\n\nwarning: Warning\nThe dimension-wise exclusive mins and maxs must be correct; if any bounding volume center is equal to, or beyond mins / maxs, the results will be silently incorrect.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_encode_single","page":"Morton Encoding","title":"ImplicitBVH.morton_encode_single","text":"morton_encode_single(centre, mins, maxs, U::MortonUnsignedType=UInt32)\n\nReturn Morton code for a single 3D position centre scaled uniformly between mins and maxs. Works transparently for SVector, Vector, etc. with eltype UInt16, UInt32 or UInt64.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_scaling","page":"Morton Encoding","title":"ImplicitBVH.morton_scaling","text":"morton_scaling(::Type{UInt16}) = 2^5\nmorton_scaling(::Type{UInt32}) = 2^10\nmorton_scaling(::Type{UInt64}) = 2^21\n\nExclusive maximum number possible to use for 3D Morton encoding for each type.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_split3","page":"Morton Encoding","title":"ImplicitBVH.morton_split3","text":"morton_split3(v::UInt16)\nmorton_split3(v::UInt32)\nmorton_split3(v::UInt64)\n\nShift a number's individual bits such that they have two zeros between them.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.bounding_volumes_extrema","page":"Morton Encoding","title":"ImplicitBVH.bounding_volumes_extrema","text":"bounding_volumes_extrema(bounding_volumes)\n\nCompute exclusive lower and upper bounds in iterable of bounding volumes, e.g. Vector{BBox}.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.relative_precision","page":"Morton Encoding","title":"ImplicitBVH.relative_precision","text":"relative_precision(::Type{Float16}) = 1e-2\nrelative_precision(::Type{Float32}) = 1e-5\nrelative_precision(::Type{Float64}) = 1e-14\n\nRelative precision value for floating-point types.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#Bounding-Volumes","page":"Bounding Volumes","title":"Bounding Volumes","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.BBox\nImplicitBVH.BSphere","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.BBox","page":"Bounding Volumes","title":"ImplicitBVH.BBox","text":"struct BBox{T}\n\nAxis-aligned bounding box, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.\n\nCan also be constructed from two spheres to e.g. allow merging BSphere leaves into BBox nodes.\n\nMethods\n\n# Convenience constructors\nBBox(lo::NTuple{3, T}, up::NTuple{3, T}) where T\nBBox{T}(lo::AbstractVector, up::AbstractVector) where T\nBBox(lo::AbstractVector, up::AbstractVector)\n\n# Construct from triangle vertices\nBBox{T}(p1, p2, p3) where T\nBBox(p1, p2, p3)\nBBox{T}(vertices::AbstractMatrix) where T\nBBox(vertices::AbstractMatrix)\nBBox{T}(triangle) where T\nBBox(triangle)\n\n# Merging bounding boxes\nBBox{T}(a::BBox, b::BBox) where T\nBBox(a::BBox{T}, b::BBox{T}) where T\nBase.:+(a::BBox, b::BBox)\n\n# Merging bounding spheres\nBBox{T}(a::BSphere{T}) where T\nBBox(a::BSphere{T}) where T\nBBox{T}(a::BSphere{T}, b::BSphere{T}) where T\nBBox(a::BSphere{T}, b::BSphere{T}) where T\n\n\n\n\n\n","category":"type"},{"location":"bounding_volumes/#ImplicitBVH.BSphere","page":"Bounding Volumes","title":"ImplicitBVH.BSphere","text":"struct BSphere{T}\n\nBounding sphere, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.\n\nMethods\n\n# Convenience constructors\nBSphere(x::NTuple{3, T}, r)\nBSphere{T}(x::AbstractVector, r) where T\nBSphere(x::AbstractVector, r)\n\n# Construct from triangle vertices\nBSphere{T}(p1, p2, p3) where T\nBSphere(p1, p2, p3)\nBSphere{T}(vertices::AbstractMatrix) where T\nBSphere(vertices::AbstractMatrix)\nBSphere{T}(triangle) where T\nBSphere(triangle)\n\n# Merging bounding volumes\nBSphere{T}(a::BSphere, b::BSphere) where T\nBSphere(a::BSphere{T}, b::BSphere{T}) where T\nBase.:+(a::BSphere, b::BSphere)\n\n\n\n\n\n","category":"type"},{"location":"bounding_volumes/#Query-Functions","page":"Bounding Volumes","title":"Query Functions","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.iscontact\nImplicitBVH.center","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.iscontact","page":"Bounding Volumes","title":"ImplicitBVH.iscontact","text":"iscontact(a::BSphere, b::BSphere)\niscontact(a::BBox, b::BBox)\niscontact(a::BSphere, b::BBox)\niscontact(a::BBox, b::BSphere)\n\nCheck if two bounding volumes are touching or inter-penetrating.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#ImplicitBVH.center","page":"Bounding Volumes","title":"ImplicitBVH.center","text":"center(b::BSphere)\ncenter(b::BBox{T}) where T\n\nGet the coordinates of a bounding volume's centre, as a NTuple{3, T}.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#Miscellaneous","page":"Bounding Volumes","title":"Miscellaneous","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.translate","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.translate","page":"Bounding Volumes","title":"ImplicitBVH.translate","text":"translate(b::BSphere{T}, dx) where T\ntranslate(b::BBox{T}, dx) where T\n\nGet a new bounding volume translated by dx; dx can be any iterable with 3 elements.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#Implicit-Binary-Tree","page":"Implicit Binary Tree","title":"Implicit Binary Tree","text":"","category":"section"},{"location":"implicit_tree/","page":"Implicit Binary Tree","title":"Implicit Binary Tree","text":"ImplicitTree\nmemory_index\nlevel_indices\nisvirtual","category":"page"},{"location":"implicit_tree/#ImplicitBVH.ImplicitTree","page":"Implicit Binary Tree","title":"ImplicitBVH.ImplicitTree","text":"struct ImplicitTree{T<:Integer}\n\nImplicit binary tree for num_leaves elements, where nodes are labelled according to a breadth-first search.\n\nMethods\n\nImplicitTree(num_leaves::Integer)\nImplicitTree{T}(num_leaves::Integer)\n\nFields\n\nlevels::Integer: Number of levels in the tree.\nreal_leaves::Integer: Number of real leaves - i.e. the elements from which the tree was constructed.\nreal_nodes::Integer: Total number of real nodes in tree.\nvirtual_leaves::Integer: Number of virtual leaves needed at the bottom level to have a perfect binary tree.\nvirtual_nodes::Integer: Total number of virtual nodes in tree needed for a complete binary tree.\n\nExamples\n\njulia> using ImplicitBVH\n\n# Given 5 geometric elements (e.g. bounding boxes) we construct the following implicit tree\n# having the 5 real leaves at implicit indices 8-12 plus 3 virtual leaves.\n# Nodes & Leaves Tree Level\n# 1 1\n# 2 3 2\n# 4 5 6 7v 3\n# 8 9 10 11 12 13v 14v 15v 4\njulia> tree = ImplicitTree(5)\nImplicitTree{Int64}\n levels: Int64 4\n real_leaves: Int64 5\n real_nodes: Int64 11\n virtual_leaves: Int64 3\n virtual_nodes: Int64 4\n\n# We can keep all tree nodes in a contiguous vector with no extra padding for the virtual\n# nodes by computing the real memory index of real nodes; e.g. real memory index of node 8\n# skips node 7 which is virtual:\njulia> memory_index(tree, 8)\n7\n\n# We can get the range of indices of real nodes on a given level\njulia> level_indices(tree, 3)\n(4, 6)\n\n# And we can check if a node at a given implicit index is virtual\njulia> isvirtual(tree, 6)\nfalse\n\njulia> isvirtual(tree, 7)\ntrue\n\n\n\n\n\n","category":"type"},{"location":"implicit_tree/#ImplicitBVH.memory_index","page":"Implicit Binary Tree","title":"ImplicitBVH.memory_index","text":"memory_index(tree::ImplicitTree, implicit_index::Integer)\n\nReturn actual memory index for a node at implicit index i in a perfect BFS-labelled tree.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#ImplicitBVH.level_indices","page":"Implicit Binary Tree","title":"ImplicitBVH.level_indices","text":"level_indices(tree::ImplicitTree, level::Integer)\n\nReturn range Tuple{Int64, Int64} of memory indices of elements at level.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#ImplicitBVH.isvirtual","page":"Implicit Binary Tree","title":"ImplicitBVH.isvirtual","text":"isvirtual(tree::ImplicitTree, implicit_index::Integer)\n\nCheck if given implicit_index corresponds to a virtual node.\n\n\n\n\n\n","category":"function"},{"location":"utilities/#Utilities","page":"Utilities","title":"Utilities","text":"","category":"section"},{"location":"utilities/","page":"Utilities","title":"Utilities","text":"ImplicitBVH.BVHOptions\nImplicitBVH.get_index_type\nImplicitBVH.TaskPartitioner","category":"page"},{"location":"utilities/#ImplicitBVH.BVHOptions","page":"Utilities","title":"ImplicitBVH.BVHOptions","text":"struct BVHOptions{I<:Integer, T}\n\nOptions for building and traversing bounding volume hierarchies, including parallel strategy settings.\n\nAn exemplar of an index (e.g. Int32(0)) is used to deduce the types of indices used in the BVH building (ImplicitTree(@ref), order) and traversal (IndexPair(@ref)).\n\nThe CPU scheduler can be :threads (for base Julia threads) or :polyester (for Polyester.jl threads).\n\nIf compute_extrema=false and mins / maxs are defined, they will not be computed from the distribution of bounding volumes; useful if you have a fixed simulation box, for example.\n\nMethods\n\nBVHOptions(;\n\n # Example index from which to deduce type\n index_exemplar::I = Int32(0),\n\n # CPU threading\n scheduler::Symbol = :threads,\n num_threads::Int = Threads.nthreads(),\n min_mortons_per_thread::Int = 1000,\n min_boundings_per_thread::Int = 1000,\n min_traversals_per_thread::Int = 1000,\n\n # GPU scheduling\n block_size::Int = 256,\n\n # Minima / maxima\n compute_extrema::Bool = true,\n mins::NTuple{3, T} = (NaN32, NaN32, NaN32),\n maxs::NTuple{3, T} = (NaN32, NaN32, NaN32),\n) where {I <: Integer, T}\n\nFields\n\nindex_exemplar::Integer\nscheduler::Symbol\nnum_threads::Int64\nmin_mortons_per_thread::Int64\nmin_boundings_per_thread::Int64\nmin_traversals_per_thread::Int64\nblock_size::Int64\ncompute_extrema::Bool\nmins::Tuple{T, T, T} where T\nmaxs::Tuple{T, T, T} where T\n\n\n\n\n\n","category":"type"},{"location":"utilities/#ImplicitBVH.get_index_type","page":"Utilities","title":"ImplicitBVH.get_index_type","text":"Get index type from options or derived data types.\n\nMethods\n\nget_index_type(::ImplicitTree{I}) where I\nget_index_type(options::BVHOptions)\n\n\n\n\n\n","category":"function"},{"location":"utilities/#ImplicitBVH.TaskPartitioner","page":"Utilities","title":"ImplicitBVH.TaskPartitioner","text":"struct TaskPartitioner\n\nPartitioning num_elems elements / jobs over maximum max_tasks tasks with minimum min_elems elements per task.\n\nMethods\n\nTaskPartitioner(num_elems, max_tasks=Threads.nthreads(), min_elems=1)\n\nFields\n\nnum_elems::Int64\nmax_tasks::Int64\nmin_elems::Int64\nnum_tasks::Int64\n\nExamples\n\nusing ImplicitBVH: TaskPartitioner\n\n# Divide 10 elements between 4 tasks\ntp = TaskPartitioner(10, 4)\nfor i in 1:tp.num_tasks\n @show tp[i]\nend\n\n# output\ntp[i] = (1, 3)\ntp[i] = (4, 6)\ntp[i] = (7, 9)\ntp[i] = (10, 10)\n\nusing ImplicitBVH: TaskPartitioner\n\n# Divide 20 elements between 6 tasks with minimum 5 elements per task.\n# Not all tasks will be required\ntp = TaskPartitioner(20, 6, 5)\nfor i in 1:tp.num_tasks\n @show tp[i]\nend\n\n# output\ntp[i] = (1, 5)\ntp[i] = (6, 10)\ntp[i] = (11, 15)\ntp[i] = (16, 20)\n\n\n\n\n\n","category":"type"},{"location":"#ImplicitBVH.jl-Documentation","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"","category":"section"},{"location":"#BVH-Construction-and-Traversal","page":"ImplicitBVH.jl Documentation","title":"BVH Construction & Traversal","text":"","category":"section"},{"location":"","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"BVH\ntraverse\nBVHTraversal\ndefault_start_level\nImplicitBVH.IndexPair","category":"page"},{"location":"#ImplicitBVH.BVH","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.BVH","text":"struct BVH{I<:Integer, VN<:(AbstractVector), VL<:(AbstractVector), VM<:(AbstractVector), VO<:(AbstractVector)}\n\nImplicit bounding volume hierarchy constructed from an iterable of some geometric primitives' (e.g. triangles in a mesh) bounding volumes forming the ImplicitTree leaves. The leaves and merged nodes above them can have different types - e.g. BSphere{Float64} for leaves merged into larger BBox{Float64}.\n\nThe initial geometric primitives are sorted according to their Morton-encoded coordinates; the unsigned integer type used for the Morton encoding can be chosen between Union{UInt16, UInt32, UInt64}.\n\nFinally, the tree can be incompletely-built up to a given built_level and later start contact detection downwards from this level, e.g.:\n\nImplicit tree from 5 bounding volumes - i.e. the real leaves\n\nTree Level Nodes & Leaves Build Up Traverse Down\n 1 1 Ʌ |\n 2 2 3 | |\n 3 4 5 6 7v | |\n 4 8 9 10 11 12 13v 14v 15v | V\n -------Real------- ---Virtual---\n\nMethods\n\n# Normal constructor which builds BVH\nBVH(\n bounding_volumes::AbstractVector{L},\n node_type::Type{N}=L,\n morton_type::Type{U}=UInt32,\n built_level=1;\n options=BVHOptions(),\n) where {L, N, U <: MortonUnsigned}\n\n# Copy constructor reusing previous memory; previous\n# bounding volumes are moved to new_positions.\nBVH(\n prev::BVH,\n new_positions::AbstractMatrix,\n built_level=1;\n options=BVHOptions(),\n)\n\nFields\n\ntree::ImplicitTree{I <: Integer}\nnodes::VN <: AbstractVector\nleaves::VL <: AbstractVector\nmortons::VM <: AbstractVector\norder::VO <: AbstractVector\nbuilt_level::Int\n\nExamples\n\nSimple usage with bounding spheres and default 64-bit types:\n\nusing ImplicitBVH\nusing ImplicitBVH: BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere([0., 0., 0.], 0.5),\n BSphere([0., 0., 1.], 0.6),\n BSphere([0., 0., 2.], 0.5),\n BSphere([0., 0., 3.], 0.4),\n BSphere([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\nUsing Float32 bounding spheres for leaves, Float32 bounding boxes for nodes above, and UInt32 Morton codes:\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\nBuild BVH up to level 2 and start traversing down from level 3, reusing the previous traversal cache:\n\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32, 2)\ntraversal = traverse(bvh, 3, traversal)\n\nUpdate previous BVH bounding volumes' positions and rebuild BVH reusing previous memory:\n\nnew_positions = rand(3, 5)\nbvh_rebuilt = BVH(bvh, new_positions)\n\n\n\n\n\n","category":"type"},{"location":"#ImplicitBVH.traverse","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.traverse","text":"traverse(\n bvh::BVH,\n start_level::Int=default_start_level(bvh),\n cache::Union{Nothing, BVHTraversal}=nothing;\n options=BVHOptions(),\n)::BVHTraversal\n\nTraverse bvh downwards from start_level, returning all contacting bounding volume leaves. The returned BVHTraversal also contains two contact buffers that can be reused on future traversals.\n\nExamples\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh, 2)\n\n# Reuse traversal buffers for future contact detection - possibly with different BVHs\ntraversal = traverse(bvh, 2, traversal)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\n\n\n\n\ntraverse(\n bvh1::BVH,\n bvh2::BVH,\n start_level1::Int=default_start_level(bvh1),\n start_level2::Int=default_start_level(bvh2),\n cache::Union{Nothing, BVHTraversal}=nothing;\n options=BVHOptions(),\n)::BVHTraversal\n\nReturn all the bvh1 bounding volume leaves that are in contact with any in bvh2. The returned BVHTraversal also contains two contact buffers that can be reused on future traversals.\n\nExamples\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres1 = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n]\n\nbounding_spheres2 = [\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVHs\nbvh1 = BVH(bounding_spheres1, BBox{Float32}, UInt32)\nbvh2 = BVH(bounding_spheres2, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh1, bvh2, default_start_level(bvh1), default_start_level(bvh2))\n\n# Reuse traversal buffers for future contact detection - possibly with different BVHs\ntraversal = traverse(bvh1, bvh2, default_start_level(bvh1), default_start_level(bvh2), traversal)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 1), (2, 3)]\n\n\n\n\n\n","category":"function"},{"location":"#ImplicitBVH.BVHTraversal","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.BVHTraversal","text":"struct BVHTraversal{C1<:(AbstractVector), C2<:(AbstractVector)}\n\nCollected BVH traversal contacts vector, some stats, plus the two buffers cache1 and cache2 which can be reused for future traversals to minimise memory allocations.\n\nFields\n\nstart_level1::Int: the level at which the single/pair-tree traversal started for the first BVH.\nstart_level2::Int: the level at which the pair-tree traversal started for the second BVH.\nnum_checks::Int: the total number of contact checks done.\nnum_contacts::Int: the number of contacts found.\ncontacts::view(cache1, 1:num_contacts): the contacting pairs found, as a view into cache1.\ncache1::C1{IndexPair} <: AbstractVector: first BVH traversal buffer.\ncache2::C2{IndexPair} <: AbstractVector: second BVH traversal buffer.\n\n\n\n\n\n","category":"type"},{"location":"#ImplicitBVH.default_start_level","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.default_start_level","text":"default_start_level(bvh::BVH)::Int\ndefault_start_level(num_leaves::Integer)::Int\n\nCompute the default start level when traversing a single BVH tree.\n\n\n\n\n\n","category":"function"},{"location":"#ImplicitBVH.IndexPair","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.IndexPair","text":"struct Tuple{I, I}\n\nAlias for a tuple of two indices representing e.g. a contacting pair.\n\n\n\n\n\n","category":"type"},{"location":"#Index","page":"ImplicitBVH.jl Documentation","title":"Index","text":"","category":"section"},{"location":"","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"","category":"page"}] +[{"location":"morton/#Morton-Encoding","page":"Morton Encoding","title":"Morton Encoding","text":"","category":"section"},{"location":"morton/","page":"Morton Encoding","title":"Morton Encoding","text":"ImplicitBVH.MortonUnsigned\nImplicitBVH.morton_encode\nImplicitBVH.morton_encode!\nImplicitBVH.morton_encode_single\nImplicitBVH.morton_scaling\nImplicitBVH.morton_split3\nImplicitBVH.bounding_volumes_extrema\nImplicitBVH.relative_precision","category":"page"},{"location":"morton/#ImplicitBVH.MortonUnsigned","page":"Morton Encoding","title":"ImplicitBVH.MortonUnsigned","text":"Acceptable unsigned integer types for Morton encoding: Union{UInt16, UInt32, UInt64}.\n\n\n\n\n\n","category":"type"},{"location":"morton/#ImplicitBVH.morton_encode","page":"Morton Encoding","title":"ImplicitBVH.morton_encode","text":"morton_encode(\n bounding_volumes,\n ::Type{U}=UInt,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nEncode the centers of some bounding_volumes as Morton codes of type U <: MortonUnsigned. See morton_encode! for full details. \n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_encode!","page":"Morton Encoding","title":"ImplicitBVH.morton_encode!","text":"morton_encode!(\n mortons::AbstractVector{U},\n bounding_volumes,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nmorton_encode!(\n mortons::AbstractVector{U},\n bounding_volumes::AbstractVector,\n mins,\n maxs,\n options=BVHOptions(),\n) where {U <: MortonUnsigned}\n\nEncode each bounding volume into vector of corresponding Morton codes such that they uniformly cover the maximum Morton range given an unsigned integer type U <: MortonUnsigned.\n\nwarning: Warning\nThe dimension-wise exclusive mins and maxs must be correct; if any bounding volume center is equal to, or beyond mins / maxs, the results will be silently incorrect.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_encode_single","page":"Morton Encoding","title":"ImplicitBVH.morton_encode_single","text":"morton_encode_single(centre, mins, maxs, U::MortonUnsignedType=UInt32)\n\nReturn Morton code for a single 3D position centre scaled uniformly between mins and maxs. Works transparently for SVector, Vector, etc. with eltype UInt16, UInt32 or UInt64.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_scaling","page":"Morton Encoding","title":"ImplicitBVH.morton_scaling","text":"morton_scaling(::Type{UInt16}) = 2^5\nmorton_scaling(::Type{UInt32}) = 2^10\nmorton_scaling(::Type{UInt64}) = 2^21\n\nExclusive maximum number possible to use for 3D Morton encoding for each type.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.morton_split3","page":"Morton Encoding","title":"ImplicitBVH.morton_split3","text":"morton_split3(v::UInt16)\nmorton_split3(v::UInt32)\nmorton_split3(v::UInt64)\n\nShift a number's individual bits such that they have two zeros between them.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.bounding_volumes_extrema","page":"Morton Encoding","title":"ImplicitBVH.bounding_volumes_extrema","text":"bounding_volumes_extrema(bounding_volumes)\n\nCompute exclusive lower and upper bounds in iterable of bounding volumes, e.g. Vector{BBox}.\n\n\n\n\n\n","category":"function"},{"location":"morton/#ImplicitBVH.relative_precision","page":"Morton Encoding","title":"ImplicitBVH.relative_precision","text":"relative_precision(::Type{Float16}) = 1e-2\nrelative_precision(::Type{Float32}) = 1e-5\nrelative_precision(::Type{Float64}) = 1e-14\n\nRelative precision value for floating-point types.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#Bounding-Volumes","page":"Bounding Volumes","title":"Bounding Volumes","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.BBox\nImplicitBVH.BSphere","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.BBox","page":"Bounding Volumes","title":"ImplicitBVH.BBox","text":"struct BBox{T}\n\nAxis-aligned bounding box, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.\n\nCan also be constructed from two spheres to e.g. allow merging BSphere leaves into BBox nodes.\n\nMethods\n\n# Convenience constructors\nBBox(lo::NTuple{3, T}, up::NTuple{3, T}) where T\nBBox{T}(lo::AbstractVector, up::AbstractVector) where T\nBBox(lo::AbstractVector, up::AbstractVector)\n\n# Construct from triangle vertices\nBBox{T}(p1, p2, p3) where T\nBBox(p1, p2, p3)\nBBox{T}(vertices::AbstractMatrix) where T\nBBox(vertices::AbstractMatrix)\nBBox{T}(triangle) where T\nBBox(triangle)\n\n# Merging bounding boxes\nBBox{T}(a::BBox, b::BBox) where T\nBBox(a::BBox{T}, b::BBox{T}) where T\nBase.:+(a::BBox, b::BBox)\n\n# Merging bounding spheres\nBBox{T}(a::BSphere{T}) where T\nBBox(a::BSphere{T}) where T\nBBox{T}(a::BSphere{T}, b::BSphere{T}) where T\nBBox(a::BSphere{T}, b::BSphere{T}) where T\n\n\n\n\n\n","category":"type"},{"location":"bounding_volumes/#ImplicitBVH.BSphere","page":"Bounding Volumes","title":"ImplicitBVH.BSphere","text":"struct BSphere{T}\n\nBounding sphere, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.\n\nMethods\n\n# Convenience constructors\nBSphere(x::NTuple{3, T}, r)\nBSphere{T}(x::AbstractVector, r) where T\nBSphere(x::AbstractVector, r)\n\n# Construct from triangle vertices\nBSphere{T}(p1, p2, p3) where T\nBSphere(p1, p2, p3)\nBSphere{T}(vertices::AbstractMatrix) where T\nBSphere(vertices::AbstractMatrix)\nBSphere{T}(triangle) where T\nBSphere(triangle)\n\n# Merging bounding volumes\nBSphere{T}(a::BSphere, b::BSphere) where T\nBSphere(a::BSphere{T}, b::BSphere{T}) where T\nBase.:+(a::BSphere, b::BSphere)\n\n\n\n\n\n","category":"type"},{"location":"bounding_volumes/#Query-Functions","page":"Bounding Volumes","title":"Query Functions","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.iscontact\nImplicitBVH.center","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.iscontact","page":"Bounding Volumes","title":"ImplicitBVH.iscontact","text":"iscontact(a::BSphere, b::BSphere)\niscontact(a::BBox, b::BBox)\niscontact(a::BSphere, b::BBox)\niscontact(a::BBox, b::BSphere)\n\nCheck if two bounding volumes are touching or inter-penetrating.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#ImplicitBVH.center","page":"Bounding Volumes","title":"ImplicitBVH.center","text":"center(b::BSphere)\ncenter(b::BBox{T}) where T\n\nGet the coordinates of a bounding volume's centre, as a NTuple{3, T}.\n\n\n\n\n\n","category":"function"},{"location":"bounding_volumes/#Miscellaneous","page":"Bounding Volumes","title":"Miscellaneous","text":"","category":"section"},{"location":"bounding_volumes/","page":"Bounding Volumes","title":"Bounding Volumes","text":"ImplicitBVH.translate","category":"page"},{"location":"bounding_volumes/#ImplicitBVH.translate","page":"Bounding Volumes","title":"ImplicitBVH.translate","text":"translate(b::BSphere{T}, dx) where T\ntranslate(b::BBox{T}, dx) where T\n\nGet a new bounding volume translated by dx; dx can be any iterable with 3 elements.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#Implicit-Binary-Tree","page":"Implicit Binary Tree","title":"Implicit Binary Tree","text":"","category":"section"},{"location":"implicit_tree/","page":"Implicit Binary Tree","title":"Implicit Binary Tree","text":"ImplicitTree\nmemory_index\nlevel_indices\nisvirtual","category":"page"},{"location":"implicit_tree/#ImplicitBVH.ImplicitTree","page":"Implicit Binary Tree","title":"ImplicitBVH.ImplicitTree","text":"struct ImplicitTree{T<:Integer}\n\nImplicit binary tree for num_leaves elements, where nodes are labelled according to a breadth-first search.\n\nMethods\n\nImplicitTree(num_leaves::Integer)\nImplicitTree{T}(num_leaves::Integer)\n\nFields\n\nlevels::Integer: Number of levels in the tree.\nreal_leaves::Integer: Number of real leaves - i.e. the elements from which the tree was constructed.\nreal_nodes::Integer: Total number of real nodes in tree.\nvirtual_leaves::Integer: Number of virtual leaves needed at the bottom level to have a perfect binary tree.\nvirtual_nodes::Integer: Total number of virtual nodes in tree needed for a complete binary tree.\n\nExamples\n\njulia> using ImplicitBVH\n\n# Given 5 geometric elements (e.g. bounding boxes) we construct the following implicit tree\n# having the 5 real leaves at implicit indices 8-12 plus 3 virtual leaves.\n# Nodes & Leaves Tree Level\n# 1 1\n# 2 3 2\n# 4 5 6 7v 3\n# 8 9 10 11 12 13v 14v 15v 4\njulia> tree = ImplicitTree(5)\nImplicitTree{Int64}\n levels: Int64 4\n real_leaves: Int64 5\n real_nodes: Int64 11\n virtual_leaves: Int64 3\n virtual_nodes: Int64 4\n\n# We can keep all tree nodes in a contiguous vector with no extra padding for the virtual\n# nodes by computing the real memory index of real nodes; e.g. real memory index of node 8\n# skips node 7 which is virtual:\njulia> memory_index(tree, 8)\n7\n\n# We can get the range of indices of real nodes on a given level\njulia> level_indices(tree, 3)\n(4, 6)\n\n# And we can check if a node at a given implicit index is virtual\njulia> isvirtual(tree, 6)\nfalse\n\njulia> isvirtual(tree, 7)\ntrue\n\n\n\n\n\n","category":"type"},{"location":"implicit_tree/#ImplicitBVH.memory_index","page":"Implicit Binary Tree","title":"ImplicitBVH.memory_index","text":"memory_index(tree::ImplicitTree, implicit_index::Integer)\n\nReturn actual memory index for a node at implicit index i in a perfect BFS-labelled tree.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#ImplicitBVH.level_indices","page":"Implicit Binary Tree","title":"ImplicitBVH.level_indices","text":"level_indices(tree::ImplicitTree, level::Integer)\n\nReturn range Tuple{Int64, Int64} of memory indices of elements at level.\n\n\n\n\n\n","category":"function"},{"location":"implicit_tree/#ImplicitBVH.isvirtual","page":"Implicit Binary Tree","title":"ImplicitBVH.isvirtual","text":"isvirtual(tree::ImplicitTree, implicit_index::Integer)\n\nCheck if given implicit_index corresponds to a virtual node.\n\n\n\n\n\n","category":"function"},{"location":"utilities/#Utilities","page":"Utilities","title":"Utilities","text":"","category":"section"},{"location":"utilities/","page":"Utilities","title":"Utilities","text":"ImplicitBVH.BVHOptions\nImplicitBVH.get_index_type","category":"page"},{"location":"utilities/#ImplicitBVH.BVHOptions","page":"Utilities","title":"ImplicitBVH.BVHOptions","text":"struct BVHOptions{I<:Integer, T}\n\nOptions for building and traversing bounding volume hierarchies, including parallel strategy settings.\n\nAn exemplar of an index (e.g. Int32(0)) is used to deduce the types of indices used in the BVH building (ImplicitTree, order) and traversal (IndexPair).\n\nThe CPU scheduler can be :threads (for base Julia threads) or :polyester (for Polyester.jl threads).\n\nIf compute_extrema=false and mins / maxs are defined, they will not be computed from the distribution of bounding volumes; useful if you have a fixed simulation box, for example. You must ensure that no bounding volume centers will touch or be outside these bounds, otherwise logically incorrect results will be silently produced.\n\nMethods\n\nBVHOptions(;\n\n # Example index from which to deduce type\n index_exemplar::I = Int32(0),\n\n # CPU threading\n scheduler::Symbol = :threads,\n num_threads::Int = Threads.nthreads(),\n min_mortons_per_thread::Int = 1000,\n min_boundings_per_thread::Int = 1000,\n min_traversals_per_thread::Int = 1000,\n\n # GPU scheduling\n block_size::Int = 256,\n\n # Minima / maxima\n compute_extrema::Bool = true,\n mins::NTuple{3, T} = (NaN32, NaN32, NaN32),\n maxs::NTuple{3, T} = (NaN32, NaN32, NaN32),\n) where {I <: Integer, T}\n\nFields\n\nindex_exemplar::Integer\nscheduler::Symbol\nnum_threads::Int64\nmin_mortons_per_thread::Int64\nmin_boundings_per_thread::Int64\nmin_traversals_per_thread::Int64\nblock_size::Int64\ncompute_extrema::Bool\nmins::Tuple{T, T, T} where T\nmaxs::Tuple{T, T, T} where T\n\n\n\n\n\n","category":"type"},{"location":"utilities/#ImplicitBVH.get_index_type","page":"Utilities","title":"ImplicitBVH.get_index_type","text":"Get index type from options or derived data types.\n\nMethods\n\nget_index_type(::ImplicitTree{I}) where I\nget_index_type(options::BVHOptions)\n\n\n\n\n\n","category":"function"},{"location":"#ImplicitBVH.jl-Documentation","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"","category":"section"},{"location":"#BVH-Construction-and-Traversal","page":"ImplicitBVH.jl Documentation","title":"BVH Construction & Traversal","text":"","category":"section"},{"location":"","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"BVH\ntraverse\nBVHTraversal\ndefault_start_level\nImplicitBVH.IndexPair","category":"page"},{"location":"#ImplicitBVH.BVH","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.BVH","text":"struct BVH{I<:Integer, VN<:(AbstractVector), VL<:(AbstractVector), VM<:(AbstractVector), VO<:(AbstractVector)}\n\nImplicit bounding volume hierarchy constructed from an iterable of some geometric primitives' (e.g. triangles in a mesh) bounding volumes forming the ImplicitTree leaves. The leaves and merged nodes above them can have different types - e.g. BSphere{Float64} for leaves merged into larger BBox{Float64}.\n\nThe initial geometric primitives are sorted according to their Morton-encoded coordinates; the unsigned integer type used for the Morton encoding can be chosen between Union{UInt16, UInt32, UInt64}.\n\nFinally, the tree can be incompletely-built up to a given built_level and later start contact detection downwards from this level, e.g.:\n\nImplicit tree from 5 bounding volumes - i.e. the real leaves\n\nTree Level Nodes & Leaves Build Up Traverse Down\n 1 1 Ʌ |\n 2 2 3 | |\n 3 4 5 6 7v | |\n 4 8 9 10 11 12 13v 14v 15v | V\n -------Real------- ---Virtual---\n\nMethods\n\n# Normal constructor which builds BVH\nBVH(\n bounding_volumes::AbstractVector{L},\n node_type::Type{N}=L,\n morton_type::Type{U}=UInt32,\n built_level=1;\n options=BVHOptions(),\n) where {L, N, U <: MortonUnsigned}\n\n# Copy constructor reusing previous memory; previous\n# bounding volumes are moved to new_positions.\nBVH(\n prev::BVH,\n new_positions::AbstractMatrix,\n built_level=1;\n options=BVHOptions(),\n)\n\nFields\n\ntree::ImplicitTree{I <: Integer}\nnodes::VN <: AbstractVector\nleaves::VL <: AbstractVector\nmortons::VM <: AbstractVector\norder::VO <: AbstractVector\nbuilt_level::Int\n\nExamples\n\nSimple usage with bounding spheres and default 64-bit types:\n\nusing ImplicitBVH\nusing ImplicitBVH: BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere([0., 0., 0.], 0.5),\n BSphere([0., 0., 1.], 0.6),\n BSphere([0., 0., 2.], 0.5),\n BSphere([0., 0., 3.], 0.4),\n BSphere([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\nUsing Float32 bounding spheres for leaves, Float32 bounding boxes for nodes above, and UInt32 Morton codes:\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\nBuild BVH up to level 2 and start traversing down from level 3, reusing the previous traversal cache:\n\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32, 2)\ntraversal = traverse(bvh, 3, traversal)\n\nUpdate previous BVH bounding volumes' positions and rebuild BVH reusing previous memory:\n\nnew_positions = rand(3, 5)\nbvh_rebuilt = BVH(bvh, new_positions)\n\n\n\n\n\n","category":"type"},{"location":"#ImplicitBVH.traverse","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.traverse","text":"traverse(\n bvh::BVH,\n start_level::Int=default_start_level(bvh),\n cache::Union{Nothing, BVHTraversal}=nothing;\n options=BVHOptions(),\n)::BVHTraversal\n\nTraverse bvh downwards from start_level, returning all contacting bounding volume leaves. The returned BVHTraversal also contains two contact buffers that can be reused on future traversals.\n\nExamples\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVH\nbvh = BVH(bounding_spheres, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh, 2)\n\n# Reuse traversal buffers for future contact detection - possibly with different BVHs\ntraversal = traverse(bvh, 2, traversal)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 2), (2, 3), (4, 5)]\n\n\n\n\n\ntraverse(\n bvh1::BVH,\n bvh2::BVH,\n start_level1::Int=default_start_level(bvh1),\n start_level2::Int=default_start_level(bvh2),\n cache::Union{Nothing, BVHTraversal}=nothing;\n options=BVHOptions(),\n)::BVHTraversal\n\nReturn all the bvh1 bounding volume leaves that are in contact with any in bvh2. The returned BVHTraversal also contains two contact buffers that can be reused on future traversals.\n\nExamples\n\nusing ImplicitBVH\nusing ImplicitBVH: BBox, BSphere\n\n# Generate some simple bounding spheres\nbounding_spheres1 = [\n BSphere{Float32}([0., 0., 0.], 0.5),\n BSphere{Float32}([0., 0., 3.], 0.4),\n]\n\nbounding_spheres2 = [\n BSphere{Float32}([0., 0., 1.], 0.6),\n BSphere{Float32}([0., 0., 2.], 0.5),\n BSphere{Float32}([0., 0., 4.], 0.6),\n]\n\n# Build BVHs\nbvh1 = BVH(bounding_spheres1, BBox{Float32}, UInt32)\nbvh2 = BVH(bounding_spheres2, BBox{Float32}, UInt32)\n\n# Traverse BVH for contact detection\ntraversal = traverse(bvh1, bvh2, default_start_level(bvh1), default_start_level(bvh2))\n\n# Reuse traversal buffers for future contact detection - possibly with different BVHs\ntraversal = traverse(bvh1, bvh2, default_start_level(bvh1), default_start_level(bvh2), traversal)\n@show traversal.contacts;\n;\n\n# output\ntraversal.contacts = Tuple{Int32, Int32}[(1, 1), (2, 3)]\n\n\n\n\n\n","category":"function"},{"location":"#ImplicitBVH.BVHTraversal","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.BVHTraversal","text":"struct BVHTraversal{C1<:(AbstractVector), C2<:(AbstractVector)}\n\nCollected BVH traversal contacts vector, some stats, plus the two buffers cache1 and cache2 which can be reused for future traversals to minimise memory allocations.\n\nFields\n\nstart_level1::Int: the level at which the single/pair-tree traversal started for the first BVH.\nstart_level2::Int: the level at which the pair-tree traversal started for the second BVH.\nnum_checks::Int: the total number of contact checks done.\nnum_contacts::Int: the number of contacts found.\ncontacts::view(cache1, 1:num_contacts): the contacting pairs found, as a view into cache1.\ncache1::C1{IndexPair} <: AbstractVector: first BVH traversal buffer.\ncache2::C2{IndexPair} <: AbstractVector: second BVH traversal buffer.\n\n\n\n\n\n","category":"type"},{"location":"#ImplicitBVH.default_start_level","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.default_start_level","text":"default_start_level(bvh::BVH)::Int\ndefault_start_level(num_leaves::Integer)::Int\n\nCompute the default start level when traversing a single BVH tree.\n\n\n\n\n\n","category":"function"},{"location":"#ImplicitBVH.IndexPair","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.IndexPair","text":"const IndexPair{I} = Tuple{I, I}\n\nAlias for a tuple of two indices representing e.g. a contacting pair.\n\n\n\n\n\n","category":"type"},{"location":"#Index","page":"ImplicitBVH.jl Documentation","title":"Index","text":"","category":"section"},{"location":"","page":"ImplicitBVH.jl Documentation","title":"ImplicitBVH.jl Documentation","text":"","category":"page"}] } diff --git a/dev/utilities/index.html b/dev/utilities/index.html index 16f1aa2..9295987 100644 --- a/dev/utilities/index.html +++ b/dev/utilities/index.html @@ -1,5 +1,5 @@ -Utilities · ImplicitBVH.jl

Utilities

ImplicitBVH.BVHOptionsType
struct BVHOptions{I<:Integer, T}

Options for building and traversing bounding volume hierarchies, including parallel strategy settings.

An exemplar of an index (e.g. Int32(0)) is used to deduce the types of indices used in the BVH building (ImplicitTree(@ref), order) and traversal (IndexPair(@ref)).

The CPU scheduler can be :threads (for base Julia threads) or :polyester (for Polyester.jl threads).

If compute_extrema=false and mins / maxs are defined, they will not be computed from the distribution of bounding volumes; useful if you have a fixed simulation box, for example.

Methods

BVHOptions(;
+Utilities · ImplicitBVH.jl

Utilities

ImplicitBVH.BVHOptionsType
struct BVHOptions{I<:Integer, T}

Options for building and traversing bounding volume hierarchies, including parallel strategy settings.

An exemplar of an index (e.g. Int32(0)) is used to deduce the types of indices used in the BVH building (ImplicitTree, order) and traversal (IndexPair).

The CPU scheduler can be :threads (for base Julia threads) or :polyester (for Polyester.jl threads).

If compute_extrema=false and mins / maxs are defined, they will not be computed from the distribution of bounding volumes; useful if you have a fixed simulation box, for example. You must ensure that no bounding volume centers will touch or be outside these bounds, otherwise logically incorrect results will be silently produced.

Methods

BVHOptions(;
 
     # Example index from which to deduce type
     index_exemplar::I               = Int32(0),
@@ -18,30 +18,5 @@
     compute_extrema::Bool           = true,
     mins::NTuple{3, T}              = (NaN32, NaN32, NaN32),
     maxs::NTuple{3, T}              = (NaN32, NaN32, NaN32),
-) where {I <: Integer, T}

Fields

  • index_exemplar::Integer

  • scheduler::Symbol

  • num_threads::Int64

  • min_mortons_per_thread::Int64

  • min_boundings_per_thread::Int64

  • min_traversals_per_thread::Int64

  • block_size::Int64

  • compute_extrema::Bool

  • mins::Tuple{T, T, T} where T

  • maxs::Tuple{T, T, T} where T

source
ImplicitBVH.get_index_typeFunction

Get index type from options or derived data types.

Methods

get_index_type(::ImplicitTree{I}) where I
-get_index_type(options::BVHOptions)
source
ImplicitBVH.TaskPartitionerType
struct TaskPartitioner

Partitioning num_elems elements / jobs over maximum max_tasks tasks with minimum min_elems elements per task.

Methods

TaskPartitioner(num_elems, max_tasks=Threads.nthreads(), min_elems=1)

Fields

  • num_elems::Int64

  • max_tasks::Int64

  • min_elems::Int64

  • num_tasks::Int64

Examples

using ImplicitBVH: TaskPartitioner
-
-# Divide 10 elements between 4 tasks
-tp = TaskPartitioner(10, 4)
-for i in 1:tp.num_tasks
-    @show tp[i]
-end
-
-# output
-tp[i] = (1, 3)
-tp[i] = (4, 6)
-tp[i] = (7, 9)
-tp[i] = (10, 10)
using ImplicitBVH: TaskPartitioner
-
-# Divide 20 elements between 6 tasks with minimum 5 elements per task.
-# Not all tasks will be required
-tp = TaskPartitioner(20, 6, 5)
-for i in 1:tp.num_tasks
-    @show tp[i]
-end
-
-# output
-tp[i] = (1, 5)
-tp[i] = (6, 10)
-tp[i] = (11, 15)
-tp[i] = (16, 20)
source
+) where {I <: Integer, T}

Fields

  • index_exemplar::Integer

  • scheduler::Symbol

  • num_threads::Int64

  • min_mortons_per_thread::Int64

  • min_boundings_per_thread::Int64

  • min_traversals_per_thread::Int64

  • block_size::Int64

  • compute_extrema::Bool

  • mins::Tuple{T, T, T} where T

  • maxs::Tuple{T, T, T} where T

source
ImplicitBVH.get_index_typeFunction

Get index type from options or derived data types.

Methods

get_index_type(::ImplicitTree{I}) where I
+get_index_type(options::BVHOptions)
source

Bounding Volumes

ImplicitBVH.BBoxType
struct BBox{T}

Axis-aligned bounding box, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.

Can also be constructed from two spheres to e.g. allow merging BSphere leaves into BBox nodes.

Methods

# Convenience constructors
+Bounding Volumes · ImplicitBVH.jl

Bounding Volumes

ImplicitBVH.BBoxType
struct BBox{T}

Axis-aligned bounding box, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.

Can also be constructed from two spheres to e.g. allow merging BSphere leaves into BBox nodes.

Methods

# Convenience constructors
 BBox(lo::NTuple{3, T}, up::NTuple{3, T}) where T
 BBox{T}(lo::AbstractVector, up::AbstractVector) where T
 BBox(lo::AbstractVector, up::AbstractVector)
@@ -21,7 +21,7 @@
 BBox{T}(a::BSphere{T}) where T
 BBox(a::BSphere{T}) where T
 BBox{T}(a::BSphere{T}, b::BSphere{T}) where T
-BBox(a::BSphere{T}, b::BSphere{T}) where T
source
ImplicitBVH.BSphereType
struct BSphere{T}

Bounding sphere, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.

Methods

# Convenience constructors
+BBox(a::BSphere{T}, b::BSphere{T}) where T
source
ImplicitBVH.BSphereType
struct BSphere{T}

Bounding sphere, highly optimised for computing bounding volumes for triangles and merging into larger bounding volumes.

Methods

# Convenience constructors
 BSphere(x::NTuple{3, T}, r)
 BSphere{T}(x::AbstractVector, r) where T
 BSphere(x::AbstractVector, r)
@@ -37,9 +37,9 @@
 # Merging bounding volumes
 BSphere{T}(a::BSphere, b::BSphere) where T
 BSphere(a::BSphere{T}, b::BSphere{T}) where T
-Base.:+(a::BSphere, b::BSphere)
source

Query Functions

Query Functions

ImplicitBVH.iscontactFunction
iscontact(a::BSphere, b::BSphere)
 iscontact(a::BBox, b::BBox)
 iscontact(a::BSphere, b::BBox)
-iscontact(a::BBox, b::BSphere)

Check if two bounding volumes are touching or inter-penetrating.

source
ImplicitBVH.centerFunction
center(b::BSphere)
-center(b::BBox{T}) where T

Get the coordinates of a bounding volume's centre, as a NTuple{3, T}.

source

Miscellaneous

ImplicitBVH.translateFunction
translate(b::BSphere{T}, dx) where T
-translate(b::BBox{T}, dx) where T

Get a new bounding volume translated by dx; dx can be any iterable with 3 elements.

source
+iscontact(a::BBox, b::BSphere)

Check if two bounding volumes are touching or inter-penetrating.

source
ImplicitBVH.centerFunction
center(b::BSphere)
+center(b::BBox{T}) where T

Get the coordinates of a bounding volume's centre, as a NTuple{3, T}.

source

Miscellaneous

ImplicitBVH.translateFunction
translate(b::BSphere{T}, dx) where T
+translate(b::BBox{T}, dx) where T

Get a new bounding volume translated by dx; dx can be any iterable with 3 elements.

source