MapperWireframer.cxx 12 KB
Newer Older
1 2 3 4 5 6 7 8
//============================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//
9
//  Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10 11 12
//  Copyright 2016 UT-Battelle, LLC.
//  Copyright 2016 Los Alamos National Security.
//
13
//  Under the terms of Contract DE-NA0003525 with NTESS,
14 15 16 17 18 19 20
//  the U.S. Government retains certain rights in this software.
//
//  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
//  Laboratory (LANL), the U.S. Government retains certain rights in
//  this software.
//============================================================================

Manish Mathai's avatar
Manish Mathai committed
21 22
#include <vtkm/Assert.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
23

Manish Mathai's avatar
Manish Mathai committed
24 25
#include <vtkm/cont/TryExecute.h>
#include <vtkm/exec/CellEdge.h>
26
#include <vtkm/filter/ExternalFaces.h>
Manish Mathai's avatar
Manish Mathai committed
27 28
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>
Manish Mathai's avatar
Manish Mathai committed
29 30
#include <vtkm/rendering/MapperWireframer.h>
#include <vtkm/rendering/Wireframer.h>
Manish Mathai's avatar
Manish Mathai committed
31 32 33 34 35
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/ScatterCounting.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
36 37 38 39 40

namespace vtkm
{
namespace rendering
{
Manish Mathai's avatar
Manish Mathai committed
41 42
namespace
{
43

44 45 46 47 48 49
class CreateConnectivity : public vtkm::worklet::WorkletMapField
{
public:
  VTKM_CONT
  CreateConnectivity() {}

50
  using ControlSignature = void(FieldIn, WholeArrayOut);
51

52
  using ExecutionSignature = void(_1, _2);
53 54 55 56 57 58 59 60 61

  template <typename ConnPortalType>
  VTKM_EXEC void operator()(const vtkm::Id& i, ConnPortalType& connPortal) const
  {
    connPortal.Set(i * 2 + 0, i);
    connPortal.Set(i * 2 + 1, i + 1);
  }
}; // conn

62 63 64
class Convert1DCoordinates : public vtkm::worklet::WorkletMapField
{
private:
65 66 67
  bool LogY;
  bool LogX;

68 69
public:
  VTKM_CONT
70 71 72 73 74
  Convert1DCoordinates(bool logY, bool logX)
    : LogY(logY)
    , LogX(logX)
  {
  }
75

76
  using ControlSignature = void(FieldIn, FieldIn, FieldOut, FieldOut);
77

78
  using ExecutionSignature = void(_1, _2, _3, _4);
79 80 81 82 83 84 85 86 87 88 89
  template <typename ScalarType>
  VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Float32, 3>& inCoord,
                            const ScalarType& scalar,
                            vtkm::Vec<vtkm::Float32, 3>& outCoord,
                            vtkm::Float32& fieldOut) const
  {
    //
    // Rendering supports lines based on a cellSetStructured<1>
    // where only the x coord matters. It creates a y based on
    // the scalar values and connects all the points with lines.
    // So, we need to convert it back to something that can
luz.paz's avatar
luz.paz committed
90
    // actually be rendered.
91 92 93 94
    //
    outCoord[0] = inCoord[0];
    outCoord[1] = static_cast<vtkm::Float32>(scalar);
    outCoord[2] = 0.f;
95 96 97 98 99 100 101 102
    if (LogY)
    {
      outCoord[1] = vtkm::Log10(outCoord[1]);
    }
    if (LogX)
    {
      outCoord[0] = vtkm::Log10(outCoord[0]);
    }
103 104 105 106 107
    // all lines have the same color
    fieldOut = 1.f;
  }
}; // convert coords

108 109 110 111
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
#endif
Manish Mathai's avatar
Manish Mathai committed
112
struct EdgesCounter : public vtkm::worklet::WorkletMapPointToCell
113
{
114
  using ControlSignature = void(CellSetIn cellSet, FieldOutCell numEdges);
115
  using ExecutionSignature = _2(CellShape shape, PointCount numPoints);
Manish Mathai's avatar
Manish Mathai committed
116
  using InputDomain = _1;
117

Manish Mathai's avatar
Manish Mathai committed
118 119 120
  template <typename CellShapeTag>
  VTKM_EXEC vtkm::IdComponent operator()(CellShapeTag shape, vtkm::IdComponent numPoints) const
  {
121
    //TODO: Remove the if/then with templates.
Manish Mathai's avatar
Manish Mathai committed
122 123 124 125 126 127 128 129
    if (shape.Id == vtkm::CELL_SHAPE_LINE)
    {
      return 1;
    }
    else
    {
      return vtkm::exec::CellEdgeNumberOfEdges(numPoints, shape, *this);
    }
Manish Mathai's avatar
Manish Mathai committed
130 131 132 133
  }
}; // struct EdgesCounter

struct EdgesExtracter : public vtkm::worklet::WorkletMapPointToCell
134
{
135
  using ControlSignature = void(CellSetIn cellSet, FieldOutCell edgeIndices);
136
  using ExecutionSignature = void(CellShape, PointIndices, VisitIndex, _2);
Manish Mathai's avatar
Manish Mathai committed
137 138
  using InputDomain = _1;
  using ScatterType = vtkm::worklet::ScatterCounting;
139

Manish Mathai's avatar
Manish Mathai committed
140
  VTKM_CONT
141 142
  template <typename CountArrayType>
  static ScatterType MakeScatter(const CountArrayType& counts)
Manish Mathai's avatar
Manish Mathai committed
143
  {
144
    return ScatterType(counts);
Manish Mathai's avatar
Manish Mathai committed
145 146 147 148 149 150 151 152
  }

  template <typename CellShapeTag, typename PointIndexVecType, typename EdgeIndexVecType>
  VTKM_EXEC void operator()(CellShapeTag shape,
                            const PointIndexVecType& pointIndices,
                            vtkm::IdComponent visitIndex,
                            EdgeIndexVecType& edgeIndices) const
  {
153
    //TODO: Remove the if/then with templates.
Manish Mathai's avatar
Manish Mathai committed
154 155 156 157 158 159 160 161
    vtkm::Id p1, p2;
    if (shape.Id == vtkm::CELL_SHAPE_LINE)
    {
      p1 = pointIndices[0];
      p2 = pointIndices[1];
    }
    else
    {
162 163 164 165
      p1 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
        pointIndices.GetNumberOfComponents(), 0, visitIndex, shape, *this)];
      p2 = pointIndices[vtkm::exec::CellEdgeLocalIndex(
        pointIndices.GetNumberOfComponents(), 1, visitIndex, shape, *this)];
Manish Mathai's avatar
Manish Mathai committed
166
    }
Manish Mathai's avatar
Manish Mathai committed
167 168 169 170 171
    // These indices need to be arranged in a definite order, as they will later be sorted to
    // detect duplicates
    edgeIndices[0] = p1 < p2 ? p1 : p2;
    edgeIndices[1] = p1 < p2 ? p2 : p1;
  }
Manish Mathai's avatar
Manish Mathai committed
172
}; // struct EdgesExtracter
Manish Mathai's avatar
Manish Mathai committed
173

