Blue Brain BioExplorer
VectorOctree.cpp
Go to the documentation of this file.
1 /*
2  *
3  * The Blue Brain BioExplorer is a tool for scientists to extract and analyse
4  * scientific data from visualization
5  *
6  * This file is part of Blue Brain BioExplorer <https://github.com/BlueBrain/BioExplorer>
7  *
8  * Copyright 2020-2024 Blue BrainProject / EPFL
9  *
10  * This program is free software: you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License as published by the Free Software
12  * Foundation, either version 3 of the License, or (at your option) any later
13  * version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program. If not, see <https://www.gnu.org/licenses/>.
22  */
23 
24 #include "VectorOctree.h"
25 
28 
29 namespace core
30 {
31 typedef std::map<uint32_t, VectorOctreeNode> VectorOctreeLevelMap;
32 
33 VectorOctree::VectorOctree(const OctreeVectors &vectors, double voxelSize, const Vector3d &minAABB,
34  const Vector3d &maxAABB)
35  : _volumeDimensions(Vector3ui(0u, 0u, 0u))
36  , _volumeSize(0u)
37 {
38  CORE_INFO("Nb of vectors : " << vectors.size());
39 
40  // **************** VectorOctree creations *******************
41  // *****************************************************
42  Vector3ui octreeSize(_pow2roundup(std::ceil((maxAABB.x - minAABB.x) / voxelSize)),
43  _pow2roundup(std::ceil((maxAABB.y - minAABB.y) / voxelSize)),
44  _pow2roundup(std::ceil((maxAABB.z - minAABB.z) / voxelSize)));
45 
46  // This octree is always cubic
47  _octreeSize = std::max(std::max(octreeSize.x, octreeSize.y), octreeSize.z);
48 
49  CORE_INFO("Vector Octree size : " << _octreeSize);
50 
51  _depth = std::log2(_octreeSize) + 1u;
52  std::vector<VectorOctreeLevelMap> octree(_depth);
53 
54  CORE_INFO("Vector Octree depth : " << _depth << " " << octree.size());
55 
56  if (_depth == 0)
57  return;
58 
59  for (uint32_t i = 0; i < vectors.size(); ++i)
60  {
61  CORE_PROGRESS("Bulding Vector Octree from vectors", i, vectors.size());
62  const uint32_t xpos = std::floor((vectors[i].position.x - minAABB.x) / voxelSize);
63  const uint32_t ypos = std::floor((vectors[i].position.y - minAABB.y) / voxelSize);
64  const uint32_t zpos = std::floor((vectors[i].position.z - minAABB.z) / voxelSize);
65  const Vector3d &value = vectors[i].direction;
66 
67  const uint32_t indexX = xpos;
68  const uint32_t indexY = ypos * (uint32_t)_octreeSize;
69  const uint32_t indexZ = zpos * (uint32_t)_octreeSize * (uint32_t)_octreeSize;
70 
71  auto it = octree[0].find(indexX + indexY + indexZ);
72  if (it == octree[0].end())
73  {
74  VectorOctreeNode *child = nullptr;
75  for (uint32_t level = 0; level < _depth; ++level)
76  {
77  bool newNode = false;
78  const uint32_t divisor = std::pow(2, level);
79  const Vector3f center(xpos, ypos, zpos);
80 
81  const uint32_t nBlock = _octreeSize / divisor;
82  const uint32_t index = std::floor(xpos / divisor) + nBlock * std::floor(ypos / divisor) +
83  nBlock * nBlock * std::floor(zpos / divisor);
84 
85  const double size = voxelSize * (level + 1u);
86 
87  if (octree[level].find(index) == octree[level].end())
88  {
89  octree[level].insert(VectorOctreeLevelMap::value_type(index, VectorOctreeNode(center, size)));
90  newNode = true;
91  }
92 
93  octree[level].at(index).addValue(value);
94 
95  if ((level > 0) && (child != nullptr))
96  octree[level].at(index).setChild(child);
97 
98  if (newNode)
99  child = &(octree[level].at(index));
100  else
101  child = nullptr;
102  }
103  }
104  else
105  {
106  for (uint32_t level = 0; level < _depth; ++level)
107  {
108  const uint32_t divisor = std::pow(2, level);
109  const uint32_t nBlock = _octreeSize / divisor;
110  const uint32_t index = std::floor(xpos / divisor) + nBlock * std::floor(ypos / divisor) +
111  nBlock * nBlock * std::floor(zpos / divisor);
112  octree[level].at(index).addValue(value);
113  }
114  }
115  }
116  for (uint32_t i = 0; i < octree.size(); ++i)
117  CORE_DEBUG("Number of leaves [" << i << "]: " << octree[i].size());
118 
119  // VectorOctree flattening
120  _offsetPerLevel.resize(_depth);
121  _offsetPerLevel[_depth - 1u] = 0;
122  uint32_t previousOffset = 0u;
123  for (uint32_t i = _depth - 1u; i > 0u; --i)
124  {
125  _offsetPerLevel[i - 1u] = previousOffset + octree[i].size();
126  previousOffset = _offsetPerLevel[i - 1u];
127  }
128 
129  uint32_t totalNodeNumber = 0;
130 
131  for (uint32_t i = 0; i < octree.size(); ++i)
132  totalNodeNumber += octree[i].size();
133 
134  // Needs to be initialized with zeros
135  _flatIndices.resize(totalNodeNumber * 2u, 0);
136  _flatData.resize(totalNodeNumber * FIELD_VECTOR_DATA_SIZE);
137 
138  // The root node
139  _flattenChildren(&(octree[_depth - 1u].at(0)), _depth - 1u);
140 
141  _volumeDimensions =
142  Vector3ui(std::ceil((maxAABB.x - minAABB.x) / voxelSize), std::ceil((maxAABB.y - minAABB.y) / voxelSize),
143  std::ceil((maxAABB.z - minAABB.z) / voxelSize));
144  _volumeSize = (uint32_t)_volumeDimensions.x * (uint32_t)_volumeDimensions.y * (uint32_t)_volumeDimensions.z;
145 }
146 
148 
149 void VectorOctree::_flattenChildren(VectorOctreeNode *node, uint32_t level)
150 {
151  const std::vector<VectorOctreeNode *> children = node->getChildren();
152  const auto &position = node->getCenter();
153  const auto &direction = node->getValue();
154  if ((children.empty()) || (level == 0))
155  {
156  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_X] = position.x;
157  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_Y] = position.y;
158  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_Z] = position.z;
159  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_X] = direction.x;
160  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_Y] = direction.y;
161  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_Z] = direction.z;
162 
163  _offsetPerLevel[level] += 1u;
164  return;
165  }
166  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_X] = position.x;
167  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_Y] = position.y;
168  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_POSITION_Z] = position.z;
169  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_X] = direction.x;
170  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_Y] = direction.y;
171  _flatData[_offsetPerLevel[level] * FIELD_VECTOR_DATA_SIZE + FIELD_VECTOR_OFFSET_DIRECTION_Z] = direction.z;
172 
173  _flatIndices[_offsetPerLevel[level] * 2u] = _offsetPerLevel[level - 1];
174  _flatIndices[_offsetPerLevel[level] * 2u + 1] = _offsetPerLevel[level - 1] + children.size() - 1u;
175  _offsetPerLevel[level] += 1u;
176 
177  for (VectorOctreeNode *child : children)
178  _flattenChildren(child, level - 1u);
179 }
180 } // namespace core
The VectorOctreeNode class implement a spherical node of the Octree acceleration structure used by th...
VectorOctree(const OctreeVectors &vectors, double voxelSize, const Vector3d &minAABB, const Vector3d &maxAABB)
Construct a new VectorOctree object.
~VectorOctree()
Destroy the VectorOctree object.
std::map< uint32_t, VectorOctreeNode > VectorOctreeLevelMap
glm::vec3 Vector3f
Definition: MathTypes.h:137
glm::vec< 3, uint32_t > Vector3ui
Definition: MathTypes.h:134
glm::vec< 3, double > Vector3d
Definition: MathTypes.h:143
std::vector< OctreeVector > OctreeVectors
Definition: Types.h:425
#define FIELD_VECTOR_OFFSET_DIRECTION_Y
Definition: CommonTypes.h:89
#define FIELD_VECTOR_OFFSET_DIRECTION_X
Definition: CommonTypes.h:88
#define FIELD_VECTOR_OFFSET_POSITION_Y
Definition: CommonTypes.h:86
#define FIELD_VECTOR_DATA_SIZE
Definition: CommonTypes.h:84
#define FIELD_VECTOR_OFFSET_POSITION_Z
Definition: CommonTypes.h:87
#define FIELD_VECTOR_OFFSET_DIRECTION_Z
Definition: CommonTypes.h:90
#define FIELD_VECTOR_OFFSET_POSITION_X
Definition: CommonTypes.h:85
#define CORE_DEBUG(__msg)
Definition: Logs.h:38
#define CORE_INFO(__msg)
Definition: Logs.h:33
#define CORE_PROGRESS(__msg, __progress, __maxValue)
Definition: Logs.h:47