Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TIndexedKdtreeNode.h
Go to the documentation of this file.
1#pragma once
2
3#include "Math/constant.h"
4#include "Utility/TSpan.h"
5
6#include <Common/assertion.h>
7#include <Common/primitive_type.h>
8#include <Common/utility.h>
9
10#include <cstddef>
11#include <vector>
12#include <limits>
13#include <cmath>
14#include <type_traits>
15
16namespace ph::math
17{
18
21template<typename Index, bool USE_SINGLE_ITEM_OPT = true>
23{
24 // Theoretically we can use a signed type. Limiting to unsigned types to simplify the implementation.
25 static_assert(std::is_unsigned_v<Index>);
26
27 inline static constexpr std::size_t NUM_FLAG_BITS = 2;
28 inline static constexpr std::size_t NUM_NUMBER_BITS = sizeof_in_bits<Index>() - NUM_FLAG_BITS;
29 inline static constexpr std::size_t MAX_NUMBER = (std::size_t(1) << NUM_NUMBER_BITS) - 1;
30
31 inline static constexpr Index FLAG_BITS_MASK = 0b11;
32 inline static constexpr Index X_AXIS_FLAG = 0b00;
33 inline static constexpr Index Y_AXIS_FLAG = 0b01;
34 inline static constexpr Index Z_AXIS_FLAG = 0b10;
35 inline static constexpr Index LEAF_FLAG = 0b11;
36
37public:
39 inline static constexpr std::size_t MAX_NODE_ITEMS = MAX_NUMBER;
40
42 inline static constexpr std::size_t MAX_NODE_INDEX = MAX_NUMBER;
43
47 inline static constexpr std::size_t MAX_BUFFER_OFFSET = std::numeric_limits<Index>::max();
48
50 real splitPos,
51 std::size_t splitAxisIndex,
52 std::size_t positiveChildIndex);
53
55 Index indexBufferOffset,
56 std::size_t numItems);
57
59 TSpanView<Index> itemIndices,
60 std::vector<Index>& indexBuffer);
61
62 bool isLeaf() const;
63 std::size_t getPositiveChildIndex() const;
64 std::size_t numItems() const;
65 real getSplitPos() const;
66 std::size_t getSplitAxis() const;
67 std::size_t getSingleItemDirectIndex() const;
68 std::size_t getIndexBufferOffset() const;
69
70private:
79 union
80 {
84 };
85
98 Index m_numberAndFlags;
99};
100
101// In-header Implementations:
102
103template<typename Index, bool USE_SINGLE_ITEM_OPT>
106 const real splitPos,
107 const std::size_t splitAxisIndex,
108 const std::size_t positiveChildIndex)
110{
111 static_assert(constant::X_AXIS == X_AXIS_FLAG);
112 static_assert(constant::Y_AXIS == Y_AXIS_FLAG);
113 static_assert(constant::Z_AXIS == Z_AXIS_FLAG);
114
115 PH_ASSERT(!std::isnan(splitPos) && !std::isinf(splitPos));
116 PH_ASSERT_IN_RANGE_INCLUSIVE(splitAxisIndex, 0, 2);
117 PH_ASSERT_LE(positiveChildIndex, MAX_NODE_INDEX);
118
120 node.u0_splitPos = splitPos;
121 node.m_numberAndFlags = static_cast<Index>((positiveChildIndex << NUM_FLAG_BITS) | splitAxisIndex);
122
123 return node;
124}
125
126template<typename Index, bool USE_SINGLE_ITEM_OPT>
129 const Index indexBufferOffset,
130 const std::size_t numItems)
132{
133 PH_ASSERT_LE(numItems, MAX_NODE_ITEMS);
134
136 node.m_numberAndFlags = static_cast<Index>((numItems << NUM_FLAG_BITS) | LEAF_FLAG);
137 node.u0_indexBufferOffset = lossless_cast<decltype(node.u0_indexBufferOffset)>(indexBufferOffset);
138
139 return node;
140}
141
142template<typename Index, bool USE_SINGLE_ITEM_OPT>
145 const TSpanView<Index> itemIndices,
146 std::vector<Index>& indexBuffer)
148{
149 PH_ASSERT(itemIndices.data());
150
151 // General case: indirect item access via index buffer
152 if(!(USE_SINGLE_ITEM_OPT && itemIndices.size() == 1))
153 {
154 // For leaf nodes we directly store index buffer offset in `u0`. Make sure that it
155 // will not overflow `Index`.
156 PH_ASSERT_LE(indexBuffer.size(), MAX_BUFFER_OFFSET);
157 const Index indexBufferOffset = static_cast<Index>(indexBuffer.size());
158
159 indexBuffer.insert(indexBuffer.end(), itemIndices.begin(), itemIndices.end());
160
161 return makeLeaf(indexBufferOffset, itemIndices.size());
162 }
163 // Special case: direct item access
164 else
165 {
166 // Make sure item buffer offset will no overflow `Index`.
167 PH_ASSERT_LE(itemIndices[0], MAX_BUFFER_OFFSET);
168
169 constexpr Index oneItemAndLeafFlag = static_cast<Index>((1 << NUM_FLAG_BITS) | LEAF_FLAG);
170
172 node.m_numberAndFlags = oneItemAndLeafFlag;
173 node.u0_itemBufferOffset = itemIndices[0];
174
175 return node;
176 }
177}
178
179template<typename Index, bool USE_SINGLE_ITEM_OPT>
181::isLeaf() const
182-> bool
183{
184 return (m_numberAndFlags & FLAG_BITS_MASK) == LEAF_FLAG;
185}
186
187template<typename Index, bool USE_SINGLE_ITEM_OPT>
190-> std::size_t
191{
192 PH_ASSERT(!isLeaf());
193
194 return static_cast<std::size_t>(m_numberAndFlags >> NUM_FLAG_BITS);
195}
196
197template<typename Index, bool USE_SINGLE_ITEM_OPT>
200-> std::size_t
201{
202 PH_ASSERT(isLeaf());
203
204 return static_cast<std::size_t>(m_numberAndFlags >> NUM_FLAG_BITS);
205}
206
207template<typename Index, bool USE_SINGLE_ITEM_OPT>
210-> real
211{
212 PH_ASSERT(!isLeaf());
213
214 return u0_splitPos;
215}
216
217template<typename Index, bool USE_SINGLE_ITEM_OPT>
220-> std::size_t
221{
222 PH_ASSERT(!isLeaf());
223
224 return static_cast<std::size_t>(m_numberAndFlags & FLAG_BITS_MASK);
225}
226
227template<typename Index, bool USE_SINGLE_ITEM_OPT>
230-> std::size_t
231{
232 PH_ASSERT(isLeaf());
233 if constexpr(USE_SINGLE_ITEM_OPT)
234 {
235 PH_ASSERT(USE_SINGLE_ITEM_OPT && numItems() == 1);
236
237 return u0_itemBufferOffset;
238 }
239 else
240 {
241 PH_ASSERT_UNREACHABLE_SECTION();
242 return static_cast<std::size_t>(-1);
243 }
244}
245
246template<typename Index, bool USE_SINGLE_ITEM_OPT>
249-> std::size_t
250{
251 PH_ASSERT(isLeaf());
252 PH_ASSERT(!(USE_SINGLE_ITEM_OPT && numItems() == 1));
253
254 return u0_indexBufferOffset;
255}
256
257}// end namespace ph::math
An indexed kD-tree node with compacted memory layout.
Definition TIndexedKdtreeNode.h:23
static constexpr std::size_t MAX_NODE_ITEMS
Definition TIndexedKdtreeNode.h:39
static constexpr std::size_t MAX_BUFFER_OFFSET
Definition TIndexedKdtreeNode.h:47
bool isLeaf() const
Definition TIndexedKdtreeNode.h:181
std::size_t getSplitAxis() const
Definition TIndexedKdtreeNode.h:219
std::size_t getSingleItemDirectIndex() const
Definition TIndexedKdtreeNode.h:229
static TIndexedKdtreeNode makeInner(real splitPos, std::size_t splitAxisIndex, std::size_t positiveChildIndex)
Definition TIndexedKdtreeNode.h:105
std::size_t numItems() const
Definition TIndexedKdtreeNode.h:199
Index u0_itemBufferOffset
Definition TIndexedKdtreeNode.h:83
static TIndexedKdtreeNode makeLeaf(Index indexBufferOffset, std::size_t numItems)
Definition TIndexedKdtreeNode.h:128
Index u0_indexBufferOffset
Definition TIndexedKdtreeNode.h:82
std::size_t getIndexBufferOffset() const
Definition TIndexedKdtreeNode.h:248
std::size_t getPositiveChildIndex() const
Definition TIndexedKdtreeNode.h:189
real u0_splitPos
Definition TIndexedKdtreeNode.h:81
real getSplitPos() const
Definition TIndexedKdtreeNode.h:209
static constexpr std::size_t MAX_NODE_INDEX
Definition TIndexedKdtreeNode.h:42
constexpr std::size_t Y_AXIS
Definition constant.h:91
constexpr std::size_t Z_AXIS
Definition constant.h:92
constexpr std::size_t X_AXIS
Definition constant.h:90
Math functions and utilities.
Definition TransformInfo.h:10
std::span< const T, EXTENT > TSpanView
Same as TSpan, except that the objects are const-qualified. Note that for pointer types,...
Definition TSpan.h:19
Definition TAABB2D.h:96