174 175 176
#if defined(VTKM_MSVC)
#pragma warning(pop)
#endif
Manish Mathai's avatar
Manish Mathai committed
177 178
} // namespace

Manish Mathai's avatar
Manish Mathai committed
179
struct MapperWireframer::InternalsType
Manish Mathai's avatar
Manish Mathai committed
180 181
{
  InternalsType()
182
    : InternalsType(nullptr, false, false)
Manish Mathai's avatar
Manish Mathai committed
183 184 185
  {
  }

186
  InternalsType(vtkm::rendering::Canvas* canvas, bool showInternalZones, bool isOverlay)
Manish Mathai's avatar
Manish Mathai committed
187 188
    : Canvas(canvas)
    , ShowInternalZones(showInternalZones)
189
    , IsOverlay(isOverlay)
Matt Larsen's avatar
Matt Larsen committed
190
    , CompositeBackground(true)
191 192
  {
  }
Manish Mathai's avatar
Manish Mathai committed
193 194 195

  vtkm::rendering::Canvas* Canvas;
  bool ShowInternalZones;
196
  bool IsOverlay;
Matt Larsen's avatar
Matt Larsen committed
197
  bool CompositeBackground;
Manish Mathai's avatar
Manish Mathai committed
198
}; // struct MapperWireframer::InternalsType
Manish Mathai's avatar
Manish Mathai committed
199

Manish Mathai's avatar
Manish Mathai committed
200
MapperWireframer::MapperWireframer()
201
  : Internals(new InternalsType(nullptr, false, false))
Manish Mathai's avatar
Manish Mathai committed
202 203 204
{
}

Manish Mathai's avatar
Manish Mathai committed
205
MapperWireframer::~MapperWireframer()
Manish Mathai's avatar
Manish Mathai committed
206
{
207 208
}

