VTK-m  2.0
MortonCodes.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_rendering_raytracing_MortonCodes_h
11 #define vtk_m_rendering_raytracing_MortonCodes_h
12 
13 #include <vtkm/VectorAnalysis.h>
14 
16 
19 
24 
25 namespace vtkm
26 {
27 namespace rendering
28 {
29 namespace raytracing
30 {
31 
32 
33 //Note: if this takes a long time. we could use a lookup table
34 //expands 10-bit unsigned int into 30 bits
36 {
37  x32 = (x32 | (x32 << 16)) & 0x030000FF;
38  x32 = (x32 | (x32 << 8)) & 0x0300F00F;
39  x32 = (x32 | (x32 << 4)) & 0x030C30C3;
40  x32 = (x32 | (x32 << 2)) & 0x09249249;
41  return x32;
42 }
43 
44 VTKM_EXEC inline vtkm::UInt64 ExpandBits64(vtkm::UInt32 x)
45 {
46  vtkm::UInt64 x64 = x & 0x1FFFFF;
47  x64 = (x64 | x64 << 32) & 0x1F00000000FFFF;
48  x64 = (x64 | x64 << 16) & 0x1F0000FF0000FF;
49  x64 = (x64 | x64 << 8) & 0x100F00F00F00F00F;
50  x64 = (x64 | x64 << 4) & 0x10c30c30c30c30c3;
51  x64 = (x64 | x64 << 2) & 0x1249249249249249;
52 
53  return x64;
54 }
55 
56 //Returns 30 bit morton code for coordinates for
57 //coordinates in the unit cude
59 {
60  //take the first 10 bits
61  x = vtkm::Min(vtkm::Max(x * 1024.0f, 0.0f), 1023.0f);
62  y = vtkm::Min(vtkm::Max(y * 1024.0f, 0.0f), 1023.0f);
63  z = vtkm::Min(vtkm::Max(z * 1024.0f, 0.0f), 1023.0f);
64  //expand the 10 bits to 30
68  //interleave coordinates
69  return (zz << 2 | yy << 1 | xx);
70 }
71 
72 //Returns 30 bit morton code for coordinates for
73 //coordinates in the unit cude
75 {
76  //take the first 21 bits
77  x = vtkm::Min(vtkm::Max(x * 2097152.0f, 0.0f), 2097151.0f);
78  y = vtkm::Min(vtkm::Max(y * 2097152.0f, 0.0f), 2097151.0f);
79  z = vtkm::Min(vtkm::Max(z * 2097152.0f, 0.0f), 2097151.0f);
80  //expand the 10 bits to 30
81  vtkm::UInt64 xx = ExpandBits64((vtkm::UInt32)x);
82  vtkm::UInt64 yy = ExpandBits64((vtkm::UInt32)y);
83  vtkm::UInt64 zz = ExpandBits64((vtkm::UInt32)z);
84  //interleave coordinates
85  return (zz << 2 | yy << 1 | xx);
86 }
87 
89 {
90 private:
91  // (1.f / dx),(1.f / dy), (1.f, / dz)
94 
95  VTKM_EXEC inline void Normalize(vtkm::Vec3f_32& point) const
96  {
97  point = (point - MinCoordinate) * InverseExtent;
98  }
99 
100  VTKM_EXEC inline void Sort4(vtkm::Id4& indices) const
101  {
102  if (indices[0] < indices[1])
103  {
104  vtkm::Id temp = indices[1];
105  indices[1] = indices[0];
106  indices[0] = temp;
107  }
108  if (indices[2] < indices[3])
109  {
110  vtkm::Id temp = indices[3];
111  indices[3] = indices[2];
112  indices[2] = temp;
113  }
114  if (indices[0] < indices[2])
115  {
116  vtkm::Id temp = indices[2];
117  indices[2] = indices[0];
118  indices[0] = temp;
119  }
120  if (indices[1] < indices[3])
121  {
122  vtkm::Id temp = indices[3];
123  indices[3] = indices[1];
124  indices[1] = temp;
125  }
126  if (indices[1] < indices[2])
127  {
128  vtkm::Id temp = indices[2];
129  indices[2] = indices[1];
130  indices[1] = temp;
131  }
132  }
133 
134 public:
135  VTKM_CONT
136  MortonCodeFace(const vtkm::Vec3f_32& inverseExtent, const vtkm::Vec3f_32& minCoordinate)
137  : InverseExtent(inverseExtent)
138  , MinCoordinate(minCoordinate)
139  {
140  }
141 
142  using ControlSignature =
143  void(CellSetIn cellset, WholeArrayIn, FieldInCell, WholeArrayOut, WholeArrayOut);
144 
145  using ExecutionSignature = void(CellShape, IncidentElementIndices, WorkIndex, _2, _3, _4, _5);
146 
147  template <typename CellShape,
148  typename CellNodeVecType,
149  typename PointPortalType,
150  typename MortonPortalType,
151  typename CellFaceIdsPortalType>
152  VTKM_EXEC inline void operator()(const CellShape& cellShape,
153  const CellNodeVecType& cellIndices,
154  const vtkm::Id& cellId,
155  const PointPortalType& points,
156  const vtkm::Id& offset,
157  MortonPortalType& mortonCodes,
158  CellFaceIdsPortalType& cellFaceIds) const
159  {
160  CellTables tables;
161  vtkm::Int32 faceCount;
162  vtkm::Int32 tableOffset;
163 
164  if (cellShape.Id == vtkm::CELL_SHAPE_TETRA)
165  {
166  faceCount = tables.FaceLookUp(1, 1);
167  tableOffset = tables.FaceLookUp(1, 0);
168  }
169  else if (cellShape.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
170  {
171  faceCount = tables.FaceLookUp(0, 1);
172  tableOffset = tables.FaceLookUp(0, 0);
173  }
174  else if (cellShape.Id == vtkm::CELL_SHAPE_WEDGE)
175  {
176  faceCount = tables.FaceLookUp(2, 1);
177  tableOffset = tables.FaceLookUp(2, 0);
178  }
179  else if (cellShape.Id == vtkm::CELL_SHAPE_PYRAMID)
180  {
181  faceCount = tables.FaceLookUp(3, 1);
182  tableOffset = tables.FaceLookUp(3, 0);
183  }
184  else
185  {
186  return;
187  }
188 
189  //calc the morton code at the center of each face
190  for (vtkm::Int32 i = 0; i < faceCount; ++i)
191  {
192  vtkm::Vec3f_32 center;
193  vtkm::UInt32 code;
194  vtkm::Id3 cellFace;
195  cellFace[0] = cellId;
196 
197  // We must be sure that this calculation is the same for all faces. If we didn't
198  // then it is possible for the same face to end up in multiple morton "buckets" due to
199  // the wonders of floating point math. This is bad. If we calculate in the same order
200  // for all faces, then at worst, two different faces can enter the same bucket, which
201  // we currently check for.
202  vtkm::Id4 faceIndices(-1);
203  //Number of indices this face has
204  const vtkm::Int32 indiceCount = tables.ShapesFaceList(tableOffset + i, 0);
205  for (vtkm::Int32 j = 1; j <= indiceCount; j++)
206  {
207  faceIndices[j - 1] = cellIndices[tables.ShapesFaceList(tableOffset + i, j)];
208  }
209  //sort the indices in descending order
210  Sort4(faceIndices);
211 
212  vtkm::Int32 count = 1;
213  BOUNDS_CHECK(points, faceIndices[0]);
214  center = points.Get(faceIndices[0]);
215  for (int idx = 1; idx < indiceCount; ++idx)
216  {
217  BOUNDS_CHECK(points, faceIndices[idx]);
218  center = center + points.Get(faceIndices[idx]);
219  count++;
220  }
221  //TODO: we could make this a recipical, but this is not a bottleneck.
222  center[0] = center[0] / vtkm::Float32(count);
223  center[1] = center[1] / vtkm::Float32(count);
224  center[2] = center[2] / vtkm::Float32(count);
225  Normalize(center);
226  code = Morton3D(center[0], center[1], center[2]);
227  BOUNDS_CHECK(mortonCodes, offset + i);
228  mortonCodes.Set(offset + i, code);
229  cellFace[1] = i;
230  cellFace[2] = -1; //Need to initialize this for the next step
231  BOUNDS_CHECK(cellFaceIds, offset + i);
232  cellFaceIds.Set(offset + i, cellFace);
233  }
234  }
235 }; // class MortonCodeFace
236 
238 {
239 private:
240  // (1.f / dx),(1.f / dy), (1.f, / dz)
243 
244 public:
245  VTKM_CONT
246  MortonCodeAABB(const vtkm::Vec3f_32& inverseExtent, const vtkm::Vec3f_32& minCoordinate)
247  : InverseExtent(inverseExtent)
248  , MinCoordinate(minCoordinate)
249  {
250  }
251 
253  using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7);
254  typedef _7 InputDomain;
255 
256  VTKM_EXEC
257  void operator()(const vtkm::Float32& xmin,
258  const vtkm::Float32& ymin,
259  const vtkm::Float32& zmin,
260  const vtkm::Float32& xmax,
261  const vtkm::Float32& ymax,
262  const vtkm::Float32& zmax,
263  vtkm::UInt32& mortonCode) const
264  {
265  vtkm::Vec3f_32 direction(xmax - xmin, ymax - ymin, zmax - zmin);
266  vtkm::Float32 halfDistance = sqrtf(vtkm::Dot(direction, direction)) * 0.5f;
267  vtkm::Normalize(direction);
268  vtkm::Float32 centroidx = xmin + halfDistance * direction[0] - MinCoordinate[0];
269  vtkm::Float32 centroidy = ymin + halfDistance * direction[1] - MinCoordinate[1];
270  vtkm::Float32 centroidz = zmin + halfDistance * direction[2] - MinCoordinate[2];
271  //normalize the centroid tp 10 bits
272  centroidx *= InverseExtent[0];
273  centroidy *= InverseExtent[1];
274  centroidz *= InverseExtent[2];
275  mortonCode = Morton3D(centroidx, centroidy, centroidz);
276  }
277 }; // class MortonCodeAABB
278 }
279 }
280 } //namespace vtkm::rendering::raytracing
281 #endif
vtkm::rendering::raytracing::CellTables::FaceLookUp
VTKM_EXEC vtkm::Int32 FaceLookUp(vtkm::Int32 x, vtkm::Int32 y) const
Definition: CellTables.h:48
vtkm::CELL_SHAPE_WEDGE
@ CELL_SHAPE_WEDGE
Definition: CellShape.h:49
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
WorkletMapField.h
vtkm::worklet::WorkletMapField::FieldOut
A control signature tag for output fields.
Definition: WorkletMapField.h:60
vtkm::Normalize
VTKM_EXEC_CONT void Normalize(T &x)
Changes a vector to be normal.
Definition: VectorAnalysis.h:168
vtkm::rendering::raytracing::MortonCodeFace::Sort4
VTKM_EXEC void Sort4(vtkm::Id4 &indices) const
Definition: MortonCodes.h:100
CellTables.h
vtkm::rendering::raytracing::MortonCodeFace::InverseExtent
vtkm::Vec3f_32 InverseExtent
Definition: MortonCodes.h:92
vtkm::rendering::raytracing::MortonCodeFace::operator()
VTKM_EXEC void operator()(const CellShape &cellShape, const CellNodeVecType &cellIndices, const vtkm::Id &cellId, const PointPortalType &points, const vtkm::Id &offset, MortonPortalType &mortonCodes, CellFaceIdsPortalType &cellFaceIds) const
Definition: MortonCodes.h:152
vtkm::rendering::raytracing::MortonCodeFace::ExecutionSignature
void(CellShape, IncidentElementIndices, WorkIndex, _2, _3, _4, _5) ExecutionSignature
Definition: MortonCodes.h:145
vtkm::rendering::raytracing::MortonCodeFace::MinCoordinate
vtkm::Vec3f_32 MinCoordinate
Definition: MortonCodes.h:93
DeviceAdapterAlgorithm.h
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
DispatcherMapField.h
vtkm::rendering::raytracing::MortonCodeAABB
Definition: MortonCodes.h:237
vtkm::rendering::raytracing::CellTables
Definition: CellTables.h:22
VectorAnalysis.h
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
vtkm::rendering::raytracing::MortonCodeAABB::InverseExtent
vtkm::Vec3f_32 InverseExtent
Definition: MortonCodes.h:241
vtkm::rendering::raytracing::MortonCodeAABB::ExecutionSignature
void(_1, _2, _3, _4, _5, _6, _7) ExecutionSignature
Definition: MortonCodes.h:253
vtkm::rendering::raytracing::MortonCodeAABB::MinCoordinate
vtkm::Vec3f_32 MinCoordinate
Definition: MortonCodes.h:242
vtkm::CELL_SHAPE_TETRA
@ CELL_SHAPE_TETRA
Definition: CellShape.h:46
vtkm::worklet::WorkletVisitCellsWithPoints
Base class for worklets that map from Points to Cells.
Definition: WorkletMapTopology.h:255
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::CELL_SHAPE_HEXAHEDRON
@ CELL_SHAPE_HEXAHEDRON
Definition: CellShape.h:48
vtkm::rendering::raytracing::ExpandBits64
VTKM_EXEC vtkm::UInt64 ExpandBits64(vtkm::UInt32 x)
Definition: MortonCodes.h:44
vtkm::rendering::raytracing::MortonCodeAABB::MortonCodeAABB
VTKM_CONT MortonCodeAABB(const vtkm::Vec3f_32 &inverseExtent, const vtkm::Vec3f_32 &minCoordinate)
Definition: MortonCodes.h:246
vtkm::rendering::raytracing::CellTables::ShapesFaceList
VTKM_EXEC vtkm::Int32 ShapesFaceList(vtkm::Int32 x, vtkm::Int32 y) const
Definition: CellTables.h:68
vtkm::rendering::raytracing::MortonCodeAABB::operator()
VTKM_EXEC void operator()(const vtkm::Float32 &xmin, const vtkm::Float32 &ymin, const vtkm::Float32 &zmin, const vtkm::Float32 &xmax, const vtkm::Float32 &ymax, const vtkm::Float32 &zmax, vtkm::UInt32 &mortonCode) const
Definition: MortonCodes.h:257
vtkm::rendering::raytracing::Morton3D
VTKM_EXEC vtkm::UInt32 Morton3D(vtkm::Float32 &x, vtkm::Float32 &y, vtkm::Float32 &z)
Definition: MortonCodes.h:58
BOUNDS_CHECK
#define BOUNDS_CHECK(HANDLE, INDEX)
Definition: RayTracingTypeDefs.h:31
vtkm::Vec< vtkm::Float32, 3 >
vtkm::UInt32
uint32_t UInt32
Definition: Types.h:161
vtkm::rendering::raytracing::MortonCodeAABB::ControlSignature
void(FieldIn, FieldIn, FieldIn, FieldIn, FieldIn, FieldIn, FieldOut) ControlSignature
Definition: MortonCodes.h:252
vtkm::Float32
float Float32
Definition: Types.h:154
vtkm::rendering::raytracing::Morton3D64
VTKM_EXEC vtkm::UInt64 Morton3D64(vtkm::Float32 &x, vtkm::Float32 &y, vtkm::Float32 &z)
Definition: MortonCodes.h:74
vtkm::Int32
int32_t Int32
Definition: Types.h:160
RayTracingTypeDefs.h
vtkm::rendering::raytracing::MortonCodeAABB::InputDomain
_7 InputDomain
Definition: MortonCodes.h:254
vtkm::rendering::raytracing::MortonCodeFace::ControlSignature
void(CellSetIn cellset, WholeArrayIn, FieldInCell, WholeArrayOut, WholeArrayOut) ControlSignature
Definition: MortonCodes.h:143
vtkm::CELL_SHAPE_PYRAMID
@ CELL_SHAPE_PYRAMID
Definition: CellShape.h:50
DispatcherMapTopology.h
WorkletMapTopology.h
vtkm::rendering::raytracing::MortonCodeFace
Definition: MortonCodes.h:88
vtkm::rendering::raytracing::ExpandBits32
VTKM_EXEC vtkm::UInt32 ExpandBits32(vtkm::UInt32 x32)
Definition: MortonCodes.h:35
vtkm::rendering::raytracing::MortonCodeFace::Normalize
VTKM_EXEC void Normalize(vtkm::Vec3f_32 &point) const
Definition: MortonCodes.h:95
vtkm::worklet::WorkletVisitCellsWithPoints::FieldInCell
FieldInVisit FieldInCell
Definition: WorkletMapTopology.h:261
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38
vtkm::rendering::raytracing::MortonCodeFace::MortonCodeFace
VTKM_CONT MortonCodeFace(const vtkm::Vec3f_32 &inverseExtent, const vtkm::Vec3f_32 &minCoordinate)
Definition: MortonCodes.h:136
vtkm::exec::arg::WorkIndex
The ExecutionSignature tag to use to get the work index.
Definition: WorkIndex.h:39