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_Quadralizer_h 11 #define vtk_m_rendering_Quadralizer_h 12 13 #include <typeinfo> 14 #include <vtkm/cont/Algorithm.h> 15 #include <vtkm/cont/ArrayHandleCounting.h> 16 #include <vtkm/cont/CellSetPermutation.h> 17 #include <vtkm/cont/DataSet.h> 18 #include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h> 19 #include <vtkm/worklet/DispatcherMapTopology.h> 20 #include <vtkm/worklet/WorkletMapField.h> 21 #include <vtkm/worklet/WorkletMapTopology.h> 22 23 24 #define QUAD_PER_CSS 6 25 26 namespace vtkm 27 { 28 namespace rendering 29 { 30 31 class Quadralizer 32 { 33 public: 34 class CountQuads : public vtkm::worklet::WorkletVisitCellsWithPoints 35 { 36 public: 37 VTKM_CONT CountQuads()38 CountQuads() {} 39 typedef void ControlSignature(CellSetIn cellset, FieldOut); 40 typedef void ExecutionSignature(CellShape, _2); 41 42 VTKM_EXEC operator()43 void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& quads) const 44 { 45 if (shapeType.Id == vtkm::CELL_SHAPE_QUAD) 46 quads = 1; 47 else if (shapeType.Id == CELL_SHAPE_HEXAHEDRON) 48 quads = 6; 49 else if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE) 50 quads = 3; 51 else if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID) 52 quads = 1; 53 54 else 55 quads = 0; 56 } 57 58 VTKM_EXEC operator()59 void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& quads) const 60 { 61 quads = 6; 62 } 63 64 VTKM_EXEC operator()65 void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& quads) const 66 { 67 if (shapeType.Id == vtkm::CELL_SHAPE_QUAD) 68 quads = 1; 69 else 70 quads = 0; 71 } 72 VTKM_EXEC operator()73 void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& quads) const 74 { 75 quads = 3; 76 } 77 }; //class CountQuads 78 79 template <int DIM> 80 class SegmentedStructured : public vtkm::worklet::WorkletVisitCellsWithPoints 81 { 82 83 public: 84 typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut); 85 typedef void ExecutionSignature(IncidentElementIndices, _2, _3); 86 //typedef _1 InputDomain; 87 VTKM_CONT SegmentedStructured()88 SegmentedStructured() {} 89 90 #if defined(VTKM_MSVC) 91 #pragma warning(push) 92 #pragma warning(disable : 4127) //conditional expression is constant 93 #endif 94 template <typename CellNodeVecType, typename OutIndicesPortal> cell2quad(vtkm::Id4 idx,vtkm::Vec<Id,5> & quad,const vtkm::Id offset,const CellNodeVecType & cellIndices,OutIndicesPortal & outputIndices)95 VTKM_EXEC void cell2quad(vtkm::Id4 idx, 96 vtkm::Vec<Id, 5>& quad, 97 const vtkm::Id offset, 98 const CellNodeVecType& cellIndices, 99 OutIndicesPortal& outputIndices) const 100 { 101 102 quad[1] = cellIndices[vtkm::IdComponent(idx[0])]; 103 quad[2] = cellIndices[vtkm::IdComponent(idx[1])]; 104 quad[3] = cellIndices[vtkm::IdComponent(idx[2])]; 105 quad[4] = cellIndices[vtkm::IdComponent(idx[3])]; 106 outputIndices.Set(offset, quad); 107 } 108 109 template <typename CellNodeVecType, typename OutIndicesPortal> operator()110 VTKM_EXEC void operator()(const CellNodeVecType& cellIndices, 111 const vtkm::Id& cellIndex, 112 OutIndicesPortal& outputIndices) const 113 { 114 if (DIM == 2) 115 { 116 outputIndices.Set( 117 cellIndex, { cellIndex, cellIndices[0], cellIndices[1], cellIndices[2], cellIndices[3] }); 118 } 119 else if (DIM == 3) 120 { 121 vtkm::Id offset = cellIndex * QUAD_PER_CSS; 122 vtkm::Vec<vtkm::Id, 5> quad; 123 quad[0] = cellIndex; 124 vtkm::Id4 idx; 125 idx[0] = 0; 126 idx[1] = 1; 127 idx[2] = 5; 128 idx[3] = 4; 129 cell2quad(idx, quad, offset, cellIndices, outputIndices); 130 131 idx[0] = 1; 132 idx[1] = 2; 133 idx[2] = 6; 134 idx[3] = 5; 135 offset++; 136 cell2quad(idx, quad, offset, cellIndices, outputIndices); 137 138 idx[0] = 3; 139 idx[1] = 7; 140 idx[2] = 6; 141 idx[3] = 2; 142 offset++; 143 cell2quad(idx, quad, offset, cellIndices, outputIndices); 144 145 idx[0] = 0; 146 idx[1] = 4; 147 idx[2] = 7; 148 idx[3] = 3; 149 offset++; 150 cell2quad(idx, quad, offset, cellIndices, outputIndices); 151 152 idx[0] = 0; 153 idx[1] = 3; 154 idx[2] = 2; 155 idx[3] = 1; 156 offset++; 157 cell2quad(idx, quad, offset, cellIndices, outputIndices); 158 159 idx[0] = 4; 160 idx[1] = 5; 161 idx[2] = 6; 162 idx[3] = 7; 163 offset++; 164 cell2quad(idx, quad, offset, cellIndices, outputIndices); 165 } 166 } 167 #if defined(VTKM_MSVC) 168 #pragma warning(pop) 169 #endif 170 }; 171 172 173 class Quadralize : public vtkm::worklet::WorkletVisitCellsWithPoints 174 { 175 176 public: 177 VTKM_CONT Quadralize()178 Quadralize() {} 179 typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut); 180 typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3); 181 182 template <typename VecType, typename OutputPortal> cell2quad(vtkm::Id & offset,const VecType & cellIndices,const vtkm::Id & cellId,const vtkm::Id Id0,const vtkm::Id Id1,const vtkm::Id Id2,const vtkm::Id Id3,OutputPortal & outputIndices)183 VTKM_EXEC void cell2quad(vtkm::Id& offset, 184 const VecType& cellIndices, 185 const vtkm::Id& cellId, 186 const vtkm::Id Id0, 187 const vtkm::Id Id1, 188 const vtkm::Id Id2, 189 const vtkm::Id Id3, 190 OutputPortal& outputIndices) const 191 { 192 vtkm::Vec<vtkm::Id, 5> quad; 193 quad[0] = cellId; 194 quad[1] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id0)]); 195 quad[2] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id1)]); 196 quad[3] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id2)]); 197 quad[4] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id3)]); 198 outputIndices.Set(offset++, quad); 199 } 200 201 template <typename VecType, typename OutputPortal> operator()202 VTKM_EXEC void operator()(const vtkm::Id& pointOffset, 203 vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), 204 const VecType& cellIndices, 205 const vtkm::Id& cellId, 206 OutputPortal& outputIndices) const 207 { 208 vtkm::Id offset = pointOffset; 209 210 cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices); 211 cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices); 212 cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices); 213 } 214 template <typename VecType, typename OutputPortal> operator()215 VTKM_EXEC void operator()(const vtkm::Id& offset, 216 vtkm::CellShapeTagQuad shapeType, 217 const VecType& cellIndices, 218 const vtkm::Id& cellId, 219 OutputPortal& outputIndices) const 220 { 221 if (shapeType.Id == vtkm::CELL_SHAPE_QUAD) 222 { 223 vtkm::Vec<vtkm::Id, 5> quad; 224 quad[0] = cellId; 225 quad[1] = static_cast<vtkm::Id>(cellIndices[0]); 226 quad[2] = static_cast<vtkm::Id>(cellIndices[1]); 227 quad[3] = static_cast<vtkm::Id>(cellIndices[2]); 228 quad[4] = static_cast<vtkm::Id>(cellIndices[3]); 229 outputIndices.Set(offset, quad); 230 } 231 } 232 233 template <typename VecType, typename OutputPortal> operator()234 VTKM_EXEC void operator()(const vtkm::Id& pointOffset, 235 vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), 236 const VecType& cellIndices, 237 const vtkm::Id& cellId, 238 OutputPortal& outputIndices) const 239 240 { 241 vtkm::Id offset = pointOffset; 242 cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices); 243 cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices); 244 cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices); 245 cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices); 246 cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices); 247 cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices); 248 } 249 250 template <typename VecType, typename OutputPortal> operator()251 VTKM_EXEC void operator()(const vtkm::Id& pointOffset, 252 vtkm::CellShapeTagGeneric shapeType, 253 const VecType& cellIndices, 254 const vtkm::Id& cellId, 255 OutputPortal& outputIndices) const 256 { 257 258 if (shapeType.Id == vtkm::CELL_SHAPE_QUAD) 259 { 260 vtkm::Vec<vtkm::Id, 5> quad; 261 quad[0] = cellId; 262 quad[1] = cellIndices[0]; 263 quad[2] = cellIndices[1]; 264 quad[3] = cellIndices[2]; 265 quad[4] = cellIndices[3]; 266 outputIndices.Set(pointOffset, quad); 267 } 268 if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON) 269 { 270 vtkm::Id offset = pointOffset; 271 cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices); 272 cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices); 273 cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices); 274 cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices); 275 cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices); 276 cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices); 277 } 278 if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE) 279 { 280 vtkm::Id offset = pointOffset; 281 282 cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices); 283 cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices); 284 cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices); 285 } 286 if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID) 287 { 288 vtkm::Id offset = pointOffset; 289 290 cell2quad(offset, cellIndices, cellId, 3, 2, 1, 0, outputIndices); 291 } 292 } 293 294 }; //class Quadralize 295 296 public: 297 VTKM_CONT Quadralizer()298 Quadralizer() {} 299 300 VTKM_CONT Run(const vtkm::cont::DynamicCellSet & cellset,vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id,5>> & outputIndices,vtkm::Id & output)301 void Run(const vtkm::cont::DynamicCellSet& cellset, 302 vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>>& outputIndices, 303 vtkm::Id& output) 304 { 305 vtkm::cont::Invoker invoke; 306 307 if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>())) 308 { 309 vtkm::cont::CellSetStructured<3> cellSetStructured3D = 310 cellset.Cast<vtkm::cont::CellSetStructured<3>>(); 311 const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells(); 312 313 vtkm::cont::ArrayHandleIndex cellIdxs(numCells); 314 outputIndices.Allocate(numCells * QUAD_PER_CSS); 315 invoke(SegmentedStructured<3>{}, cellSetStructured3D, cellIdxs, outputIndices); 316 317 output = numCells * QUAD_PER_CSS; 318 } 319 else if (cellset.IsSameType(vtkm::cont::CellSetStructured<2>())) 320 { 321 vtkm::cont::CellSetStructured<2> cellSetStructured2D = 322 cellset.Cast<vtkm::cont::CellSetStructured<2>>(); 323 const vtkm::Id numCells = cellSetStructured2D.GetNumberOfCells(); 324 325 vtkm::cont::ArrayHandleIndex cellIdxs(numCells); 326 outputIndices.Allocate(numCells); 327 invoke(SegmentedStructured<2>{}, cellSetStructured2D, cellIdxs, outputIndices); 328 329 output = numCells; 330 } 331 else 332 { 333 auto cellSetUnstructured = 334 cellset.ResetCellSetList(VTKM_DEFAULT_CELL_SET_LIST_UNSTRUCTURED{}); 335 vtkm::cont::ArrayHandle<vtkm::Id> quadsPerCell; 336 invoke(CountQuads{}, cellSetUnstructured, quadsPerCell); 337 338 vtkm::Id total = 0; 339 total = vtkm::cont::Algorithm::Reduce(quadsPerCell, vtkm::Id(0)); 340 341 vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets; 342 vtkm::cont::Algorithm::ScanExclusive(quadsPerCell, cellOffsets); 343 outputIndices.Allocate(total); 344 345 invoke(Quadralize{}, cellSetUnstructured, cellOffsets, outputIndices); 346 347 output = total; 348 } 349 } 350 }; 351 } 352 } 353 #endif 354