Manish Mathai's avatar
Manish Mathai committed
209
vtkm::rendering::Canvas* MapperWireframer::GetCanvas() const
210
{
Manish Mathai's avatar
Manish Mathai committed
211
  return this->Internals->Canvas;
212 213
}

Manish Mathai's avatar
Manish Mathai committed
214
void MapperWireframer::SetCanvas(vtkm::rendering::Canvas* canvas)
215
{
Manish Mathai's avatar
Manish Mathai committed
216
  this->Internals->Canvas = canvas;
217 218
}

Manish Mathai's avatar
Manish Mathai committed
219
bool MapperWireframer::GetShowInternalZones() const
220
{
Manish Mathai's avatar
Manish Mathai committed
221 222 223
  return this->Internals->ShowInternalZones;
}

Manish Mathai's avatar
Manish Mathai committed
224
void MapperWireframer::SetShowInternalZones(bool showInternalZones)
Manish Mathai's avatar
Manish Mathai committed
225 226
{
  this->Internals->ShowInternalZones = showInternalZones;
227 228
}

229 230 231 232 233 234 235 236 237 238
bool MapperWireframer::GetIsOverlay() const
{
  return this->Internals->IsOverlay;
}

void MapperWireframer::SetIsOverlay(bool isOverlay)
{
  this->Internals->IsOverlay = isOverlay;
}

Manish Mathai's avatar
Manish Mathai committed
239
void MapperWireframer::StartScene()
240 241 242 243
{
  // Nothing needs to be done.
}

Manish Mathai's avatar
Manish Mathai committed
244
void MapperWireframer::EndScene()
245 246 247 248
{
  // Nothing needs to be done.
}

249
void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
Manish Mathai's avatar
Manish Mathai committed
250
                                   const vtkm::cont::CoordinateSystem& coords,
251
                                   const vtkm::cont::Field& inScalarField,
252
                                   const vtkm::cont::ColorTable& colorTable,
Manish Mathai's avatar
Manish Mathai committed
253 254
                                   const vtkm::rendering::Camera& camera,
                                   const vtkm::Range& scalarRange)
Manish Mathai's avatar
Manish Mathai committed
255
{
256
  vtkm::cont::DynamicCellSet cellSet = inCellSet;
257 258 259 260 261 262 263 264 265

  bool is1D = cellSet.IsSameType(vtkm::cont::CellSetStructured<1>());

  vtkm::cont::CoordinateSystem actualCoords = coords;
  vtkm::cont::Field actualField = inScalarField;

  if (is1D)
  {

266 267
    bool isSupportedField =
      inScalarField.GetAssociation() == vtkm::cont::Field::Association::POINTS;
268 269 270 271 272 273 274 275 276 277
    if (!isSupportedField)
    {
      throw vtkm::cont::ErrorBadValue(
        "WireFramer: field must be associated with points for 1D cell set");
    }
    vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> newCoords;
    vtkm::cont::ArrayHandle<vtkm::Float32> newScalars;
    //
    // Convert the cell set into something we can draw
    //
278 279
    vtkm::worklet::DispatcherMapField<Convert1DCoordinates>(
      Convert1DCoordinates(this->LogarithmY, this->LogarithmX))
280 281 282 283
      .Invoke(coords.GetData(),
              inScalarField.GetData().ResetTypes(vtkm::TypeListTagFieldScalar()),
              newCoords,
              newScalars);
284 285

    actualCoords = vtkm::cont::CoordinateSystem("coords", newCoords);
286 287
    actualField = vtkm::cont::Field(
      inScalarField.GetName(), vtkm::cont::Field::Association::POINTS, newScalars);
288

289 290
    vtkm::Id numCells = cellSet.GetNumberOfCells();
    vtkm::cont::ArrayHandle<vtkm::Id> conn;
291
    vtkm::cont::ArrayHandleCounting<vtkm::Id> iter =
Matt Larsen's avatar
Matt Larsen committed
292
      vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0), vtkm::Id(1), numCells);
293
    conn.Allocate(numCells * 2);
294
    vtkm::worklet::DispatcherMapField<CreateConnectivity>(CreateConnectivity()).Invoke(iter, conn);
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

    vtkm::cont::CellSetSingleType<> newCellSet("cells");
    newCellSet.Fill(newCoords.GetNumberOfValues(), vtkm::CELL_SHAPE_LINE, 2, conn);
    cellSet = vtkm::cont::DynamicCellSet(newCellSet);
  }
  bool isLines = false;
  // Check for a cell set that is already lines
  // Since there is no need to de external faces or
  // render the depth of the mesh to hide internal zones
  if (cellSet.IsSameType(vtkm::cont::CellSetSingleType<>()))
  {
    auto singleType = cellSet.Cast<vtkm::cont::CellSetSingleType<>>();
    isLines = singleType.GetCellShape(0) == vtkm::CELL_SHAPE_LINE;
  }

  bool doExternalFaces = !(this->Internals->ShowInternalZones) && !isLines && !is1D;
  if (doExternalFaces)
