1 #ifndef MOBILERT_ACCELERATORS_REGULARGRID_HPP 2 #define MOBILERT_ACCELERATORS_REGULARGRID_HPP 30 ::std::vector<::std::vector<T*>>
grid_;
77 ::std::uint32_t
bitCounter(::std::uint32_t value)
const;
79 ::std::int32_t
getCellIndex(::std::int32_t cellX, ::std::int32_t cellY, ::std::int32_t cellZ)
const;
84 explicit RegularGrid(::std::vector<T> &&primitives, ::std::uint32_t gridSize);
114 ::std::vector<T> &&primitives, const ::std::uint32_t gridSize
117 ::std::vector<::std::vector<T*>> {
118 static_cast<::std::uint32_t
> (gridSize * gridSize * gridSize)
121 primitives_ {::std::move(primitives)},
122 gridSize_ {
static_cast<::std::int32_t
> (gridSize)},
123 gridShift_ {bitCounter(gridSize - 1U)},
124 worldBoundaries_ {Scene::getBounds<T> (primitives_)},
127 static_cast<float> (gridSize_) / (worldBoundaries_.getPointMax() - worldBoundaries_.getPointMin())[0],
128 static_cast<float> (gridSize_) / (worldBoundaries_.getPointMax() - worldBoundaries_.getPointMin())[1],
129 static_cast<float> (gridSize_) / (worldBoundaries_.getPointMax() - worldBoundaries_.getPointMin())[2]
132 cellSize_ {(worldBoundaries_.getPointMax() - worldBoundaries_.getPointMin()) * (1.0F / static_cast<float> (gridSize_))} {
134 LOG_INFO(
"Building RegularGrid for: ",
typeid(T).name());
135 const ::glm::vec3 worldBoundsMin {this->worldBoundaries_.getPointMin()};
136 const ::glm::vec3 worldBoundsMax {this->worldBoundaries_.getPointMax()};
138 worldBoundsMin[0],
", ",
139 worldBoundsMin[1],
", ",
140 worldBoundsMin[2],
") max=(",
141 worldBoundsMax[0],
", ",
142 worldBoundsMax[1],
", ",
143 worldBoundsMax[2],
")" 146 LOG_INFO(
"PRIMITIVES = ", this->primitives_.size());
162 ::std::vector<::std::vector<T*>> {}.swap(this->grid_);
189 LOG_INFO(
"Will add primitives to RegularGrid (",
typeid(T).name(),
")");
191 this->mutexes_ = ::std::vector<::std::mutex> (this->grid_.size());
194 LOG_INFO(
"Adding primitives to RegularGrid (",
typeid(T).name(),
") (mutexes: ", this->mutexes_.size(),
" [", this->mutexes_.capacity(),
", ", this->mutexes_.max_size(),
"])");
195 const ::std::uint32_t numChildren {::std::thread::hardware_concurrency()};
196 if (numChildren <= 0) {
197 LOG_ERROR(
"Number of available CPU cores is ", numChildren);
200 ::std::vector<::std::thread> threads {};
201 threads.reserve(numChildren);
202 LOG_INFO(
"Created mutexes and it will fill the Regular Grid using ", numChildren + 1,
" threads");
203 for (::std::uint32_t i {}; i < numChildren; ++i) {
204 threads.emplace_back(&RegularGrid::addPrimitivesThreadWork,
this, i, numChildren + 1);
206 addPrimitivesThreadWork(numChildren, numChildren + 1);
207 for (::std::thread &thread : threads) {
211 LOG_INFO(
"Added primitives to RegularGrid (",
typeid(T).name(),
")");
217 const ::glm::vec3 worldBoundsMin {this->worldBoundaries_.getPointMin()};
218 const ::glm::vec3 worldBoundsMax {this->worldBoundaries_.getPointMax()};
221 const ::glm::vec3 size {worldBoundsMax - worldBoundsMin};
222 const float dx {size[0] / this->gridSize_};
223 const float dy {size[1] / this->gridSize_};
224 const float dz {size[2] / this->gridSize_};
225 const float dxReci {dx > 0 ? 1.0F / dx : 1.0F};
226 const float dyReci {dy > 0 ? 1.0F / dy : 1.0F};
227 const float dzReci {dz > 0 ? 1.0F / dz : 1.0F};
228 const ::std::uint32_t numPrimitives {
static_cast<::std::uint32_t
> (this->primitives_.size())};
230 for (::std::int32_t index {
static_cast<::std::int32_t
>(threadId)}; index < static_cast<::std::int32_t> (numPrimitives); index +=
static_cast<::std::int32_t
>(numberOfThreads)) {
233 T &primitive {this->primitives_[
static_cast<::std::uint32_t
> (index)]};
234 const AABB bound {primitive.getAABB()};
236 const ::glm::vec3 &bv2 {bound.getPointMax()};
239 ::std::int32_t x1 {
static_cast<::std::int32_t
> ((bv1[0] - worldBoundsMin[0]) * dxReci)};
240 ::std::int32_t x2 {
static_cast<::std::int32_t
> ((bv2[0] - worldBoundsMin[0]) * dxReci) + 1};
241 x1 = ::std::max(0, x1);
242 x2 = ::std::min(x2, this->gridSize_ - 1);
243 x2 = ::std::fabs(size[0]) < ::std::numeric_limits<float>::epsilon()? 0 : x2;
244 x1 = ::std::min(x1, x2);
245 ::std::int32_t y1 {
static_cast<::std::int32_t
> ((bv1[1] - worldBoundsMin[1]) * dyReci)};
246 ::std::int32_t y2 {
static_cast<::std::int32_t
> ((bv2[1] - worldBoundsMin[1]) * dyReci) + 1};
247 y1 = ::std::max(0, y1);
248 y2 = ::std::min(y2, this->gridSize_ - 1);
249 y2 = ::std::fabs(size[1]) < ::std::numeric_limits<float>::epsilon()? 0 : y2;
250 y1 = ::std::min(y1, y2);
251 ::std::int32_t z1 {
static_cast<::std::int32_t
> ((bv1[2] - worldBoundsMin[2]) * dzReci)};
252 ::std::int32_t z2 {
static_cast<::std::int32_t
> ((bv2[2] - worldBoundsMin[2]) * dzReci) + 1};
253 z1 = ::std::max(0, z1);
254 z2 = ::std::min(z2, this->gridSize_ - 1);
255 z2 = ::std::fabs(size[2]) < ::std::numeric_limits<float>::epsilon()? 0 : z2;
256 z1 = ::std::min(z1, z2);
259 for (::std::int32_t x {x1}; x <= x2; ++x) {
260 for (::std::int32_t y {y1}; y <= y2; ++y) {
261 for (::std::int32_t z {z1}; z <= z2; ++z) {
263 const ::std::uint32_t idx {
static_cast<::std::uint32_t
> (
265 y * this->gridSize_ +
266 z * this->gridSize_ * this->gridSize_
268 const ::glm::vec3 &pos {
269 worldBoundsMin[0] +
static_cast<float>(x) * dx,
270 worldBoundsMin[1] + static_cast<float>(y) * dy,
271 worldBoundsMin[2] +
static_cast<float>(z) * dz
273 const AABB cell {pos, pos + ::glm::vec3 {dx, dy, dz}};
275 const bool intersectedBox {primitive.
intersect(cell)};
276 if (intersectedBox) {
278 const ::std::lock_guard<::std::mutex> lock {this->mutexes_[idx]};
279 this->grid_[idx].emplace_back(&primitive);
288 LOG_INFO(
"Added '", numPrimitives,
"' primitives to RegularGrid ",
typeid(T).name(),
": (", dx,
", ", dy,
", ", dz,
")");
301 intersection = intersect (intersection);
316 intersection = intersect (intersection);
334 const ::glm::vec3 &worldBoundsMin {this->worldBoundaries_.getPointMin()};
337 const ::glm::vec3 &cell {(intersection.
ray_.
origin_ - worldBoundsMin) * this->cellSizeInverted_};
338 ::std::int32_t cellX {
static_cast<::std::int32_t
> (cell[0])};
339 ::std::int32_t cellY {
static_cast<::std::int32_t
> (cell[1])};
340 ::std::int32_t cellZ {
static_cast<::std::int32_t
> (cell[2])};
342 cellX = ::std::min(cellX, this->gridSize_ - 1);
343 cellX = ::std::max(cellX, 0);
344 cellY = ::std::min(cellY, this->gridSize_ - 1);
345 cellY = ::std::max(cellY, 0);
346 cellZ = ::std::min(cellZ, this->gridSize_ - 1);
347 cellZ = ::std::max(cellZ, 0);
349 ::std::int32_t stepX {}, outX {};
350 ::std::int32_t stepY {}, outY {};
351 ::std::int32_t stepZ {}, outZ {};
355 outX = this->gridSize_;
356 cb[0] = (worldBoundsMin[0] + (
static_cast<float> (cellX) + 1.0F) * this->cellSize_[0]);
360 cb[0] = (worldBoundsMin[0] +
static_cast<float> (cellX) * this->cellSize_[0]);
365 outY = this->gridSize_;
366 cb[1] = (worldBoundsMin[1] + (
static_cast<float> (cellY) + 1.0F) * this->cellSize_[1]);
370 cb[1] = (worldBoundsMin[1] +
static_cast<float> (cellY) * this->cellSize_[1]);
375 outZ = this->gridSize_;
376 cb[2] = (worldBoundsMin[2] + (
static_cast<float> (cellZ) + 1.0F) * this->cellSize_[2]);
380 cb[2] = (worldBoundsMin[2] +
static_cast<float> (cellZ) * this->cellSize_[2]);
383 ::glm::vec3 tmax {}, tdelta {};
384 if (::std::fabs(intersection.
ray_.
direction_[0]) > ::std::numeric_limits<float>::epsilon()) {
386 tmax[0] = ((cb[0] - intersection.
ray_.
origin_[0]) * rxr);
387 tdelta[0] = (this->cellSize_[0] *
static_cast<float> (stepX) * rxr);
392 if (::std::fabs(intersection.
ray_.
direction_[1]) > ::std::numeric_limits<float>::epsilon()) {
394 tmax[1] = ((cb[1] - intersection.
ray_.
origin_[1]) * ryr);
395 tdelta[1] = (this->cellSize_[1] *
static_cast<float> (stepY) * ryr);
400 if (::std::fabs(intersection.
ray_.
direction_[2]) > ::std::numeric_limits<float>::epsilon()) {
402 tmax[2] = ((cb[2] - intersection.
ray_.
origin_[2]) * rzr);
403 tdelta[2] = (this->cellSize_[2] *
static_cast<float> (stepZ) * rzr);
413 const ::std::int32_t index {getCellIndex(cellX, cellY, cellZ)};
414 const auto itPrimitives {this->grid_.begin() + index};
415 ::std::vector<T*> primitivesList {*itPrimitives};
418 for (T *
const primitive : primitivesList) {
419 const float lastDist {intersection.
length_};
420 intersection = primitive->intersect(intersection);
421 if (intersection.
length_ < lastDist) {
429 if (tmax[0] < tmax[1]) {
430 if (tmax[0] < tmax[2]) {
435 tmax[0] = (tmax[0] + tdelta[0]);
441 tmax[2] = (tmax[2] + tdelta[2]);
444 if (tmax[1] < tmax[2]) {
449 tmax[1] = (tmax[1] + tdelta[1]);
455 tmax[2] = (tmax[2] + tdelta[2]);
464 const ::std::int32_t index {getCellIndex(cellX, cellY, cellZ)};
465 const auto itPrimitives {this->grid_.begin() + index};
466 ::std::vector<T*> primitivesList {*itPrimitives};
469 for (T *
const primitive : primitivesList) {
470 intersection = primitive->intersect(intersection);
472 if (tmax[0] < tmax[1]) {
473 if (tmax[0] < tmax[2]) {
474 if (intersection.
length_ < tmax[0]) {
481 tmax[0] = (tmax[0] + tdelta[0]);
483 if (intersection.
length_ < tmax[2]) {
490 tmax[2] = (tmax[2] + tdelta[2]);
493 if (tmax[1] < tmax[2]) {
494 if (intersection.
length_ < tmax[1]) {
501 tmax[1] = (tmax[1] + tdelta[1]);
503 if (intersection.
length_ < tmax[2]) {
510 tmax[2] = (tmax[2] + tdelta[2]);
527 const ::std::int32_t cellX,
528 const ::std::int32_t cellY,
529 const ::std::int32_t cellZ)
const {
530 const ::std::int32_t index {
531 static_cast<::std::int32_t
> (
532 static_cast<::std::uint32_t
> (cellX) +
533 (static_cast<::std::uint32_t> (cellY) << (this->gridShift_)) +
534 (
static_cast<::std::uint32_t
> (cellZ) << (this->gridShift_ * 2U))
548 return this->primitives_;
553 #endif //MOBILERT_ACCELERATORS_REGULARGRID_HPP ::glm::vec3 cellSizeInverted_
Definition: RegularGrid.hpp:55
void addPrimitivesThreadWork(::std::uint32_t threadId, ::std::uint32_t numberOfThreads)
Definition: RegularGrid.hpp:216
::std::uint32_t gridShift_
Definition: RegularGrid.hpp:45
::std::int32_t gridSize_
Definition: RegularGrid.hpp:40
const float RayLengthMax
Definition: Constants.hpp:33
void checkSystemError(const char *const message)
Definition: Utils.cpp:237
::glm::vec3 cellSize_
Definition: RegularGrid.hpp:60
Ray ray_
Definition: Intersection.hpp:27
Intersection intersect(Intersection intersection)
Definition: RegularGrid.hpp:333
::glm::vec3 origin_
Definition: Ray.hpp:19
RegularGrid & operator=(const RegularGrid ®ularGrid)=delete
Intersection trace(Intersection intersection)
Definition: RegularGrid.hpp:300
Definition: RegularGrid.hpp:24
#define LOG_INFO(...)
Definition: Utils.hpp:43
::glm::vec3 direction_
Definition: Ray.hpp:24
float length_
Definition: Intersection.hpp:19
bool intersect(const Ray &ray) const
Definition: AABB.cpp:34
#define LOG_ERROR(...)
Definition: Utils.hpp:53
Definition: Intersection.hpp:14
void addPrimitives()
Definition: RegularGrid.hpp:188
~RegularGrid()
Definition: RegularGrid.hpp:160
const ::std::vector< T > & getPrimitives() const
Definition: RegularGrid.hpp:547
::std::atomic<::std::uint64_t > counter
Definition: Ray.cpp:11
::std::string to_string(const T &str)
Definition: Utils.hpp:378
::std::vector<::std::mutex > mutexes_
Definition: RegularGrid.hpp:65
::std::vector< T > primitives_
Definition: RegularGrid.hpp:35
::std::vector<::std::vector< T * > > grid_
Definition: RegularGrid.hpp:30
AABB worldBoundaries_
Definition: RegularGrid.hpp:50
::std::uint32_t bitCounter(::std::uint32_t value) const
Definition: RegularGrid.hpp:173
::std::int32_t getCellIndex(::std::int32_t cellX, ::std::int32_t cellY, ::std::int32_t cellZ) const
Definition: RegularGrid.hpp:526
bool shadowTrace_
Definition: Ray.hpp:45
Intersection shadowTrace(Intersection intersection)
Definition: RegularGrid.hpp:315
::glm::vec3 getPointMin() const
Definition: AABB.cpp:92