312
  {
313 314
    // If internal zones are to be hidden, the number of edges processed can be reduced by
    // running the external faces filter on the input cell set.
315
    vtkm::cont::DataSet dataSet;
316
    dataSet.AddCoordinateSystem(actualCoords);
317
    dataSet.AddCellSet(inCellSet);
318
    dataSet.AddField(inScalarField);
319 320 321
    vtkm::filter::ExternalFaces externalFaces;
    externalFaces.SetCompactPoints(false);
    externalFaces.SetPassPolyData(true);
322
    vtkm::cont::DataSet output = externalFaces.Execute(dataSet);
323 324
    cellSet = output.GetCellSet();
    actualField = output.GetField(0);
325 326 327
  }

  // Extract unique edges from the cell set.
328 329 330 331 332 333 334 335
  vtkm::cont::ArrayHandle<vtkm::IdComponent> counts;
  vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 2>> edgeIndices;
  vtkm::worklet::DispatcherMapTopology<EdgesCounter>().Invoke(cellSet, counts);
  vtkm::worklet::DispatcherMapTopology<EdgesExtracter> extractDispatcher(
    EdgesExtracter::MakeScatter(counts));
  extractDispatcher.Invoke(cellSet, edgeIndices);
  vtkm::cont::Algorithm::template Sort<vtkm::Id2>(edgeIndices);
  vtkm::cont::Algorithm::template Unique<vtkm::Id2>(edgeIndices);
Manish Mathai's avatar
Manish Mathai committed
336

337 338
  Wireframer renderer(
    this->Internals->Canvas, this->Internals->ShowInternalZones, this->Internals->IsOverlay);
339 340
  // Render the cell set using a raytracer, on a separate canvas, and use the generated depth
  // buffer, which represents the solid mesh, to avoid drawing on the internal zones
341 342 343
  bool renderDepth =
    !(this->Internals->ShowInternalZones) && !(this->Internals->IsOverlay) && !isLines && !is1D;
  if (renderDepth)
Manish Mathai's avatar
Manish Mathai committed
344 345 346
  {
    CanvasRayTracer canvas(this->Internals->Canvas->GetWidth(),
                           this->Internals->Canvas->GetHeight());
347
    canvas.SetBackgroundColor(vtkm::rendering::Color::white);
Manish Mathai's avatar
Manish Mathai committed
348 349 350
    canvas.Initialize();
    canvas.Activate();
    canvas.Clear();
Manish Mathai's avatar
Manish Mathai committed
351
    MapperRayTracer raytracer;
Manish Mathai's avatar
Manish Mathai committed
352 353
    raytracer.SetCanvas(&canvas);
    raytracer.SetActiveColorTable(colorTable);
354
    raytracer.RenderCells(cellSet, actualCoords, actualField, colorTable, camera, scalarRange);
Manish Mathai's avatar
Manish Mathai committed
355 356
    renderer.SetSolidDepthBuffer(canvas.GetDepthBuffer());
  }
357
  else
358 359 360
  {
    renderer.SetSolidDepthBuffer(this->Internals->Canvas->GetDepthBuffer());
  }
Manish Mathai's avatar
Manish Mathai committed
361 362 363

  renderer.SetCamera(camera);
  renderer.SetColorMap(this->ColorMap);
364
  renderer.SetData(actualCoords, edgeIndices, actualField, scalarRange);
Manish Mathai's avatar
Manish Mathai committed
365
  renderer.Render();
Matt Larsen's avatar
Matt Larsen committed
366 367 368 369 370 371 372 373 374 375

  if (this->Internals->CompositeBackground)
  {
    this->Internals->Canvas->BlendBackground();
  }
}

void MapperWireframer::SetCompositeBackground(bool on)
{
  this->Internals->CompositeBackground = on;
Manish Mathai's avatar
Manish Mathai committed
376 377
}

Manish Mathai's avatar
Manish Mathai committed
378
vtkm::rendering::Mapper* MapperWireframer::NewCopy() const
379
{
Manish Mathai's avatar
Manish Mathai committed
380
  return new vtkm::rendering::MapperWireframer(*this);
381 382
}
}
383
} // namespace vtkm::rendering