adding more ray tracing files

This commit is contained in:
mclarsen 2018-09-10 19:51:45 -07:00
parent 1c2f78ca92
commit 6362978ab2
28 changed files with 5567 additions and 0 deletions

@ -0,0 +1,442 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_Cylinderizer_h
#define vtk_m_rendering_Cylinderizer_h
#include <typeinfo>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#define SEG_PER_TRI 3
//CSS is CellSetStructured
#define TRI_PER_CSS 12
namespace vtkm
{
namespace rendering
{
class Cylinderizer
{
public:
class CountSegments : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
CountSegments() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut<>);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& segments) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_LINE)
segments = 1;
else if (shapeType.Id == vtkm::CELL_SHAPE_TRIANGLE)
segments = 3;
else if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
segments = 4;
else if (shapeType.Id == vtkm::CELL_SHAPE_TETRA)
segments = 12;
else if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
segments = 24;
else if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
segments = 18;
else if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
segments = 36;
else
segments = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& segments) const
{
segments = 36;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& segments) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
segments = 4;
else
segments = 0;
}
}; //class CountSegments
template <int DIM>
class SegmentedStructured : public vtkm::worklet::WorkletMapPointToCell
{
public:
typedef void ControlSignature(CellSetIn cellset, FieldInTo<>, WholeArrayOut<>);
typedef void ExecutionSignature(FromIndices, _2, _3);
//typedef _1 InputDomain;
VTKM_CONT
SegmentedStructured() {}
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
#endif
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void cell2seg(vtkm::Id3 idx,
vtkm::Vec<Id, 3>& segment,
const vtkm::Id offset,
const CellNodeVecType& cellIndices,
OutIndicesPortal& outputIndices) const
{
segment[1] = cellIndices[vtkm::IdComponent(idx[0])];
segment[2] = cellIndices[vtkm::IdComponent(idx[1])];
outputIndices.Set(offset, segment);
segment[1] = cellIndices[vtkm::IdComponent(idx[1])];
segment[2] = cellIndices[vtkm::IdComponent(idx[2])];
outputIndices.Set(offset + 1, segment);
segment[1] = cellIndices[vtkm::IdComponent(idx[2])];
segment[2] = cellIndices[vtkm::IdComponent(idx[0])];
outputIndices.Set(offset + 2, segment);
}
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void operator()(const CellNodeVecType& cellIndices,
const vtkm::Id& cellIndex,
OutIndicesPortal& outputIndices) const
{
if (DIM == 2)
{
// Do nothing mark says
}
else if (DIM == 3)
{
vtkm::Id offset = cellIndex * TRI_PER_CSS * SEG_PER_TRI;
vtkm::Vec<vtkm::Id, 3> segment;
segment[0] = cellIndex;
vtkm::Id3 idx;
idx[0] = 0;
idx[1] = 1;
idx[2] = 5;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 5;
idx[2] = 4;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 1;
idx[1] = 2;
idx[2] = 6;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 1;
idx[1] = 6;
idx[2] = 5;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 3;
idx[1] = 7;
idx[2] = 6;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 3;
idx[1] = 6;
idx[2] = 2;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 4;
idx[2] = 7;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 7;
idx[2] = 3;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 3;
idx[2] = 2;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 2;
idx[2] = 1;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 4;
idx[1] = 5;
idx[2] = 6;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
idx[0] = 4;
idx[1] = 6;
idx[2] = 7;
offset += 3;
cell2seg(idx, segment, offset, cellIndices, outputIndices);
}
}
#if defined(VTKM_MSVC)
#pragma warning(pop)
#endif
};
class Cylinderize : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
Cylinderize() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void tri2seg(vtkm::Id& offset,
const VecType& cellIndices,
const vtkm::Id& cellId,
const vtkm::Id Id0,
const vtkm::Id Id1,
const vtkm::Id Id2,
OutputPortal& outputIndices) const
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = vtkm::Id(cellIndices[vtkm::IdComponent(Id0)]);
segment[2] = vtkm::Id(cellIndices[vtkm::IdComponent(Id1)]);
outputIndices.Set(offset++, segment);
segment[1] = vtkm::Id(cellIndices[vtkm::IdComponent(Id1)]);
segment[2] = vtkm::Id(cellIndices[vtkm::IdComponent(Id2)]);
outputIndices.Set(offset++, segment);
segment[1] = vtkm::Id(cellIndices[vtkm::IdComponent(Id2)]);
segment[2] = vtkm::Id(cellIndices[vtkm::IdComponent(Id0)]);
outputIndices.Set(offset++, segment);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& offset,
vtkm::CellShapeTagQuad shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(offset, segment);
segment[1] = cellIndices[1];
segment[2] = cellIndices[2];
outputIndices.Set(offset + 1, segment);
segment[1] = cellIndices[2];
segment[2] = cellIndices[3];
outputIndices.Set(offset + 2, segment);
segment[1] = cellIndices[3];
segment[2] = cellIndices[0];
outputIndices.Set(offset + 3, segment);
}
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 1, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 5, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 2, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 6, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 7, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 6, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 4, 7, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 7, 3, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 3, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 2, 1, outputIndices);
tri2seg(offset, cellIndices, cellId, 4, 5, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 4, 6, 7, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_LINE)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
}
if (shapeType.Id == vtkm::CELL_SHAPE_TRIANGLE)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
segment[1] = cellIndices[1];
segment[2] = cellIndices[2];
outputIndices.Set(pointOffset + 1, segment);
segment[1] = cellIndices[2];
segment[2] = cellIndices[0];
outputIndices.Set(pointOffset + 2, segment);
}
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
segment[1] = cellIndices[1];
segment[2] = cellIndices[2];
outputIndices.Set(pointOffset + 1, segment);
segment[1] = cellIndices[2];
segment[2] = cellIndices[3];
outputIndices.Set(pointOffset + 2, segment);
segment[1] = cellIndices[3];
segment[2] = cellIndices[0];
outputIndices.Set(pointOffset + 3, segment);
}
if (shapeType.Id == vtkm::CELL_SHAPE_TETRA)
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 3, 1, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 2, 3, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 2, 3, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 2, 1, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 1, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 5, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 2, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 6, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 7, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 6, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 4, 7, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 7, 3, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 3, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 2, 1, outputIndices);
tri2seg(offset, cellIndices, cellId, 4, 5, 6, outputIndices);
tri2seg(offset, cellIndices, cellId, 4, 6, 7, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 1, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 5, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 0, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 2, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 4, 5, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 5, 2, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 3, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 4, 1, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
{
vtkm::Id offset = pointOffset;
tri2seg(offset, cellIndices, cellId, 0, 4, 1, outputIndices);
tri2seg(offset, cellIndices, cellId, 1, 2, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 2, 3, 4, outputIndices);
tri2seg(offset, cellIndices, cellId, 0, 4, 3, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 2, 1, outputIndices);
tri2seg(offset, cellIndices, cellId, 3, 1, 0, outputIndices);
}
}
}; //class cylinderize
public:
VTKM_CONT
Cylinderizer() {}
VTKM_CONT
void Run(const vtkm::cont::DynamicCellSet& cellset,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>>& outputIndices,
vtkm::Id& output)
{
if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
vtkm::cont::CellSetStructured<3> cellSetStructured3D =
cellset.Cast<vtkm::cont::CellSetStructured<3>>();
const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells();
vtkm::cont::ArrayHandleCounting<vtkm::Id> cellIdxs(0, 1, numCells);
outputIndices.Allocate(numCells * TRI_PER_CSS * SEG_PER_TRI);
vtkm::worklet::DispatcherMapTopology<SegmentedStructured<3>> segInvoker;
segInvoker.Invoke(cellSetStructured3D, cellIdxs, outputIndices);
output = numCells * TRI_PER_CSS * SEG_PER_TRI;
}
else
{
vtkm::cont::ArrayHandle<vtkm::Id> segmentsPerCell;
vtkm::worklet::DispatcherMapTopology<CountSegments> countInvoker;
countInvoker.Invoke(cellset, segmentsPerCell);
vtkm::Id total = 0;
total = vtkm::cont::Algorithm::Reduce(segmentsPerCell, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(segmentsPerCell, cellOffsets);
outputIndices.Allocate(total);
vtkm::worklet::DispatcherMapTopology<Cylinderize> cylInvoker;
cylInvoker.Invoke(cellset, cellOffsets, outputIndices);
output = total;
}
}
};
}
}
#endif

@ -0,0 +1,249 @@
//============================================================================
// 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.
//
// Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/MapperCylinder.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/Cylinderizer.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/CylinderExtractor.h>
#include <vtkm/rendering/raytracing/CylinderIntersector.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/QuadExtractor.h>
#include <vtkm/rendering/raytracing/QuadIntersector.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracer.h>
#include <vtkm/rendering/raytracing/SphereExtractor.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/Worklets.h>
namespace vtkm
{
namespace rendering
{
class CalcDistance : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CalcDistance(const vtkm::Vec<vtkm::Float32, 3>& _eye_pos)
: eye_pos(_eye_pos)
{
}
typedef void ControlSignature(FieldIn<>, FieldOut<>);
typedef void ExecutionSignature(_1, _2);
template <typename VecType, typename OutType>
VTKM_EXEC inline void operator()(const VecType& pos, OutType& out) const
{
VecType tmp = eye_pos - pos;
out = vtkm::Sqrt(vtkm::dot(tmp, tmp));
}
const vtkm::Vec<vtkm::Float32, 3> eye_pos;
}; //class CalcDistance
struct MapperCylinder::InternalsType
{
vtkm::rendering::CanvasRayTracer* Canvas;
vtkm::rendering::raytracing::RayTracer Tracer;
vtkm::rendering::raytracing::Camera RayCamera;
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
bool CompositeBackground;
vtkm::Float32 Radius;
vtkm::Float32 Delta;
bool UseVariableRadius;
VTKM_CONT
InternalsType()
: Canvas(nullptr)
, CompositeBackground(true)
, Radius(-1.0f)
, Delta(0.5)
, UseVariableRadius(false)
{
}
};
MapperCylinder::MapperCylinder()
: Internals(new InternalsType)
{
}
MapperCylinder::~MapperCylinder()
{
}
void MapperCylinder::SetCanvas(vtkm::rendering::Canvas* canvas)
{
if (canvas != nullptr)
{
this->Internals->Canvas = dynamic_cast<CanvasRayTracer*>(canvas);
if (this->Internals->Canvas == nullptr)
{
throw vtkm::cont::ErrorBadValue("Ray Tracer: bad canvas type. Must be CanvasRayTracer");
}
}
else
{
this->Internals->Canvas = nullptr;
}
}
vtkm::rendering::Canvas* MapperCylinder::GetCanvas() const
{
return this->Internals->Canvas;
}
void MapperCylinder::UseVariableRadius(bool useVariableRadius)
{
this->Internals->UseVariableRadius = useVariableRadius;
}
void MapperCylinder::SetRadius(const vtkm::Float32& radius)
{
if (radius <= 0.f)
{
throw vtkm::cont::ErrorBadValue("MapperCylinder: radius must be positive");
}
this->Internals->Radius = radius;
}
void MapperCylinder::SetRadiusDelta(const vtkm::Float32& delta)
{
this->Internals->Delta = delta;
}
void MapperCylinder::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange)
{
raytracing::Logger* logger = raytracing::Logger::GetInstance();
logger->OpenLogEntry("mapper_cylinder");
vtkm::cont::Timer<> tot_timer;
vtkm::cont::Timer<> timer;
vtkm::Bounds shapeBounds;
raytracing::CylinderExtractor cylExtractor;
vtkm::Float32 baseRadius = this->Internals->Radius;
if (baseRadius == -1.f)
{
// set a default radius
vtkm::cont::ArrayHandle<vtkm::Float32> dist;
vtkm::worklet::DispatcherMapField<CalcDistance>(CalcDistance(camera.GetPosition()))
.Invoke(coords, dist);
vtkm::Float32 min_dist =
vtkm::cont::Algorithm::Reduce(dist, vtkm::Infinity<vtkm::Float32>(), vtkm::Minimum());
baseRadius = 0.576769694f * min_dist - 0.603522029f * vtkm::Pow(vtkm::Float32(min_dist), 2.f) +
0.232171175f * vtkm::Pow(vtkm::Float32(min_dist), 3.f) -
0.038697244f * vtkm::Pow(vtkm::Float32(min_dist), 4.f) +
0.002366979f * vtkm::Pow(vtkm::Float32(min_dist), 5.f);
baseRadius /= min_dist;
vtkm::worklet::DispatcherMapField<vtkm::rendering::raytracing::MemSet<vtkm::Float32>>(
vtkm::rendering::raytracing::MemSet<vtkm::Float32>(baseRadius))
.Invoke(cylExtractor.GetRadii());
}
if (this->Internals->UseVariableRadius)
{
vtkm::Float32 minRadius = baseRadius - baseRadius * this->Internals->Delta;
vtkm::Float32 maxRadius = baseRadius + baseRadius * this->Internals->Delta;
cylExtractor.ExtractCells(cellset, scalarField, minRadius, maxRadius);
}
else
{
cylExtractor.ExtractCells(cellset, baseRadius);
}
//
// Add supported shapes
//
if (cylExtractor.GetNumberOfCylinders() > 0)
{
raytracing::CylinderIntersector* cylIntersector = new raytracing::CylinderIntersector();
cylIntersector->SetData(coords, cylExtractor.GetCylIds(), cylExtractor.GetRadii());
this->Internals->Tracer.AddShapeIntersector(cylIntersector);
shapeBounds.Include(cylIntersector->GetShapeBounds());
}
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);
timer.Reset();
this->Internals->Canvas->WriteToCanvas(
this->Internals->Rays, this->Internals->Rays.Buffers.at(0).Buffer, camera);
if (this->Internals->CompositeBackground)
{
this->Internals->Canvas->BlendBackground();
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("write_to_canvas", time);
time = tot_timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
void MapperCylinder::SetCompositeBackground(bool on)
{
this->Internals->CompositeBackground = on;
}
void MapperCylinder::StartScene()
{
// Nothing needs to be done.
}
void MapperCylinder::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperCylinder::NewCopy() const
{
return new vtkm::rendering::MapperCylinder(*this);
}
}
} // vtkm::rendering

@ -0,0 +1,246 @@
//============================================================================
// 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.
//
// Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/MapperPoint.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/internal/RunTriangulator.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracer.h>
#include <vtkm/rendering/raytracing/SphereExtractor.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
namespace vtkm
{
namespace rendering
{
struct MapperPoint::InternalsType
{
vtkm::rendering::CanvasRayTracer* Canvas;
vtkm::rendering::raytracing::RayTracer Tracer;
vtkm::rendering::raytracing::Camera RayCamera;
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
bool CompositeBackground;
vtkm::Float32 PointRadius;
bool UseNodes;
vtkm::Float32 PointDelta;
bool UseVariableRadius;
VTKM_CONT
InternalsType()
: Canvas(nullptr)
, CompositeBackground(true)
, PointRadius(-1.f)
, UseNodes(true)
, PointDelta(0.5f)
, UseVariableRadius(false)
{
}
};
MapperPoint::MapperPoint()
: Internals(new InternalsType)
{
}
MapperPoint::~MapperPoint()
{
}
void MapperPoint::SetCanvas(vtkm::rendering::Canvas* canvas)
{
if (canvas != nullptr)
{
this->Internals->Canvas = dynamic_cast<CanvasRayTracer*>(canvas);
if (this->Internals->Canvas == nullptr)
{
throw vtkm::cont::ErrorBadValue("MapperPoint: bad canvas type. Must be CanvasRayTracer");
}
}
else
{
this->Internals->Canvas = nullptr;
}
}
vtkm::rendering::Canvas* MapperPoint::GetCanvas() const
{
return this->Internals->Canvas;
}
void MapperPoint::UseCells()
{
this->Internals->UseNodes = false;
}
void MapperPoint::UseNodes()
{
this->Internals->UseNodes = true;
}
void MapperPoint::SetRadius(const vtkm::Float32& radius)
{
if (radius <= 0.f)
{
throw vtkm::cont::ErrorBadValue("MapperPoint: point radius must be positive");
}
this->Internals->PointRadius = radius;
}
void MapperPoint::SetRadiusDelta(const vtkm::Float32& delta)
{
this->Internals->PointDelta = delta;
}
void MapperPoint::UseVariableRadius(bool useVariableRadius)
{
this->Internals->UseVariableRadius = useVariableRadius;
}
void MapperPoint::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange)
{
raytracing::Logger* logger = raytracing::Logger::GetInstance();
// make sure we start fresh
this->Internals->Tracer.Clear();
logger->OpenLogEntry("mapper_ray_tracer");
vtkm::cont::Timer<> tot_timer;
vtkm::cont::Timer<> timer;
vtkm::Bounds coordBounds = coords.GetBounds();
vtkm::Float32 baseRadius = this->Internals->PointRadius;
if (baseRadius == -1.f)
{
// set a default radius
vtkm::Float64 lx = coordBounds.X.Length();
vtkm::Float64 ly = coordBounds.Y.Length();
vtkm::Float64 lz = coordBounds.Z.Length();
vtkm::Float64 mag = vtkm::Sqrt(lx * lx + ly * ly + lz * lz);
// same as used in vtk ospray
constexpr vtkm::Float64 heuristic = 500.;
baseRadius = static_cast<vtkm::Float32>(mag / heuristic);
}
vtkm::Bounds shapeBounds;
raytracing::SphereExtractor sphereExtractor;
if (this->Internals->UseVariableRadius)
{
vtkm::Float32 minRadius = baseRadius - baseRadius * this->Internals->PointDelta;
vtkm::Float32 maxRadius = baseRadius + baseRadius * this->Internals->PointDelta;
if (this->Internals->UseNodes)
{
sphereExtractor.ExtractCoordinates(coords, scalarField, minRadius, maxRadius);
}
else
{
sphereExtractor.ExtractCells(cellset, scalarField, minRadius, maxRadius);
}
}
else
{
if (this->Internals->UseNodes)
{
sphereExtractor.ExtractCoordinates(coords, baseRadius);
}
else
{
sphereExtractor.ExtractCells(cellset, baseRadius);
}
}
if (sphereExtractor.GetNumberOfSpheres() > 0)
{
raytracing::SphereIntersector* sphereIntersector = new raytracing::SphereIntersector();
sphereIntersector->SetData(coords, sphereExtractor.GetPointIds(), sphereExtractor.GetRadii());
this->Internals->Tracer.AddShapeIntersector(sphereIntersector);
shapeBounds.Include(sphereIntersector->GetShapeBounds());
}
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);
timer.Reset();
this->Internals->Canvas->WriteToCanvas(
this->Internals->Rays, this->Internals->Rays.Buffers.at(0).Buffer, camera);
if (this->Internals->CompositeBackground)
{
this->Internals->Canvas->BlendBackground();
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("write_to_canvas", time);
time = tot_timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
void MapperPoint::SetCompositeBackground(bool on)
{
this->Internals->CompositeBackground = on;
}
void MapperPoint::StartScene()
{
// Nothing needs to be done.
}
void MapperPoint::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperPoint::NewCopy() const
{
return new vtkm::rendering::MapperPoint(*this);
}
}
} // vtkm::rendering

@ -0,0 +1,99 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_MapperPoint_h
#define vtk_m_rendering_MapperPoint_h
#include <vtkm/cont/ColorTable.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/Mapper.h>
#include <memory>
namespace vtkm
{
namespace rendering
{
class VTKM_RENDERING_EXPORT MapperPoint : public Mapper
{
public:
MapperPoint();
~MapperPoint();
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
/**
* \brief render points based on cell shape point
*
*/
void UseCells();
/**
* \brief render points using the nodes of the mesh.
* This is the default.
*/
void UseNodes();
/**
* \brief render points using a variable radius based on
* the scalar field.
* The default is false.
*/
void UseVariableRadius(bool useVariableRadius);
/**
* \brief Set a base raidus for all points. If a
* radius is never specified the default heuristic
* is used.
*/
void SetRadius(const vtkm::Float32& radius);
/**
* \brief When using a variable raidus for all points, the
* radius delta controls how much larger and smaller
* radii become based on the scalar field. If the delta
* is 0 all points will have the same radius. If the delta
* is 0.5 then the max/min scalar values would have a radii
* of base +/- base * 0.5.
*/
void SetRadiusDelta(const vtkm::Float32& delta);
void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& colorTable,
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
struct RenderFunctor;
};
}
} //namespace vtkm::rendering
#endif //vtk_m_rendering_MapperPoint_h

@ -0,0 +1,170 @@
//============================================================================
// 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.
//
// Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/MapperQuad.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/Cylinderizer.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/CylinderExtractor.h>
#include <vtkm/rendering/raytracing/CylinderIntersector.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/QuadExtractor.h>
#include <vtkm/rendering/raytracing/QuadIntersector.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracer.h>
#include <vtkm/rendering/raytracing/SphereExtractor.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
namespace vtkm
{
namespace rendering
{
struct MapperQuad::InternalsType
{
vtkm::rendering::CanvasRayTracer* Canvas;
vtkm::rendering::raytracing::RayTracer Tracer;
vtkm::rendering::raytracing::Camera RayCamera;
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
bool CompositeBackground;
VTKM_CONT
InternalsType()
: Canvas(nullptr)
, CompositeBackground(true)
{
}
};
MapperQuad::MapperQuad()
: Internals(new InternalsType)
{
}
MapperQuad::~MapperQuad()
{
}
void MapperQuad::SetCanvas(vtkm::rendering::Canvas* canvas)
{
if (canvas != nullptr)
{
this->Internals->Canvas = dynamic_cast<CanvasRayTracer*>(canvas);
if (this->Internals->Canvas == nullptr)
{
throw vtkm::cont::ErrorBadValue("Ray Tracer: bad canvas type. Must be CanvasRayTracer");
}
}
else
{
this->Internals->Canvas = nullptr;
}
}
vtkm::rendering::Canvas* MapperQuad::GetCanvas() const
{
return this->Internals->Canvas;
}
void MapperQuad::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange)
{
raytracing::Logger* logger = raytracing::Logger::GetInstance();
logger->OpenLogEntry("mapper_ray_tracer");
vtkm::cont::Timer<> tot_timer;
vtkm::cont::Timer<> timer;
//
// Add supported shapes
//
vtkm::Bounds shapeBounds;
raytracing::QuadExtractor quadExtractor;
quadExtractor.ExtractCells(cellset);
if (quadExtractor.GetNumberOfQuads() > 0)
{
raytracing::QuadIntersector* quadIntersector = new raytracing::QuadIntersector();
quadIntersector->SetData(coords, quadExtractor.GetQuadIds());
this->Internals->Tracer.AddShapeIntersector(quadIntersector);
shapeBounds.Include(quadIntersector->GetShapeBounds());
}
//
// Create rays
//
vtkm::rendering::raytracing::Camera& cam = this->Internals->Tracer.GetCamera();
cam.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.SetParameters(camera, *this->Internals->Canvas);
this->Internals->RayCamera.CreateRays(this->Internals->Rays, shapeBounds);
this->Internals->Rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(
this->Internals->Rays, camera, *this->Internals->Canvas);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);
timer.Reset();
this->Internals->Canvas->WriteToCanvas(
this->Internals->Rays, this->Internals->Rays.Buffers.at(0).Buffer, camera);
if (this->Internals->CompositeBackground)
{
this->Internals->Canvas->BlendBackground();
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("write_to_canvas", time);
time = tot_timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
void MapperQuad::SetCompositeBackground(bool on)
{
this->Internals->CompositeBackground = on;
}
void MapperQuad::StartScene()
{
// Nothing needs to be done.
}
void MapperQuad::EndScene()
{
// Nothing needs to be done.
}
vtkm::rendering::Mapper* MapperQuad::NewCopy() const
{
return new vtkm::rendering::MapperQuad(*this);
}
}
} // vtkm::rendering

@ -0,0 +1,65 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_MapperQuad_h
#define vtk_m_rendering_MapperQuad_h
#include <vtkm/cont/ColorTable.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/Mapper.h>
#include <memory>
namespace vtkm
{
namespace rendering
{
class VTKM_RENDERING_EXPORT MapperQuad : public Mapper
{
public:
MapperQuad();
~MapperQuad();
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
virtual vtkm::rendering::Canvas* GetCanvas() const override;
void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& colorTable,
const vtkm::rendering::Camera& camera,
const vtkm::Range& scalarRange) override;
virtual void StartScene() override;
virtual void EndScene() override;
void SetCompositeBackground(bool on);
vtkm::rendering::Mapper* NewCopy() const override;
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
struct RenderFunctor;
};
}
} //namespace vtkm::rendering
#endif //vtk_m_rendering_MapperQuad_h

@ -0,0 +1,331 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_Quadralizer_h
#define vtk_m_rendering_Quadralizer_h
#include <typeinfo>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#define QUAD_PER_CSS 6
namespace vtkm
{
namespace rendering
{
class Quadralizer
{
public:
class CountQuads : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
CountQuads() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut<>);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& quads) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
quads = 1;
else if (shapeType.Id == CELL_SHAPE_HEXAHEDRON)
quads = 6;
else if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
quads = 3;
else if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
quads = 1;
else
quads = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& quads) const
{
quads = 6;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& quads) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
quads = 1;
else
quads = 0;
}
}; //class CountQuads
template <int DIM>
class SegmentedStructured : public vtkm::worklet::WorkletMapPointToCell
{
public:
typedef void ControlSignature(CellSetIn cellset, FieldInTo<>, WholeArrayOut<>);
typedef void ExecutionSignature(FromIndices, _2, _3);
//typedef _1 InputDomain;
VTKM_CONT
SegmentedStructured() {}
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
#endif
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void cell2quad(vtkm::Vec<vtkm::Id, 4> idx,
vtkm::Vec<Id, 5>& quad,
const vtkm::Id offset,
const CellNodeVecType& cellIndices,
OutIndicesPortal& outputIndices) const
{
quad[1] = cellIndices[vtkm::IdComponent(idx[0])];
quad[2] = cellIndices[vtkm::IdComponent(idx[1])];
quad[3] = cellIndices[vtkm::IdComponent(idx[2])];
quad[4] = cellIndices[vtkm::IdComponent(idx[3])];
outputIndices.Set(offset, quad);
}
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void operator()(const CellNodeVecType& cellIndices,
const vtkm::Id& cellIndex,
OutIndicesPortal& outputIndices) const
{
if (DIM == 2)
{
// Do nothing mark says
}
else if (DIM == 3)
{
vtkm::Id offset = cellIndex * QUAD_PER_CSS;
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellIndex;
vtkm::Vec<vtkm::Id, 4> idx;
idx[0] = 0;
idx[1] = 1;
idx[2] = 5, idx[3] = 4;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 1;
idx[1] = 2;
idx[2] = 6;
idx[3] = 5;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 3;
idx[1] = 7;
idx[2] = 6;
idx[3] = 2;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 4;
idx[2] = 7;
idx[3] = 3;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 3;
idx[2] = 2;
idx[3] = 1;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 4;
idx[1] = 5;
idx[2] = 6;
idx[3] = 7;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
}
}
#if defined(VTKM_MSVC)
#pragma warning(pop)
#endif
};
class Quadralize : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
Quadralize() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void 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) const
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id0)]);
quad[2] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id1)]);
quad[3] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id2)]);
quad[4] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id3)]);
outputIndices.Set(offset++, quad);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& offset,
vtkm::CellShapeTagQuad shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = static_cast<vtkm::Id>(cellIndices[0]);
quad[2] = static_cast<vtkm::Id>(cellIndices[1]);
quad[3] = static_cast<vtkm::Id>(cellIndices[2]);
quad[4] = static_cast<vtkm::Id>(cellIndices[3]);
outputIndices.Set(offset, quad);
}
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = cellIndices[0];
quad[2] = cellIndices[1];
quad[3] = cellIndices[2];
quad[4] = cellIndices[3];
outputIndices.Set(pointOffset, quad);
}
if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 2, 1, 0, outputIndices);
}
}
}; //class Quadralize
public:
VTKM_CONT
Quadralizer() {}
VTKM_CONT
void Run(const vtkm::cont::DynamicCellSet& cellset,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>>& outputIndices,
vtkm::Id& output)
{
if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
vtkm::cont::CellSetStructured<3> cellSetStructured3D =
cellset.Cast<vtkm::cont::CellSetStructured<3>>();
const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells();
vtkm::cont::ArrayHandleCounting<vtkm::Id> cellIdxs(0, 1, numCells);
outputIndices.Allocate(numCells * QUAD_PER_CSS);
vtkm::worklet::DispatcherMapTopology<SegmentedStructured<3>> segInvoker;
segInvoker.Invoke(cellSetStructured3D, cellIdxs, outputIndices);
output = numCells * QUAD_PER_CSS;
}
else
{
vtkm::cont::ArrayHandle<vtkm::Id> quadsPerCell;
vtkm::worklet::DispatcherMapTopology<CountQuads> countInvoker;
countInvoker.Invoke(cellset, quadsPerCell);
vtkm::Id total = 0;
total = vtkm::cont::Algorithm::Reduce(quadsPerCell, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(quadsPerCell, cellOffsets);
outputIndices.Allocate(total);
vtkm::worklet::DispatcherMapTopology<Quadralize> quadInvoker;
quadInvoker.Invoke(cellset, cellOffsets, outputIndices);
output = total;
}
}
};
}
}
#endif

@ -0,0 +1,267 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_BVH_Traverser_h
#define vtk_m_rendering_raytracing_BVH_Traverser_h
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
#define END_FLAG -1000000000
template <typename BVHPortalType, typename Precision>
VTKM_EXEC inline bool IntersectAABB(const BVHPortalType& bvh,
const vtkm::Int32& currentNode,
const vtkm::Vec<Precision, 3>& originDir,
const vtkm::Vec<Precision, 3>& invDir,
const Precision& closestDistance,
bool& hitLeftChild,
bool& hitRightChild,
const Precision& minDistance) //Find hit after this distance
{
vtkm::Vec<vtkm::Float32, 4> first4 = bvh.Get(currentNode);
vtkm::Vec<vtkm::Float32, 4> second4 = bvh.Get(currentNode + 1);
vtkm::Vec<vtkm::Float32, 4> third4 = bvh.Get(currentNode + 2);
Precision xmin0 = first4[0] * invDir[0] - originDir[0];
Precision ymin0 = first4[1] * invDir[1] - originDir[1];
Precision zmin0 = first4[2] * invDir[2] - originDir[2];
Precision xmax0 = first4[3] * invDir[0] - originDir[0];
Precision ymax0 = second4[0] * invDir[1] - originDir[1];
Precision zmax0 = second4[1] * invDir[2] - originDir[2];
Precision min0 = vtkm::Max(
vtkm::Max(vtkm::Max(vtkm::Min(ymin0, ymax0), vtkm::Min(xmin0, xmax0)), vtkm::Min(zmin0, zmax0)),
minDistance);
Precision max0 = vtkm::Min(
vtkm::Min(vtkm::Min(vtkm::Max(ymin0, ymax0), vtkm::Max(xmin0, xmax0)), vtkm::Max(zmin0, zmax0)),
closestDistance);
hitLeftChild = (max0 >= min0);
Precision xmin1 = second4[2] * invDir[0] - originDir[0];
Precision ymin1 = second4[3] * invDir[1] - originDir[1];
Precision zmin1 = third4[0] * invDir[2] - originDir[2];
Precision xmax1 = third4[1] * invDir[0] - originDir[0];
Precision ymax1 = third4[2] * invDir[1] - originDir[1];
Precision zmax1 = third4[3] * invDir[2] - originDir[2];
Precision min1 = vtkm::Max(
vtkm::Max(vtkm::Max(vtkm::Min(ymin1, ymax1), vtkm::Min(xmin1, xmax1)), vtkm::Min(zmin1, zmax1)),
minDistance);
Precision max1 = vtkm::Min(
vtkm::Min(vtkm::Min(vtkm::Max(ymin1, ymax1), vtkm::Max(xmin1, xmax1)), vtkm::Max(zmin1, zmax1)),
closestDistance);
hitRightChild = (max1 >= min1);
return (min0 > min1);
}
template <template <typename> class LeafIntersectorType>
class BVHTraverser
{
public:
template <typename Device>
class Intersector : public vtkm::worklet::WorkletMapField
{
public:
typedef typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 4>> Float4ArrayHandle;
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 2>> Int2Handle;
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
typedef typename Float4ArrayHandle::ExecutionTypes<Device>::PortalConst Float4ArrayPortal;
typedef typename Int2Handle::ExecutionTypes<Device>::PortalConst Int2ArrayPortal;
typedef typename IdHandle::ExecutionTypes<Device>::PortalConst IdArrayPortal;
typedef typename Id4Handle::ExecutionTypes<Device>::PortalConst Id4ArrayPortal;
private:
bool Occlusion;
Float4ArrayPortal FlatBVH;
IdArrayPortal Leafs;
LeafIntersectorType<Device> LeafIntersector;
VTKM_EXEC
inline vtkm::Float32 rcp(vtkm::Float32 f) const { return 1.0f / f; }
VTKM_EXEC
inline vtkm::Float32 rcp_safe(vtkm::Float32 f) const
{
return rcp((vtkm::Abs(f) < 1e-8f) ? 1e-8f : f);
}
VTKM_EXEC
inline vtkm::Float64 rcp(vtkm::Float64 f) const { return 1.0 / f; }
VTKM_EXEC
inline vtkm::Float64 rcp_safe(vtkm::Float64 f) const
{
return rcp((vtkm::Abs(f) < 1e-8f) ? 1e-8f : f);
}
public:
VTKM_CONT
Intersector(bool occlusion, LinearBVH& bvh, LeafIntersectorType<Device>& leafIntersector)
: Occlusion(occlusion)
, FlatBVH(bvh.FlatBVH.PrepareForInput(Device()))
, Leafs(bvh.Leafs.PrepareForInput(Device()))
, LeafIntersector(leafIntersector)
{
}
using ControlSignature = void(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7, _8, _9);
template <typename PointPortalType, typename Precision>
VTKM_EXEC void operator()(const vtkm::Vec<Precision, 3>& dir,
const vtkm::Vec<Precision, 3>& origin,
Precision& distance,
const Precision& minDistance,
const Precision& maxDistance,
Precision& minU,
Precision& minV,
vtkm::Id& hitIndex,
const PointPortalType& points) const
{
Precision closestDistance = maxDistance;
distance = maxDistance;
hitIndex = -1;
vtkm::Vec<Precision, 3> invDir;
invDir[0] = rcp_safe(dir[0]);
invDir[1] = rcp_safe(dir[1]);
invDir[2] = rcp_safe(dir[2]);
vtkm::Int32 currentNode;
vtkm::Int32 todo[64];
vtkm::Int32 stackptr = 0;
vtkm::Int32 barrier = (vtkm::Int32)END_FLAG;
currentNode = 0;
todo[stackptr] = barrier;
vtkm::Vec<Precision, 3> originDir = origin * invDir;
while (currentNode != END_FLAG)
{
if (currentNode > -1)
{
bool hitLeftChild, hitRightChild;
bool rightCloser = IntersectAABB(FlatBVH,
currentNode,
originDir,
invDir,
closestDistance,
hitLeftChild,
hitRightChild,
minDistance);
if (!hitLeftChild && !hitRightChild)
{
currentNode = todo[stackptr];
stackptr--;
}
else
{
vtkm::Vec<vtkm::Float32, 4> children =
FlatBVH.Get(currentNode + 3); //Children.Get(currentNode);
vtkm::Int32 leftChild;
memcpy(&leftChild, &children[0], 4);
vtkm::Int32 rightChild;
memcpy(&rightChild, &children[1], 4);
currentNode = (hitLeftChild) ? leftChild : rightChild;
if (hitLeftChild && hitRightChild)
{
if (rightCloser)
{
currentNode = rightChild;
stackptr++;
todo[stackptr] = leftChild;
}
else
{
stackptr++;
todo[stackptr] = rightChild;
}
}
}
} // if inner node
if (currentNode < 0 && currentNode != barrier) //check register usage
{
currentNode = -currentNode - 1; //swap the neg address
LeafIntersector.IntersectLeaf(currentNode,
origin,
dir,
points,
hitIndex,
closestDistance,
minU,
minV,
Leafs,
minDistance);
currentNode = todo[stackptr];
stackptr--;
} // if leaf node
} //while
if (hitIndex != -1)
distance = closestDistance;
} // ()
};
template <typename Precision, typename Device>
VTKM_CONT void IntersectRays(Ray<Precision>& rays,
LinearBVH& bvh,
LeafIntersectorType<Device> leafIntersector,
vtkm::cont::CoordinateSystem& coordsHandle,
Device vtkmNotUsed(Device))
{
vtkm::worklet::DispatcherMapField<Intersector<Device>> intersectDispatch(
Intersector<Device>(false, bvh, leafIntersector));
intersectDispatch.SetDevice(Device());
intersectDispatch.Invoke(rays.Dir,
rays.Origin,
rays.Distance,
rays.MinDistance,
rays.MaxDistance,
rays.U,
rays.V,
rays.HitIdx,
coordsHandle);
}
}; // BVHTraverser
#undef END_FLAG
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_BVHTraverser_h

@ -0,0 +1,326 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/raytracing/CylinderExtractor.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/Cylinderizer.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
class CountSegments : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
CountSegments() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut<>);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& segments) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_LINE)
segments = 1;
else if (shapeType.Id == vtkm::CELL_SHAPE_TRIANGLE)
segments = 3;
else if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
segments = 4;
else
segments = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
}; // ClassCountSegments
class Pointify : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
Pointify() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagQuad vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_LINE)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
//outputIndices.Set(pointOffset, cellId);
//outputId2.Set(pointOffset, vtkm::Id2(cellId, cellId));
}
else if (shapeType.Id == vtkm::CELL_SHAPE_TRIANGLE)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
segment[1] = cellIndices[1];
segment[2] = cellIndices[2];
outputIndices.Set(pointOffset + 1, segment);
segment[1] = cellIndices[2];
segment[2] = cellIndices[0];
outputIndices.Set(pointOffset + 2, segment);
}
else if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Id3 segment;
segment[0] = cellId;
segment[1] = cellIndices[0];
segment[2] = cellIndices[1];
outputIndices.Set(pointOffset, segment);
segment[1] = cellIndices[1];
segment[2] = cellIndices[2];
outputIndices.Set(pointOffset + 1, segment);
segment[1] = cellIndices[2];
segment[2] = cellIndices[3];
outputIndices.Set(pointOffset + 2, segment);
segment[1] = cellIndices[3];
segment[2] = cellIndices[0];
outputIndices.Set(pointOffset + 3, segment);
}
}
}; //class pointify
class Iterator : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
Iterator() {}
typedef void ControlSignature(FieldOut<>);
typedef void ExecutionSignature(_1, WorkIndex);
VTKM_EXEC
void operator()(vtkm::Id2& index, const vtkm::Id2& idx) const { index = idx; }
}; //class Iterator
class FieldRadius : public vtkm::worklet::WorkletMapField
{
protected:
vtkm::Float32 MinRadius;
vtkm::Float32 RadiusDelta;
vtkm::Float32 MinValue;
vtkm::Float32 InverseDelta;
public:
VTKM_CONT
FieldRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::Range scalarRange)
: MinRadius(minRadius)
, RadiusDelta(maxRadius - minRadius)
, MinValue(static_cast<vtkm::Float32>(scalarRange.Min))
{
vtkm::Float32 delta = static_cast<vtkm::Float32>(scalarRange.Max - scalarRange.Min);
if (delta != 0.f)
InverseDelta = 1.f / (delta);
else
InverseDelta = 0.f; // just map scalar to 0;
}
typedef void ControlSignature(FieldIn<>, FieldOut<>, WholeArrayIn<Scalar>);
typedef void ExecutionSignature(_1, _2, _3);
template <typename ScalarPortalType>
VTKM_EXEC void operator()(const vtkm::Id3& cylId,
vtkm::Float32& radius,
const ScalarPortalType& scalars) const
{
vtkm::Float32 scalar = static_cast<vtkm::Float32>(scalars.Get(cylId[0]));
vtkm::Float32 t = (scalar - MinValue) * InverseDelta;
radius = MinRadius + t * RadiusDelta;
}
}; //class FieldRadius
} //namespace detail
//void CylinderExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
// const vtkm::Float32 radius)
//{
// this->SetPointIdsFromCoords(coords);
// this->SetUniformRadius(radius);
//}
//TODO: I don't think I need varying radius
//void CylinderExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
// const vtkm::cont::Field& field,
// const vtkm::Float32 minRadius,
// const vtkm::Float32 maxRadius)
//{
// this->SetPointIdsFromCoords(coords);
// this->SetVaryingRadius(minRadius, maxRadius, field);
//}
void CylinderExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::Float32 radius)
{
vtkm::Id numOfSegments;
vtkm::rendering::Cylinderizer geometrizer;
geometrizer.Run(cells, this->CylIds, numOfSegments);
//this->SetCylinderIdsFromCells(cells);
this->SetUniformRadius(radius);
}
void CylinderExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius)
{
vtkm::Id numOfSegments;
vtkm::rendering::Cylinderizer geometrizer;
geometrizer.Run(cells, this->CylIds, numOfSegments);
//this->SetCylinderIdsFromCells(cells);
this->SetVaryingRadius(minRadius, maxRadius, field);
}
void CylinderExtractor::SetUniformRadius(const vtkm::Float32 radius)
{
const vtkm::Id size = this->CylIds.GetNumberOfValues();
Radii.Allocate(size);
vtkm::cont::ArrayHandleConstant<vtkm::Float32> radiusHandle(radius, size);
vtkm::cont::Algorithm::Copy(radiusHandle, Radii);
}
void CylinderExtractor::SetCylinderIdsFromCells(const vtkm::cont::DynamicCellSet& cells)
{
vtkm::Id numCells = cells.GetNumberOfCells();
if (numCells == 0)
{
return;
}
//
// look for points in the cell set
//
if (cells.IsSameType(vtkm::cont::CellSetExplicit<>()))
{
vtkm::cont::ArrayHandle<vtkm::Id> points;
vtkm::worklet::DispatcherMapTopology<detail::CountSegments>(detail::CountSegments())
.Invoke(cells, points);
vtkm::Id totalPoints = 0;
totalPoints = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets);
CylIds.Allocate(totalPoints);
vtkm::worklet::DispatcherMapTopology<detail::Pointify>(detail::Pointify())
.Invoke(cells, cellOffsets, this->CylIds);
}
}
void CylinderExtractor::SetVaryingRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::cont::Field& field)
{
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray = field.GetRange();
if (rangeArray.GetNumberOfValues() != 1)
{
throw vtkm::cont::ErrorBadValue("Cylinder Extractor: scalar field must have one component");
}
vtkm::Range range = rangeArray.GetPortalConstControl().Get(0);
Radii.Allocate(this->CylIds.GetNumberOfValues());
vtkm::worklet::DispatcherMapField<detail::FieldRadius>(
detail::FieldRadius(minRadius, maxRadius, range))
.Invoke(this->CylIds, this->Radii, field);
}
vtkm::cont::ArrayHandle<vtkm::Id3> CylinderExtractor::GetCylIds()
{
return this->CylIds;
}
vtkm::cont::ArrayHandle<vtkm::Float32> CylinderExtractor::GetRadii()
{
return this->Radii;
}
vtkm::Id CylinderExtractor::GetNumberOfCylinders() const
{
return this->CylIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,84 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Cylinder_Extractor_h
#define vtk_m_rendering_raytracing_Cylinder_Extractor_h
#include <vtkm/cont/DataSet.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class CylinderExtractor
{
protected:
vtkm::cont::ArrayHandle<vtkm::Id3> CylIds;
vtkm::cont::ArrayHandle<vtkm::Float32> Radii;
public:
//
// Extract all nodes using a constant radius
//
// void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords, const vtkm::Float32 radius);
// //
// // Set radius based on scalar field values. Each is interpolated from min to max
// //
// void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
// const vtkm::cont::Field& field,
// const vtkm::Float32 minRadius,
// const vtkm::Float32 maxRadius);
//
// Extract all vertex shapes with constant radius
//
void ExtractCells(const vtkm::cont::DynamicCellSet& cells, vtkm::Float32 radius);
//
// Extract all vertex elements with radius based on scalar values
//
void ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius);
vtkm::cont::ArrayHandle<vtkm::Id3> GetCylIds();
vtkm::cont::ArrayHandle<vtkm::Float32> GetRadii();
vtkm::Id GetNumberOfCylinders() const;
protected:
void SetUniformRadius(const vtkm::Float32 radius);
void SetVaryingRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::cont::Field& field);
// void SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords);
void SetCylinderIdsFromCells(const vtkm::cont::DynamicCellSet& cells);
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Extractor_h

@ -0,0 +1,378 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/raytracing/BVHTraverser.h>
#include <vtkm/rendering/raytracing/CylinderIntersector.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
template <typename Device>
class CylinderLeafIntersector : public vtkm::cont::ExecutionObjectBase
{
public:
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id3>;
using IdArrayPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using FloatHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
using FloatPortal = typename FloatHandle::ExecutionTypes<Device>::PortalConst;
IdArrayPortal CylIds;
FloatPortal Radii;
CylinderLeafIntersector(const IdHandle& cylIds, const FloatHandle& radii)
: CylIds(cylIds.PrepareForInput(Device()))
, Radii(radii.PrepareForInput(Device()))
{
}
template <typename vec3>
VTKM_EXEC vec3 cylinder(const vec3& ray_start,
const vec3& ray_direction,
const vec3& p,
const vec3& q,
float r) const
{
float t = 0;
vec3 d = q - p;
vec3 m = ray_start - p;
vec3 s = ray_start - q;
vtkm::Float32 mdotm = vtkm::Float32(vtkm::dot(m, m));
vec3 n = ray_direction * (vtkm::Max(mdotm, static_cast<vtkm::Float32>(vtkm::dot(s, s))) + r);
vtkm::Float32 mdotd = vtkm::Float32(vtkm::dot(m, d));
vtkm::Float32 ndotd = vtkm::Float32(vtkm::dot(n, d));
vtkm::Float32 ddotd = vtkm::Float32(vtkm::dot(d, d));
if ((mdotd < 0.0f) && (mdotd + ndotd < 0.0f))
{
return vec3(0.f, 0.f, 0.f);
}
if ((mdotd > ddotd) && (mdotd + ndotd > ddotd))
{
return vec3(0.f, 0.f, 0.f);
}
vtkm::Float32 ndotn = vtkm::Float32(vtkm::dot(n, n));
vtkm::Float32 nlen = vtkm::Float32(sqrt(ndotn));
vtkm::Float32 mdotn = vtkm::Float32(vtkm::dot(m, n));
vtkm::Float32 a = ddotd * ndotn - ndotd * ndotd;
vtkm::Float32 k = mdotm - r * r;
vtkm::Float32 c = ddotd * k - mdotd * mdotd;
if (fabs(a) < 1e-6)
{
if (c > 0.0)
{
return vec3(0, 0, 0);
}
if (mdotd < 0.0f)
{
t = -mdotn / ndotn;
}
else if (mdotd > ddotd)
{
t = (ndotd - mdotn) / ndotn;
}
else
t = 0;
return vec3(1, t * nlen, 0);
}
vtkm::Float32 b = ddotd * mdotn - ndotd * mdotd;
vtkm::Float32 discr = b * b - a * c;
if (discr < 0.0f)
{
return vec3(0, 0, 0);
}
t = (-b - vtkm::Sqrt(discr)) / a;
if (t < 0.0f || t > 1.0f)
{
return vec3(0, 0, 0);
}
vtkm::Float32 u = mdotd + t * ndotd;
if (u > ddotd)
{
if (ndotd >= 0.0f)
{
return vec3(0, 0, 0);
}
t = (ddotd - mdotd) / ndotd;
return vec3(
k + ddotd - 2 * mdotd + t * (2 * (mdotn - ndotd) + t * ndotn) <= 0.0f, t * nlen, 0);
}
else if (u < 0.0f)
{
if (ndotd <= 0.0f)
{
return vec3(0.0, 0.0, 0);
}
t = -mdotd / ndotd;
return vec3(k + 2 * t * (mdotn + t * ndotn) <= 0.0f, t * nlen, 0);
}
return vec3(1, t * nlen, 0);
}
template <typename PointPortalType, typename LeafPortalType, typename Precision>
VTKM_EXEC inline void IntersectLeaf(
const vtkm::Int32& currentNode,
const vtkm::Vec<Precision, 3>& origin,
const vtkm::Vec<Precision, 3>& dir,
const PointPortalType& points,
vtkm::Id& hitIndex,
Precision& closestDistance, // closest distance in this set of primitives
Precision& vtkmNotUsed(minU),
Precision& vtkmNotUsed(minV),
LeafPortalType leafs,
const Precision& minDistance) const // report intesections past this distance
{
const vtkm::Id cylCount = leafs.Get(currentNode);
for (vtkm::Id i = 1; i <= cylCount; ++i)
{
const vtkm::Id cylIndex = leafs.Get(currentNode + i);
if (cylIndex < CylIds.GetNumberOfValues())
{
vtkm::Id3 pointIndex = CylIds.Get(cylIndex);
vtkm::Float32 radius = Radii.Get(cylIndex);
vtkm::Vec<Precision, 3> bottom, top;
bottom = vtkm::Vec<Precision, 3>(points.Get(pointIndex[1]));
top = vtkm::Vec<Precision, 3>(points.Get(pointIndex[2]));
vtkm::Vec<vtkm::Float32, 3> ret;
ret = cylinder(origin, dir, bottom, top, radius);
if (ret[0] > 0)
{
if (ret[1] < closestDistance && ret[1] > minDistance)
{
//matid = vtkm::Vec<, 3>(points.Get(cur_offset + 2))[0];
closestDistance = ret[1];
hitIndex = cylIndex;
}
}
}
} // for
}
};
struct IntersectFunctor
{
template <typename Device, typename Precision>
VTKM_CONT bool operator()(Device,
CylinderIntersector* self,
Ray<Precision>& rays,
bool returnCellIndex)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->IntersectRaysImp(Device(), rays, returnCellIndex);
return true;
}
};
class CalculateNormals : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CalculateNormals() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
template <typename Precision, typename PointPortalType, typename IndicesPortalType>
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
const vtkm::Vec<Precision, 3>& intersection,
Precision& normalX,
Precision& normalY,
Precision& normalZ,
const PointPortalType& points,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
vtkm::Id3 cylId = indicesPortal.Get(hitIndex);
vtkm::Vec<Precision, 3> a, b;
a = points.Get(cylId[1]);
b = points.Get(cylId[2]);
vtkm::Vec<Precision, 3> ap, ab;
ap = intersection - a;
ab = b - a;
Precision mag2 = vtkm::Magnitude(ab);
Precision len = vtkm::dot(ab, ap);
Precision t = len / mag2;
vtkm::Vec<Precision, 3> center;
center = a + t * ab;
vtkm::Vec<Precision, 3> normal = intersection - center;
vtkm::Normalize(normal);
//flip the normal if its pointing the wrong way
normalX = normal[0];
normalY = normal[1];
normalZ = normal[2];
}
}; //class CalculateNormals
template <typename Precision>
class GetScalar : public vtkm::worklet::WorkletMapField
{
private:
Precision MinScalar;
Precision invDeltaScalar;
public:
VTKM_CONT
GetScalar(const vtkm::Float32& minScalar, const vtkm::Float32& maxScalar)
: MinScalar(minScalar)
{
//Make sure the we don't divide by zero on
//something like an iso-surface
if (maxScalar - MinScalar != 0.f)
invDeltaScalar = 1.f / (maxScalar - MinScalar);
else
invDeltaScalar = 1.f / minScalar;
}
typedef void ControlSignature(FieldIn<>,
FieldInOut<>,
WholeArrayIn<ScalarRenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4);
template <typename ScalarPortalType, typename IndicesPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
Precision& scalar,
const ScalarPortalType& scalars,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
//TODO: this should be interpolated?
vtkm::Id3 pointId = indicesPortal.Get(hitIndex);
scalar = Precision(scalars.Get(pointId[0]));
//normalize
scalar = (scalar - MinScalar) * invDeltaScalar;
}
}; //class GetScalar
} // namespace detail
CylinderIntersector::CylinderIntersector()
: ShapeIntersector()
{
}
CylinderIntersector::~CylinderIntersector()
{
}
void CylinderIntersector::IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
void CylinderIntersector::IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
template <typename Device, typename Precision>
void CylinderIntersector::IntersectRaysImp(Device,
Ray<Precision>& rays,
bool vtkmNotUsed(returnCellIndex))
{
detail::CylinderLeafIntersector<Device> leafIntersector(this->CylIds, Radii);
BVHTraverser<detail::CylinderLeafIntersector> traverser;
traverser.IntersectRays(rays, this->BVH, leafIntersector, this->CoordsHandle, Device());
RayOperations::UpdateRayStatus(rays);
}
template <typename Precision>
void CylinderIntersector::IntersectionDataImp(Ray<Precision>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
ShapeIntersector::IntersectionPoint(rays);
// TODO: if this is nodes of a mesh, support points
bool isSupportedField =
(scalarField->GetAssociation() == vtkm::cont::Field::Association::POINTS ||
scalarField->GetAssociation() == vtkm::cont::Field::Association::CELL_SET);
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue("Field not accociated with a cell set");
vtkm::worklet::DispatcherMapField<detail::CalculateNormals>(detail::CalculateNormals())
.Invoke(rays.HitIdx,
rays.Intersection,
rays.NormalX,
rays.NormalY,
rays.NormalZ,
CoordsHandle,
CylIds);
vtkm::worklet::DispatcherMapField<detail::GetScalar<Precision>>(
detail::GetScalar<Precision>(vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
.Invoke(rays.HitIdx, rays.Scalar, *scalarField, CylIds);
}
void CylinderIntersector::IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
void CylinderIntersector::IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
vtkm::Id CylinderIntersector::GetNumberOfShapes() const
{
return CylIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,325 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_MeshConnectivityBase
#define vtk_m_rendering_raytracing_MeshConnectivityBase
#include <sstream>
#include <vtkm/CellShape.h>
#include <vtkm/VirtualObjectBase.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/VirtualObjectHandle.h>
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/CellTables.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_ALWAYS_EXPORT MeshConnectivityBase : public VirtualObjectBase
{
public:
VTKM_EXEC_CONT
virtual vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const = 0;
VTKM_EXEC_CONT
virtual vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const = 0;
VTKM_EXEC_CONT
virtual vtkm::UInt8 GetCellShape(const vtkm::Id& cellId) const = 0;
};
class VTKM_ALWAYS_EXPORT MeshConnStructured : public MeshConnectivityBase
{
protected:
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
vtkm::Id3 CellDims;
vtkm::Id3 PointDims;
VTKM_CONT MeshConnStructured() = default;
public:
VTKM_CONT
MeshConnStructured(const vtkm::Id3& cellDims, const vtkm::Id3& pointDims)
: CellDims(cellDims)
, PointDims(pointDims)
{
}
VTKM_EXEC_CONT
vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const override
{
//TODO: there is probably a better way to do this.
vtkm::Id3 logicalCellId;
logicalCellId[0] = cellId % CellDims[0];
logicalCellId[1] = (cellId / CellDims[0]) % CellDims[1];
logicalCellId[2] = cellId / (CellDims[0] * CellDims[1]);
if (face == 0)
logicalCellId[1] -= 1;
if (face == 2)
logicalCellId[1] += 1;
if (face == 1)
logicalCellId[0] += 1;
if (face == 3)
logicalCellId[0] -= 1;
if (face == 4)
logicalCellId[2] -= 1;
if (face == 5)
logicalCellId[2] += 1;
vtkm::Id nextCell =
(logicalCellId[2] * CellDims[1] + logicalCellId[1]) * CellDims[0] + logicalCellId[0];
bool validCell = true;
if (logicalCellId[0] >= CellDims[0])
validCell = false;
if (logicalCellId[1] >= CellDims[1])
validCell = false;
if (logicalCellId[2] >= CellDims[2])
validCell = false;
vtkm::Id minId = vtkm::Min(logicalCellId[0], vtkm::Min(logicalCellId[1], logicalCellId[2]));
if (minId < 0)
validCell = false;
if (!validCell)
nextCell = -1;
return nextCell;
}
VTKM_EXEC_CONT
vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellIndex) const override
{
vtkm::Id3 cellId;
cellId[0] = cellIndex % CellDims[0];
cellId[1] = (cellIndex / CellDims[0]) % CellDims[1];
cellId[2] = cellIndex / (CellDims[0] * CellDims[1]);
cellIndices[0] = (cellId[2] * PointDims[1] + cellId[1]) * PointDims[0] + cellId[0];
cellIndices[1] = cellIndices[0] + 1;
cellIndices[2] = cellIndices[1] + PointDims[0];
cellIndices[3] = cellIndices[2] - 1;
cellIndices[4] = cellIndices[0] + PointDims[0] * PointDims[1];
cellIndices[5] = cellIndices[4] + 1;
cellIndices[6] = cellIndices[5] + PointDims[0];
cellIndices[7] = cellIndices[6] - 1;
return 8;
}
VTKM_EXEC
vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const override
{
return vtkm::UInt8(CELL_SHAPE_HEXAHEDRON);
}
}; // MeshConnStructured
template <typename Device>
class VTKM_ALWAYS_EXPORT MeshConnUnstructured : public MeshConnectivityBase
{
protected:
using IdHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using UCharHandle = typename vtkm::cont::ArrayHandle<vtkm::UInt8>;
using IdConstPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using UCharConstPortal = typename UCharHandle::ExecutionTypes<Device>::PortalConst;
// Constant Portals for the execution Environment
//FaceConn
IdConstPortal FaceConnPortal;
IdConstPortal FaceOffsetsPortal;
//Cell Set
IdConstPortal CellConnPortal;
IdConstPortal CellOffsetsPortal;
UCharConstPortal ShapesPortal;
VTKM_CONT MeshConnUnstructured() = default;
public:
VTKM_CONT
MeshConnUnstructured(const IdHandle& faceConnectivity,
const IdHandle& faceOffsets,
const IdHandle& cellConn,
const IdHandle& cellOffsets,
const UCharHandle& shapes)
: FaceConnPortal(faceConnectivity.PrepareForInput(Device()))
, FaceOffsetsPortal(faceOffsets.PrepareForInput(Device()))
, CellConnPortal(cellConn.PrepareForInput(Device()))
, CellOffsetsPortal(cellOffsets.PrepareForInput(Device()))
, ShapesPortal(shapes.PrepareForInput(Device()))
{
}
VTKM_EXEC_CONT
vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const override
{
BOUNDS_CHECK(FaceOffsetsPortal, cellId);
vtkm::Id cellStartIndex = FaceOffsetsPortal.Get(cellId);
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
return FaceConnPortal.Get(cellStartIndex + face);
}
//----------------------------------------------------------------------------
VTKM_EXEC
vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const override
{
const vtkm::Int32 shapeId = static_cast<vtkm::Int32>(ShapesPortal.Get(cellId));
CellTables tables;
const vtkm::Int32 numIndices = tables.FaceLookUp(tables.CellTypeLookUp(shapeId), 2);
BOUNDS_CHECK(CellOffsetsPortal, cellId);
const vtkm::Id cellOffset = CellOffsetsPortal.Get(cellId);
for (vtkm::Int32 i = 0; i < numIndices; ++i)
{
BOUNDS_CHECK(CellConnPortal, cellOffset + i);
cellIndices[i] = CellConnPortal.Get(cellOffset + i);
}
return numIndices;
}
//----------------------------------------------------------------------------
VTKM_EXEC
vtkm::UInt8 GetCellShape(const vtkm::Id& cellId) const override
{
BOUNDS_CHECK(ShapesPortal, cellId)
return ShapesPortal.Get(cellId);
}
}; // MeshConnUnstructured
template <typename Device>
class MeshConnSingleType : public MeshConnectivityBase
{
protected:
using IdHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using IdConstPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using CountingHandle = typename vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using CountingPortal = typename CountingHandle::ExecutionTypes<Device>::PortalConst;
// Constant Portals for the execution Environment
IdConstPortal FaceConnPortal;
IdConstPortal CellConnectivityPortal;
CountingPortal CellOffsetsPortal;
vtkm::Int32 ShapeId;
vtkm::Int32 NumIndices;
vtkm::Int32 NumFaces;
private:
VTKM_CONT
MeshConnSingleType() {}
public:
VTKM_CONT
MeshConnSingleType(IdHandle& faceConn,
IdHandle& cellConn,
CountingHandle& cellOffsets,
vtkm::Int32 shapeId,
vtkm::Int32 numIndices,
vtkm::Int32 numFaces)
: FaceConnPortal(faceConn.PrepareForInput(Device()))
, CellConnectivityPortal(cellConn.PrepareForInput(Device()))
, CellOffsetsPortal(cellOffsets.PrepareForInput(Device()))
, ShapeId(shapeId)
, NumIndices(numIndices)
, NumFaces(numFaces)
{
}
//----------------------------------------------------------------------------
// Execution Environment Methods
//----------------------------------------------------------------------------
VTKM_EXEC
vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const override
{
BOUNDS_CHECK(CellOffsetsPortal, cellId);
vtkm::Id cellStartIndex = cellId * NumFaces;
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
return FaceConnPortal.Get(cellStartIndex + face);
}
VTKM_EXEC
vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const override
{
BOUNDS_CHECK(CellOffsetsPortal, cellId);
const vtkm::Id cellOffset = CellOffsetsPortal.Get(cellId);
for (vtkm::Int32 i = 0; i < NumIndices; ++i)
{
BOUNDS_CHECK(CellConnectivityPortal, cellOffset + i);
cellIndices[i] = CellConnectivityPortal.Get(cellOffset + i);
}
return NumIndices;
}
//----------------------------------------------------------------------------
VTKM_EXEC
vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const override
{
return vtkm::UInt8(ShapeId);
}
}; //MeshConn Single type specialization
class VTKM_ALWAYS_EXPORT MeshConnHandle
: public vtkm::cont::VirtualObjectHandle<MeshConnectivityBase>
{
private:
using Superclass = vtkm::cont::VirtualObjectHandle<MeshConnectivityBase>;
public:
MeshConnHandle() = default;
template <typename MeshConnType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
explicit MeshConnHandle(MeshConnType* meshConn,
bool aquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Superclass(meshConn, aquireOwnership, devices)
{
}
};
template <typename MeshConnType, typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
VTKM_CONT MeshConnHandle make_MeshConnHandle(MeshConnType&& func,
DeviceAdapterList devices = DeviceAdapterList())
{
using IFType = typename std::remove_reference<MeshConnType>::type;
return MeshConnHandle(new IFType(std::forward<MeshConnType>(func)), true, devices);
}
}
}
} //namespace vtkm::rendering::raytracing
#ifdef VTKM_CUDA
// Cuda seems to have a bug where it expects the template class VirtualObjectTransfer
// to be instantiated in a consitent order among all the translation units of an
// executable. Failing to do so results in random crashes and incorrect results.
// We workaroud this issue by explicitly instantiating VirtualObjectTransfer for
// all the implicit functions here.
#include <vtkm/cont/cuda/internal/VirtualObjectTransferCuda.h>
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(vtkm::rendering::raytracing::MeshConnStructured);
VTKM_EXPLICITLY_INSTANTIATE_TRANSFER(
vtkm::rendering::raytracing::MeshConnUnstructured<vtkm::cont::DeviceAdapterTagCuda>);
#endif
#endif // MeshConnectivityBase

@ -0,0 +1,285 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <sstream>
#include <vtkm/CellShape.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/internal/DeviceAdapterListHelpers.h>
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBase.h>
#include <vtkm/rendering/raytracing/MeshConnectivityContainers.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
MeshConnContainer::MeshConnContainer(){};
MeshConnContainer::~MeshConnContainer(){};
template <typename T>
VTKM_CONT void MeshConnContainer::FindEntryImpl(Ray<T>& rays,
const vtkm::cont::DeviceAdapterId deviceId)
{
bool getCellIndex = true;
Intersector.SetUseWaterTight(true);
switch (deviceId.GetValue())
{
#ifdef VTKM_ENABLE_TBB
case VTKM_DEVICE_ADAPTER_TBB:
Intersector.IntersectRays(rays, vtkm::cont::DeviceAdapterTagTBB(), getCellIndex);
break;
#endif
#ifdef VTKM_ENABLE_CUDA
case VTKM_DEVICE_ADAPTER_CUDA:
Intersector.IntersectRays(rays, vtkm::cont::DeviceAdapterTagCuda(), getCellIndex);
break;
#endif
default:
Intersector.IntersectRays(rays, vtkm::cont::DeviceAdapterTagSerial(), getCellIndex);
break;
}
}
void MeshConnContainer::FindEntry(Ray<vtkm::Float32>& rays,
const vtkm::cont::DeviceAdapterId deviceId)
{
this->FindEntryImpl(rays, deviceId);
}
void MeshConnContainer::FindEntry(Ray<vtkm::Float64>& rays,
const vtkm::cont::DeviceAdapterId deviceId)
{
this->FindEntryImpl(rays, deviceId);
}
VTKM_CONT
UnstructuredContainer::UnstructuredContainer(const vtkm::cont::CellSetExplicit<>& cellset,
const vtkm::cont::CoordinateSystem& coords,
IdHandle& faceConn,
IdHandle& faceOffsets,
Id4Handle& externalTriangles)
: FaceConnectivity(faceConn)
, FaceOffsets(faceOffsets)
, Cellset(cellset)
, Coords(coords)
{
this->ExternalTriangles = externalTriangles;
//
// Grab the cell arrays
//
CellConn =
Cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
CellOffsets =
Cellset.GetIndexOffsetArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
Shapes = Cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
Intersector.SetData(Coords, ExternalTriangles);
}
UnstructuredContainer::~UnstructuredContainer(){};
const MeshConnectivityBase* UnstructuredContainer::Construct(
const vtkm::cont::DeviceAdapterId deviceId)
{
switch (deviceId.GetValue())
{
#ifdef VTKM_ENABLE_TBB
case VTKM_DEVICE_ADAPTER_TBB:
using TBB = vtkm::cont::DeviceAdapterTagTBB;
{
MeshConnUnstructured<TBB> conn(this->FaceConnectivity,
this->FaceOffsets,
this->CellConn,
this->CellOffsets,
this->Shapes);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(TBB());
#endif
#ifdef VTKM_ENABLE_CUDA
case VTKM_DEVICE_ADAPTER_CUDA:
using CUDA = vtkm::cont::DeviceAdapterTagCuda;
{
MeshConnUnstructured<CUDA> conn(this->FaceConnectivity,
this->FaceOffsets,
this->CellConn,
this->CellOffsets,
this->Shapes);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(CUDA());
#endif
default:
using SERIAL = vtkm::cont::DeviceAdapterTagSerial;
{
MeshConnUnstructured<SERIAL> conn(this->FaceConnectivity,
this->FaceOffsets,
this->CellConn,
this->CellOffsets,
this->Shapes);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(SERIAL());
}
}
VTKM_CONT
UnstructuredSingleContainer::UnstructuredSingleContainer()
{
}
VTKM_CONT
UnstructuredSingleContainer::UnstructuredSingleContainer(
const vtkm::cont::CellSetSingleType<>& cellset,
const vtkm::cont::CoordinateSystem& coords,
IdHandle& faceConn,
Id4Handle& externalTriangles)
: FaceConnectivity(faceConn)
, Coords(coords)
, Cellset(cellset)
{
this->ExternalTriangles = externalTriangles;
this->Intersector.SetUseWaterTight(true);
CellConnectivity =
Cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
Cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
ShapeId = shapes.GetPortalConstControl().Get(0);
CellTables tables;
NumIndices = tables.FaceLookUp(tables.CellTypeLookUp(ShapeId), 2);
if (NumIndices == 0)
{
std::stringstream message;
message << "Unstructured Mesh Connecitity Single type Error: unsupported cell type: ";
message << ShapeId;
throw vtkm::cont::ErrorBadValue(message.str());
}
vtkm::Id start = 0;
NumFaces = tables.FaceLookUp(tables.CellTypeLookUp(ShapeId), 1);
vtkm::Id numCells = CellConnectivity.GetPortalConstControl().GetNumberOfValues();
CellOffsets = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(start, NumIndices, numCells);
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("mesh_conn_construction");
vtkm::cont::Timer<cont::DeviceAdapterTagSerial> timer;
Intersector.SetData(Coords, ExternalTriangles);
}
const MeshConnectivityBase* UnstructuredSingleContainer::Construct(
const vtkm::cont::DeviceAdapterId deviceId)
{
switch (deviceId.GetValue())
{
#ifdef VTKM_ENABLE_TBB
case VTKM_DEVICE_ADAPTER_TBB:
using TBB = vtkm::cont::DeviceAdapterTagTBB;
{
MeshConnSingleType<TBB> conn(this->FaceConnectivity,
this->CellConnectivity,
this->CellOffsets,
this->ShapeId,
this->NumIndices,
this->NumFaces);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(TBB());
#endif
#ifdef VTKM_ENABLE_CUDA
case VTKM_DEVICE_ADAPTER_CUDA:
using CUDA = vtkm::cont::DeviceAdapterTagCuda;
{
MeshConnSingleType<CUDA> conn(this->FaceConnectivity,
this->CellConnectivity,
this->CellOffsets,
this->ShapeId,
this->NumIndices,
this->NumFaces);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(CUDA());
#endif
default:
using SERIAL = vtkm::cont::DeviceAdapterTagSerial;
{
MeshConnSingleType<SERIAL> conn(this->FaceConnectivity,
this->CellConnectivity,
this->CellOffsets,
this->ShapeId,
this->NumIndices,
this->NumFaces);
Handle = make_MeshConnHandle(conn);
}
return Handle.PrepareForExecution(SERIAL());
}
}
StructuredContainer::StructuredContainer(const vtkm::cont::CellSetStructured<3>& cellset,
const vtkm::cont::CoordinateSystem& coords,
Id4Handle& externalTriangles)
: Coords(coords)
, Cellset(cellset)
{
ExternalTriangles = externalTriangles;
Intersector.SetUseWaterTight(true);
PointDims = Cellset.GetPointDimensions();
CellDims = Cellset.GetCellDimensions();
this->Intersector.SetData(Coords, ExternalTriangles);
}
const MeshConnectivityBase* StructuredContainer::Construct(
const vtkm::cont::DeviceAdapterId deviceId)
{
MeshConnStructured conn(CellDims, PointDims);
Handle = make_MeshConnHandle(conn);
switch (deviceId.GetValue())
{
#ifdef VTKM_ENABLE_TBB
case VTKM_DEVICE_ADAPTER_TBB:
return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagTBB());
#endif
#ifdef VTKM_ENABLE_CUDA
case VTKM_DEVICE_ADAPTER_CUDA:
return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagCuda());
#endif
default:
return Handle.PrepareForExecution(vtkm::cont::DeviceAdapterTagSerial());
}
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,155 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_MeshConnectivityContainer_h
#define vtk_m_rendering_raytracing_MeshConnectivityContainer_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBase.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class MeshConnContainer
{
public:
MeshConnContainer();
virtual ~MeshConnContainer();
virtual const MeshConnectivityBase* Construct(const vtkm::cont::DeviceAdapterId deviceId) = 0;
template <typename T>
VTKM_CONT void FindEntryImpl(Ray<T>& rays, const vtkm::cont::DeviceAdapterId deviceId);
void FindEntry(Ray<vtkm::Float32>& rays, const vtkm::cont::DeviceAdapterId deviceId);
void FindEntry(Ray<vtkm::Float64>& rays, const vtkm::cont::DeviceAdapterId deviceId);
protected:
using Id4Handle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
// Mesh Boundary
Id4Handle ExternalTriangles;
TriangleIntersector Intersector;
MeshConnHandle Handle;
};
class UnstructuredContainer : public MeshConnContainer
{
public:
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
typedef vtkm::cont::ArrayHandle<vtkm::UInt8> UCharHandle;
// Control Environment Handles
// FaceConn
IdHandle FaceConnectivity;
IdHandle FaceOffsets;
//Cell Set
IdHandle CellConn;
IdHandle CellOffsets;
UCharHandle Shapes;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CellSetExplicit<> Cellset;
vtkm::cont::CoordinateSystem Coords;
private:
VTKM_CONT
UnstructuredContainer(){};
public:
VTKM_CONT
UnstructuredContainer(const vtkm::cont::CellSetExplicit<>& cellset,
const vtkm::cont::CoordinateSystem& coords,
IdHandle& faceConn,
IdHandle& faceOffsets,
Id4Handle& externalTriangles);
virtual ~UnstructuredContainer();
const MeshConnectivityBase* Construct(const vtkm::cont::DeviceAdapterId deviceId);
};
class StructuredContainer : public MeshConnContainer
{
protected:
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
vtkm::Id3 CellDims;
vtkm::Id3 PointDims;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CoordinateSystem Coords;
vtkm::cont::CellSetStructured<3> Cellset;
private:
VTKM_CONT
StructuredContainer() {}
public:
VTKM_CONT
StructuredContainer(const vtkm::cont::CellSetStructured<3>& cellset,
const vtkm::cont::CoordinateSystem& coords,
Id4Handle& externalTriangles);
const MeshConnectivityBase* Construct(const vtkm::cont::DeviceAdapterId deviceId) override;
}; //structure mesh conn
class UnstructuredSingleContainer : public MeshConnContainer
{
public:
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
typedef vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandle;
typedef vtkm::cont::ArrayHandleConstant<vtkm::UInt8> ShapesHandle;
typedef vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> NumIndicesHandle;
// Control Environment Handles
IdHandle FaceConnectivity;
CountingHandle CellOffsets;
IdHandle CellConnectivity;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CoordinateSystem Coords;
vtkm::cont::CellSetSingleType<> Cellset;
vtkm::Int32 ShapeId;
vtkm::Int32 NumIndices;
vtkm::Int32 NumFaces;
private:
VTKM_CONT
UnstructuredSingleContainer();
public:
VTKM_CONT
UnstructuredSingleContainer(const vtkm::cont::CellSetSingleType<>& cellset,
const vtkm::cont::CoordinateSystem& coords,
IdHandle& faceConn,
Id4Handle& externalFaces);
const MeshConnectivityBase* Construct(const vtkm::cont::DeviceAdapterId deviceId) override;
}; //UnstructuredSingleContainer
}
}
} //namespace vtkm::rendering::raytracing
#endif

@ -0,0 +1,249 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/raytracing/QuadExtractor.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/Quadralizer.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
class CountQuads : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
CountQuads() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut<>);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& quads) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
quads = 1;
else
quads = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& quads) const
{
quads = 6;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 1;
}
}; // ClassCountquads
class Pointify : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
Pointify() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void 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) const
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id0)]);
quad[2] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id1)]);
quad[3] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id2)]);
quad[4] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id3)]);
outputIndices.Set(offset++, quad);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagQuad vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = cellIndices[0];
quad[2] = cellIndices[1];
quad[3] = cellIndices[2];
quad[4] = cellIndices[3];
outputIndices.Set(pointOffset, quad);
}
}
}; //class pointify
class Iterator : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
Iterator() {}
typedef void ControlSignature(FieldOut<>);
typedef void ExecutionSignature(_1, WorkIndex);
VTKM_EXEC
void operator()(vtkm::Id2& index, const vtkm::Id2& idx) const { index = idx; }
}; //class Iterator
class FieldRadius : public vtkm::worklet::WorkletMapField
{
protected:
vtkm::Float32 MinRadius;
vtkm::Float32 RadiusDelta;
vtkm::Float32 MinValue;
vtkm::Float32 InverseDelta;
public:
VTKM_CONT
FieldRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::Range scalarRange)
: MinRadius(minRadius)
, RadiusDelta(maxRadius - minRadius)
, MinValue(static_cast<vtkm::Float32>(scalarRange.Min))
{
vtkm::Float32 delta = static_cast<vtkm::Float32>(scalarRange.Max - scalarRange.Min);
if (delta != 0.f)
InverseDelta = 1.f / (delta);
else
InverseDelta = 0.f; // just map scalar to 0;
}
typedef void ControlSignature(FieldIn<>, FieldOut<>, WholeArrayIn<Scalar>);
typedef void ExecutionSignature(_1, _2, _3);
template <typename ScalarPortalType>
VTKM_EXEC void operator()(const vtkm::Id& pointId,
vtkm::Float32& radius,
const ScalarPortalType& scalars) const
{
vtkm::Float32 scalar = static_cast<vtkm::Float32>(scalars.Get(pointId));
vtkm::Float32 t = (scalar - MinValue) * InverseDelta;
radius = MinRadius + t * RadiusDelta;
}
}; //class FieldRadius
} //namespace detail
void QuadExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells)
{
vtkm::Id numOfQuads;
vtkm::rendering::Quadralizer quadrizer;
quadrizer.Run(cells, this->QuadIds, numOfQuads);
//this->SetPointIdsFromCells(cells);
}
void QuadExtractor::SetQuadIdsFromCells(const vtkm::cont::DynamicCellSet& cells)
{
vtkm::Id numCells = cells.GetNumberOfCells();
if (numCells == 0)
{
return;
}
//
// look for points in the cell set
//
if (cells.IsSameType(vtkm::cont::CellSetExplicit<>()))
{
vtkm::cont::ArrayHandle<vtkm::Id> points;
vtkm::worklet::DispatcherMapTopology<detail::CountQuads>(detail::CountQuads())
.Invoke(cells, points);
vtkm::Id total = 0;
total = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets);
QuadIds.Allocate(total);
vtkm::worklet::DispatcherMapTopology<detail::Pointify>(detail::Pointify())
.Invoke(cells, cellOffsets, this->QuadIds);
}
}
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>> QuadExtractor::GetQuadIds()
{
return this->QuadIds;
}
vtkm::Id QuadExtractor::GetNumberOfQuads() const
{
return this->QuadIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,52 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Quad_Extractor_h
#define vtk_m_rendering_raytracing_Quad_Extractor_h
#include <vtkm/cont/DataSet.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class QuadExtractor
{
protected:
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>> QuadIds;
vtkm::cont::ArrayHandle<vtkm::Float32> Radii;
public:
void ExtractCells(const vtkm::cont::DynamicCellSet& cells);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>> GetQuadIds();
vtkm::Id GetNumberOfQuads() const;
protected:
void SetQuadIdsFromCells(const vtkm::cont::DynamicCellSet& cells);
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Extractor_h

@ -0,0 +1,410 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/raytracing/BVHTraverser.h>
#include <vtkm/rendering/raytracing/QuadIntersector.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
template <typename Device>
class QuadLeafIntersector : public vtkm::cont::ExecutionObjectBase
{
public:
using IdType = vtkm::Vec<vtkm::Id, 5>;
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>>;
using IdArrayPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using FloatHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
using FloatPortal = typename FloatHandle::ExecutionTypes<Device>::PortalConst;
IdArrayPortal QuadIds;
QuadLeafIntersector(const IdHandle& quadIds)
: QuadIds(quadIds.PrepareForInput(Device()))
{
}
template <typename vec3, typename Precision>
VTKM_EXEC bool quad(const vec3& ray_origin,
const vec3& ray_direction,
const vec3& v00,
const vec3& v10,
const vec3& v11,
const vec3& v01,
Precision& u,
Precision& v,
Precision& t) const
{
/* An Efficient Ray-Quadrilateral Intersection Test
Ares Lagae Philip Dutr´e
http://graphics.cs.kuleuven.be/publications/LD05ERQIT/index.html
v01 *------------ * v11
|\ |
| \ |
| \ |
| \ |
| \ |
| \ |
v00 *------------* v10
*/
// Rejects rays that are parallel to Q, and rays that intersect the plane of
// Q either on the left of the line V00V01 or on the right of the line V00V10.
vec3 E03 = v01 - v00;
vec3 P = vtkm::Cross(ray_direction, E03);
vec3 E01 = v10 - v00;
Precision det = vtkm::dot(E01, P);
if (vtkm::Abs(det) < vtkm::Epsilon<Precision>())
return false;
Precision inv_det = 1.0f / det;
vec3 T = ray_origin - v00;
Precision alpha = vtkm::dot(T, P) * inv_det;
if (alpha < 0.0)
return false;
vec3 Q = vtkm::Cross(T, E01);
Precision beta = vtkm::dot(ray_direction, Q) * inv_det;
if (beta < 0.0)
return false;
if ((alpha + beta) > 1.0f)
{
// Rejects rays that intersect the plane of Q either on the
// left of the line V11V10 or on the right of the line V11V01.
vec3 E23 = v01 - v11;
vec3 E21 = v10 - v11;
vec3 P_prime = vtkm::Cross(ray_direction, E21);
Precision det_prime = vtkm::dot(E23, P_prime);
if (vtkm::Abs(det_prime) < vtkm::Epsilon<Precision>())
return false;
Precision inv_det_prime = 1.0f / det_prime;
vec3 T_prime = ray_origin - v11;
Precision alpha_prime = vtkm::dot(T_prime, P_prime) * inv_det_prime;
if (alpha_prime < 0.0f)
return false;
vec3 Q_prime = vtkm::Cross(T_prime, E23);
Precision beta_prime = vtkm::dot(ray_direction, Q_prime) * inv_det_prime;
if (beta_prime < 0.0f)
return false;
}
// Compute the ray parameter of the intersection point, and
// reject the ray if it does not hit Q.
t = vtkm::dot(E03, Q) * inv_det;
if (t < 0.0)
return false;
// Compute the barycentric coordinates of V11
Precision alpha_11, beta_11;
vec3 E02 = v11 - v00;
vec3 n = vtkm::Cross(E01, E02);
if ((vtkm::Abs(n[0]) >= vtkm::Abs(n[1])) && (vtkm::Abs(n[0]) >= vtkm::Abs(n[2])))
{
alpha_11 = ((E02[1] * E03[2]) - (E02[2] * E03[1])) / n[0];
beta_11 = ((E01[1] * E02[2]) - (E01[2] * E02[1])) / n[0];
}
else if ((vtkm::Abs(n[1]) >= vtkm::Abs(n[0])) && (vtkm::Abs(n[1]) >= vtkm::Abs(n[2])))
{
alpha_11 = ((E02[2] * E03[0]) - (E02[0] * E03[2])) / n[1];
beta_11 = ((E01[2] * E02[0]) - (E01[0] * E02[2])) / n[1];
}
else
{
alpha_11 = ((E02[0] * E03[1]) - (E02[1] * E03[0])) / n[2];
beta_11 = ((E01[0] * E02[1]) - (E01[1] * E02[0])) / n[2];
}
// Compute the bilinear coordinates of the intersection point.
if (vtkm::Abs(alpha_11 - 1.0f) < vtkm::Epsilon<Precision>())
{
u = alpha;
if (vtkm::Abs(beta_11 - 1.0f) < vtkm::Epsilon<Precision>())
v = beta;
else
v = beta / ((u * (beta_11 - 1.0f)) + 1.0f);
}
else if (vtkm::Abs(beta_11 - 1.0) < vtkm::Epsilon<Precision>())
{
v = beta;
u = alpha / ((v * (alpha_11 - 1.0f)) + 1.0f);
}
else
{
Precision A = 1.0f - beta_11;
Precision B = (alpha * (beta_11 - 1.0f)) - (beta * (alpha_11 - 1.0f)) - 1.0f;
Precision C = alpha;
Precision D = (B * B) - (4.0f * A * C);
Precision QQ = -0.5f * (B + ((B < 0.0f ? -1.0f : 1.0f) * vtkm::Sqrt(D)));
u = QQ / A;
if ((u < 0.0f) || (u > 1.0f))
u = C / QQ;
v = beta / ((u * (beta_11 - 1.0f)) + 1.0f);
}
return true;
}
template <typename PointPortalType, typename LeafPortalType, typename Precision>
VTKM_EXEC inline void IntersectLeaf(
const vtkm::Int32& currentNode,
const vtkm::Vec<Precision, 3>& origin,
const vtkm::Vec<Precision, 3>& dir,
const PointPortalType& points,
vtkm::Id& hitIndex,
Precision& closestDistance, // closest distance in this set of primitives
Precision& minU,
Precision& minV,
LeafPortalType leafs,
const Precision& minDistance) const // report intesections past this distance
{
const vtkm::Id quadCount = leafs.Get(currentNode);
for (vtkm::Id i = 1; i <= quadCount; ++i)
{
const vtkm::Id quadIndex = leafs.Get(currentNode + i);
if (quadIndex < QuadIds.GetNumberOfValues())
{
IdType pointIndex = QuadIds.Get(quadIndex);
Precision dist;
vtkm::Vec<Precision, 3> q, r, s, t;
q = vtkm::Vec<Precision, 3>(points.Get(pointIndex[1]));
r = vtkm::Vec<Precision, 3>(points.Get(pointIndex[2]));
s = vtkm::Vec<Precision, 3>(points.Get(pointIndex[3]));
t = vtkm::Vec<Precision, 3>(points.Get(pointIndex[4]));
Precision u, v;
bool ret = quad(origin, dir, q, r, s, t, u, v, dist);
if (ret)
{
if (dist < closestDistance && dist > minDistance)
{
//matid = vtkm::Vec<, 3>(points.Get(cur_offset + 2))[0];
closestDistance = dist;
hitIndex = quadIndex;
minU = u;
minV = v;
}
}
}
} // for
}
};
struct IntersectFunctor
{
template <typename Device, typename Precision>
VTKM_CONT bool operator()(Device,
QuadIntersector* self,
Ray<Precision>& rays,
bool returnCellIndex)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->IntersectRaysImp(Device(), rays, returnCellIndex);
return true;
}
};
class CalculateNormals : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CalculateNormals() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
template <typename Precision, typename PointPortalType, typename IndicesPortalType>
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
const vtkm::Vec<Precision, 3>& rayDir,
Precision& normalX,
Precision& normalY,
Precision& normalZ,
const PointPortalType& points,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
vtkm::Vec<vtkm::Id, 5> quadId = indicesPortal.Get(hitIndex);
vtkm::Vec<Precision, 3> a, b, c;
a = points.Get(quadId[1]);
b = points.Get(quadId[2]);
c = points.Get(quadId[3]);
vtkm::Vec<Precision, 3> normal = vtkm::TriangleNormal(a, b, c);
vtkm::Normalize(normal);
//flip the normal if its pointing the wrong way
if (vtkm::dot(normal, rayDir) > 0.f)
normal = -normal;
normalX = normal[0];
normalY = normal[1];
normalZ = normal[2];
}
}; //class CalculateNormals
template <typename Precision>
class GetScalar : public vtkm::worklet::WorkletMapField
{
private:
Precision MinScalar;
Precision invDeltaScalar;
public:
VTKM_CONT
GetScalar(const vtkm::Float32& minScalar, const vtkm::Float32& maxScalar)
: MinScalar(minScalar)
{
//Make sure the we don't divide by zero on
//something like an iso-surface
if (maxScalar - MinScalar != 0.f)
invDeltaScalar = 1.f / (maxScalar - MinScalar);
else
invDeltaScalar = 1.f / minScalar;
}
typedef void ControlSignature(FieldIn<>,
FieldInOut<>,
WholeArrayIn<ScalarRenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4);
template <typename ScalarPortalType, typename IndicesPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
Precision& scalar,
const ScalarPortalType& scalars,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
//TODO: this should be interpolated?
vtkm::Vec<vtkm::Id, 5> pointId = indicesPortal.Get(hitIndex);
scalar = Precision(scalars.Get(pointId[0]));
//normalize
scalar = (scalar - MinScalar) * invDeltaScalar;
}
}; //class GetScalar
} // namespace detail
QuadIntersector::QuadIntersector()
: ShapeIntersector()
{
}
QuadIntersector::~QuadIntersector()
{
}
void QuadIntersector::IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
void QuadIntersector::IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
template <typename Device, typename Precision>
void QuadIntersector::IntersectRaysImp(Device,
Ray<Precision>& rays,
bool vtkmNotUsed(returnCellIndex))
{
detail::QuadLeafIntersector<Device> leafIntersector(this->QuadIds);
BVHTraverser<detail::QuadLeafIntersector> traverser;
traverser.IntersectRays(rays, this->BVH, leafIntersector, this->CoordsHandle, Device());
RayOperations::UpdateRayStatus(rays);
}
template <typename Precision>
void QuadIntersector::IntersectionDataImp(Ray<Precision>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
ShapeIntersector::IntersectionPoint(rays);
// TODO: if this is nodes of a mesh, support points
bool isSupportedField =
(scalarField->GetAssociation() == vtkm::cont::Field::Association::POINTS ||
scalarField->GetAssociation() == vtkm::cont::Field::Association::CELL_SET);
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue("Field not accociated with a cell set");
vtkm::worklet::DispatcherMapField<detail::CalculateNormals>(detail::CalculateNormals())
.Invoke(rays.HitIdx, rays.Dir, rays.NormalX, rays.NormalY, rays.NormalZ, CoordsHandle, QuadIds);
vtkm::worklet::DispatcherMapField<detail::GetScalar<Precision>>(
detail::GetScalar<Precision>(vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
.Invoke(rays.HitIdx, rays.Scalar, *scalarField, QuadIds);
}
void QuadIntersector::IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
void QuadIntersector::IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
vtkm::Id QuadIntersector::GetNumberOfShapes() const
{
return QuadIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,176 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Quad_Intersector_h
#define vtk_m_rendering_raytracing_Quad_Intersector_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/raytracing/ShapeIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
#define AABB_EPSILON 1.0e-4f
class FindQuadAABBs : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
FindQuadAABBs() {}
typedef void ControlSignature(FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8);
template <typename PointPortalType>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Id, 5> quadId,
vtkm::Float32& xmin,
vtkm::Float32& ymin,
vtkm::Float32& zmin,
vtkm::Float32& xmax,
vtkm::Float32& ymax,
vtkm::Float32& zmax,
const PointPortalType& points) const
{
// cast to Float32
vtkm::Vec<vtkm::Float32, 3> q, r, s, t;
q = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(quadId[1]));
r = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(quadId[2]));
s = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(quadId[3]));
t = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(quadId[4]));
xmin = q[0];
ymin = q[1];
zmin = q[2];
xmax = xmin;
ymax = ymin;
zmax = zmin;
xmin = vtkm::Min(xmin, r[0]);
ymin = vtkm::Min(ymin, r[1]);
zmin = vtkm::Min(zmin, r[2]);
xmax = vtkm::Max(xmax, r[0]);
ymax = vtkm::Max(ymax, r[1]);
zmax = vtkm::Max(zmax, r[2]);
xmin = vtkm::Min(xmin, s[0]);
ymin = vtkm::Min(ymin, s[1]);
zmin = vtkm::Min(zmin, s[2]);
xmax = vtkm::Max(xmax, s[0]);
ymax = vtkm::Max(ymax, s[1]);
zmax = vtkm::Max(zmax, s[2]);
xmin = vtkm::Min(xmin, t[0]);
ymin = vtkm::Min(ymin, t[1]);
zmin = vtkm::Min(zmin, t[2]);
xmax = vtkm::Max(xmax, t[0]);
ymax = vtkm::Max(ymax, t[1]);
zmax = vtkm::Max(zmax, t[2]);
vtkm::Float32 xEpsilon, yEpsilon, zEpsilon;
const vtkm::Float32 minEpsilon = 1e-6f;
xEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (xmax - xmin));
yEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (ymax - ymin));
zEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (zmax - zmin));
xmin -= xEpsilon;
ymin -= yEpsilon;
zmin -= zEpsilon;
xmax += xEpsilon;
ymax += yEpsilon;
zmax += zEpsilon;
}
}; //class FindAABBs
}
class QuadIntersector : public ShapeIntersector
{
protected:
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>> QuadIds;
public:
QuadIntersector();
virtual ~QuadIntersector() override;
void SetData(const vtkm::cont::CoordinateSystem& coords,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>> quadIds)
{
this->QuadIds = quadIds;
this->CoordsHandle = coords;
AABBs AABB;
vtkm::worklet::DispatcherMapField<detail::FindQuadAABBs> faabbsInvoker;
faabbsInvoker.Invoke(this->QuadIds,
AABB.xmins,
AABB.ymins,
AABB.zmins,
AABB.xmaxs,
AABB.ymaxs,
AABB.zmaxs,
CoordsHandle);
//vtkm::worklet::DispatcherMapField<detail::FindQuadAABBs> faabbsInvoker(detail::FindQuadAABBs())
// .Invoke(this->QuadIds,
// AABB.xmins,
// AABB.ymins,
// AABB.zmins,
// AABB.xmaxs,
// AABB.ymaxs,
// AABB.zmaxs,
// CoordsHandle);
this->SetAABBs(AABB);
}
void IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex = false) override;
void IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex = false) override;
template <typename Device, typename Precision>
void IntersectRaysImp(Device, Ray<Precision>& rays, bool returnCellIndex);
template <typename Precision>
void IntersectionDataImp(Ray<Precision>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange);
void IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) override;
void IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) override;
vtkm::Id GetNumberOfShapes() const override;
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Intersector_h

@ -0,0 +1,112 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/raytracing/ShapeIntersector.h>
#include <vtkm/worklet/DispatcherMapField.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace
{
class IntersectionPointMap : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
IntersectionPointMap() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<>,
FieldIn<>,
FieldIn<>,
FieldInOut<>,
FieldInOut<>,
FieldInOut<>,
FieldInOut<>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8);
template <typename Precision>
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
const Precision& distance,
const vtkm::Vec<Precision, 3>& rayDir,
const vtkm::Vec<Precision, 3>& rayOrigin,
Precision& intersectionX,
Precision& intersectionY,
Precision& intersectionZ,
Precision& maxDistance) const
{
if (hitIndex < 0)
return;
intersectionX = rayOrigin[0] + rayDir[0] * distance;
intersectionY = rayOrigin[1] + rayDir[1] * distance;
intersectionZ = rayOrigin[2] + rayDir[2] * distance;
maxDistance = distance;
}
}; //class IntersectionPoint
} // anon namespace
ShapeIntersector::ShapeIntersector()
{
}
ShapeIntersector::~ShapeIntersector(){};
void ShapeIntersector::IntersectionPoint(Ray<vtkm::Float32>& rays)
{
this->IntersectionPointImp(rays);
}
void ShapeIntersector::IntersectionPoint(Ray<vtkm::Float64>& rays)
{
this->IntersectionPointImp(rays);
}
template <typename Precision>
void ShapeIntersector::IntersectionPointImp(Ray<Precision>& rays)
{
rays.EnableIntersectionData();
// Find the intersection point from hit distance
// and set the new max distance
vtkm::worklet::DispatcherMapField<IntersectionPointMap>(IntersectionPointMap())
.Invoke(rays.HitIdx,
rays.Distance,
rays.Dir,
rays.Origin,
rays.IntersectionX,
rays.IntersectionY,
rays.IntersectionZ,
rays.MaxDistance);
}
vtkm::Bounds ShapeIntersector::GetShapeBounds() const
{
return ShapeBounds;
}
void ShapeIntersector::SetAABBs(AABBs& aabbs)
{
this->BVH.SetData(aabbs);
this->BVH.Construct();
this->ShapeBounds = this->BVH.TotalBounds;
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,85 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Shape_Intersector_h
#define vtk_m_rendering_raytracing_Shape_Intersector_h
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/Ray.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT ShapeIntersector
{
protected:
LinearBVH BVH;
vtkm::cont::CoordinateSystem CoordsHandle;
vtkm::Bounds ShapeBounds;
void SetAABBs(AABBs& aabbs);
public:
ShapeIntersector();
virtual ~ShapeIntersector();
//
// Intersect Rays finds the nearest intersection shape contained in the derived
// class in between min and max distances. HitIdx will be set to the local
// primitive id unless returnCellIndex is set to true. Cells are often
// decomposed into triangles and setting returnCellIndex to true will set
// HitIdx to the id of the cell.
//
virtual void IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex = false) = 0;
virtual void IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex = false) = 0;
//
// Calling intersection data directly after IntersectRays popoulates
// ray data: intersection point, surface normal, and interpolated scalar
// value at the intersection location. Additionally, distance to intersection
// becomes the new max distance.
//
virtual void IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) = 0;
virtual void IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) = 0;
template <typename Precision>
void IntersectionPointImp(Ray<Precision>& rays);
void IntersectionPoint(Ray<vtkm::Float32>& rays);
void IntersectionPoint(Ray<vtkm::Float64>& rays);
vtkm::Bounds GetShapeBounds() const;
virtual vtkm::Id GetNumberOfShapes() const = 0;
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Intersector_h

@ -0,0 +1,285 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/raytracing/SphereExtractor.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
class CountPoints : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
CountPoints() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut<>);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& points) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_VERTEX)
points = 1;
else
points = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shapeType), vtkm::Id& points) const
{
points = 0;
}
}; // ClassCountPoints
class Pointify : public vtkm::worklet::WorkletMapPointToCell
{
public:
VTKM_CONT
Pointify() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagQuad vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& vtkmNotUsed(pointOffset),
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& vtkmNotUsed(cellId),
OutputPortal& vtkmNotUsed(outputIndices)) const
{
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& vtkmNotUsed(cellIndices),
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_VERTEX)
{
outputIndices.Set(pointOffset, cellId);
}
}
}; //class pointify
class Iterator : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
Iterator() {}
typedef void ControlSignature(FieldOut<>);
typedef void ExecutionSignature(_1, WorkIndex);
VTKM_EXEC
void operator()(vtkm::Id& index, const vtkm::Id& idx) const { index = idx; }
}; //class Iterator
class FieldRadius : public vtkm::worklet::WorkletMapField
{
protected:
vtkm::Float32 MinRadius;
vtkm::Float32 RadiusDelta;
vtkm::Float32 MinValue;
vtkm::Float32 InverseDelta;
public:
VTKM_CONT
FieldRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::Range scalarRange)
: MinRadius(minRadius)
, RadiusDelta(maxRadius - minRadius)
, MinValue(static_cast<vtkm::Float32>(scalarRange.Min))
{
vtkm::Float32 delta = static_cast<vtkm::Float32>(scalarRange.Max - scalarRange.Min);
if (delta != 0.f)
InverseDelta = 1.f / (delta);
else
InverseDelta = 0.f; // just map scalar to 0;
}
typedef void ControlSignature(FieldIn<>, FieldOut<>, WholeArrayIn<Scalar>);
typedef void ExecutionSignature(_1, _2, _3);
template <typename ScalarPortalType>
VTKM_EXEC void operator()(const vtkm::Id& pointId,
vtkm::Float32& radius,
const ScalarPortalType& scalars) const
{
vtkm::Float32 scalar = static_cast<vtkm::Float32>(scalars.Get(pointId));
vtkm::Float32 t = (scalar - MinValue) * InverseDelta;
radius = MinRadius + t * RadiusDelta;
}
}; //class FieldRadius
} //namespace detail
void SphereExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
const vtkm::Float32 radius)
{
this->SetPointIdsFromCoords(coords);
this->SetUniformRadius(radius);
}
void SphereExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius)
{
this->SetPointIdsFromCoords(coords);
this->SetVaryingRadius(minRadius, maxRadius, field);
}
void SphereExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::Float32 radius)
{
this->SetPointIdsFromCells(cells);
this->SetUniformRadius(radius);
}
void SphereExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius)
{
this->SetPointIdsFromCells(cells);
this->SetVaryingRadius(minRadius, maxRadius, field);
}
void SphereExtractor::SetUniformRadius(const vtkm::Float32 radius)
{
const vtkm::Id size = this->PointIds.GetNumberOfValues();
Radii.Allocate(size);
vtkm::cont::ArrayHandleConstant<vtkm::Float32> radiusHandle(radius, size);
vtkm::cont::Algorithm::Copy(radiusHandle, Radii);
}
void SphereExtractor::SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords)
{
vtkm::Id size = coords.GetData().GetNumberOfValues();
this->PointIds.Allocate(size);
vtkm::worklet::DispatcherMapField<detail::Iterator>(detail::Iterator()).Invoke(this->PointIds);
}
void SphereExtractor::SetPointIdsFromCells(const vtkm::cont::DynamicCellSet& cells)
{
using SingleType = vtkm::cont::CellSetSingleType<>;
vtkm::Id numCells = cells.GetNumberOfCells();
if (numCells == 0)
{
return;
}
//
// look for points in the cell set
//
if (cells.IsSameType(vtkm::cont::CellSetExplicit<>()))
{
vtkm::cont::ArrayHandle<vtkm::Id> points;
vtkm::worklet::DispatcherMapTopology<detail::CountPoints>(detail::CountPoints())
.Invoke(cells, points);
vtkm::Id totalPoints = 0;
totalPoints = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets);
PointIds.Allocate(totalPoints);
vtkm::worklet::DispatcherMapTopology<detail::Pointify>(detail::Pointify())
.Invoke(cells, cellOffsets, this->PointIds);
}
else if (cells.IsSameType(SingleType()))
{
SingleType pointCells = cells.Cast<SingleType>();
vtkm::UInt8 shape_id = pointCells.GetCellShape(0);
if (shape_id == vtkm::CELL_SHAPE_VERTEX)
{
this->PointIds.Allocate(numCells);
vtkm::worklet::DispatcherMapField<detail::Iterator>(detail::Iterator())
.Invoke(this->PointIds);
}
}
}
void SphereExtractor::SetVaryingRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::cont::Field& field)
{
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray = field.GetRange();
if (rangeArray.GetNumberOfValues() != 1)
{
throw vtkm::cont::ErrorBadValue("Sphere Extractor: scalar field must have one component");
}
vtkm::Range range = rangeArray.GetPortalConstControl().Get(0);
Radii.Allocate(this->PointIds.GetNumberOfValues());
vtkm::worklet::DispatcherMapField<detail::FieldRadius>(
detail::FieldRadius(minRadius, maxRadius, range))
.Invoke(this->PointIds, this->Radii, field);
}
vtkm::cont::ArrayHandle<vtkm::Id> SphereExtractor::GetPointIds()
{
return this->PointIds;
}
vtkm::cont::ArrayHandle<vtkm::Float32> SphereExtractor::GetRadii()
{
return this->Radii;
}
vtkm::Id SphereExtractor::GetNumberOfSpheres() const
{
return this->PointIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,83 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Sphere_Extractor_h
#define vtk_m_rendering_raytracing_Sphere_Extractor_h
#include <vtkm/cont/DataSet.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class SphereExtractor
{
protected:
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
vtkm::cont::ArrayHandle<vtkm::Float32> Radii;
public:
//
// Extract all nodes using a constant radius
//
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords, const vtkm::Float32 radius);
//
// Set radius based on scalar field values. Each is interpolated from min to max
//
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius);
//
// Extract all vertex shapes with constant radius
//
void ExtractCells(const vtkm::cont::DynamicCellSet& cells, vtkm::Float32 radius);
//
// Extract all vertex elements with radius based on scalar values
//
void ExtractCells(const vtkm::cont::DynamicCellSet& cells,
const vtkm::cont::Field& field,
const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius);
vtkm::cont::ArrayHandle<vtkm::Id> GetPointIds();
vtkm::cont::ArrayHandle<vtkm::Float32> GetRadii();
vtkm::Id GetNumberOfSpheres() const;
protected:
void SetUniformRadius(const vtkm::Float32 radius);
void SetVaryingRadius(const vtkm::Float32 minRadius,
const vtkm::Float32 maxRadius,
const vtkm::cont::Field& field);
void SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords);
void SetPointIdsFromCells(const vtkm::cont::DynamicCellSet& cells);
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Extractor_h

@ -0,0 +1,394 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/rendering/raytracing/BVHTraverser.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
namespace detail
{
class FindSphereAABBs : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
FindSphereAABBs() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8, _9);
template <typename PointPortalType>
VTKM_EXEC void operator()(const vtkm::Id pointId,
const vtkm::Float32& radius,
vtkm::Float32& xmin,
vtkm::Float32& ymin,
vtkm::Float32& zmin,
vtkm::Float32& xmax,
vtkm::Float32& ymax,
vtkm::Float32& zmax,
const PointPortalType& points) const
{
// cast to Float32
vtkm::Vec<vtkm::Float32, 3> point;
vtkm::Vec<vtkm::Float32, 3> temp;
point = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(pointId));
temp[0] = radius;
temp[1] = 0.f;
temp[2] = 0.f;
vtkm::Vec<vtkm::Float32, 3> p = point + temp;
//set first point to max and min
xmin = p[0];
xmax = p[0];
ymin = p[1];
ymax = p[1];
zmin = p[2];
zmax = p[2];
p = point - temp;
xmin = vtkm::Min(xmin, p[0]);
xmax = vtkm::Max(xmax, p[0]);
ymin = vtkm::Min(ymin, p[1]);
ymax = vtkm::Max(ymax, p[1]);
zmin = vtkm::Min(zmin, p[2]);
zmax = vtkm::Max(zmax, p[2]);
temp[0] = 0.f;
temp[1] = radius;
temp[2] = 0.f;
p = point + temp;
xmin = vtkm::Min(xmin, p[0]);
xmax = vtkm::Max(xmax, p[0]);
ymin = vtkm::Min(ymin, p[1]);
ymax = vtkm::Max(ymax, p[1]);
zmin = vtkm::Min(zmin, p[2]);
zmax = vtkm::Max(zmax, p[2]);
p = point - temp;
xmin = vtkm::Min(xmin, p[0]);
xmax = vtkm::Max(xmax, p[0]);
ymin = vtkm::Min(ymin, p[1]);
ymax = vtkm::Max(ymax, p[1]);
zmin = vtkm::Min(zmin, p[2]);
zmax = vtkm::Max(zmax, p[2]);
temp[0] = 0.f;
temp[1] = 0.f;
temp[2] = radius;
p = point + temp;
xmin = vtkm::Min(xmin, p[0]);
xmax = vtkm::Max(xmax, p[0]);
ymin = vtkm::Min(ymin, p[1]);
ymax = vtkm::Max(ymax, p[1]);
zmin = vtkm::Min(zmin, p[2]);
zmax = vtkm::Max(zmax, p[2]);
p = point - temp;
xmin = vtkm::Min(xmin, p[0]);
xmax = vtkm::Max(xmax, p[0]);
ymin = vtkm::Min(ymin, p[1]);
ymax = vtkm::Max(ymax, p[1]);
zmin = vtkm::Min(zmin, p[2]);
zmax = vtkm::Max(zmax, p[2]);
}
}; //class FindAABBs
template <typename Device>
class SphereLeafIntersector
{
public:
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
using IdArrayPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using FloatHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
using FloatPortal = typename FloatHandle::ExecutionTypes<Device>::PortalConst;
IdArrayPortal PointIds;
FloatPortal Radii;
SphereLeafIntersector(const IdHandle& pointIds, const FloatHandle& radii)
: PointIds(pointIds.PrepareForInput(Device()))
, Radii(radii.PrepareForInput(Device()))
{
}
template <typename PointPortalType, typename LeafPortalType, typename Precision>
VTKM_EXEC inline void IntersectLeaf(
const vtkm::Int32& currentNode,
const vtkm::Vec<Precision, 3>& origin,
const vtkm::Vec<Precision, 3>& dir,
const PointPortalType& points,
vtkm::Id& hitIndex,
Precision& closestDistance, // closest distance in this set of primitives
Precision& vtkmNotUsed(minU),
Precision& vtkmNotUsed(minV),
LeafPortalType leafs,
const Precision& minDistance) const // report intesections past this distance
{
const vtkm::Id sphereCount = leafs.Get(currentNode);
for (vtkm::Id i = 1; i <= sphereCount; ++i)
{
const vtkm::Id sphereIndex = leafs.Get(currentNode + i);
vtkm::Id pointIndex = PointIds.Get(sphereIndex);
vtkm::Float32 radius = Radii.Get(sphereIndex);
vtkm::Vec<Precision, 3> center = vtkm::Vec<Precision, 3>(points.Get(pointIndex));
vtkm::Vec<Precision, 3> l = center - origin;
Precision dot1 = vtkm::dot(l, dir);
if (dot1 >= 0)
{
Precision d = vtkm::dot(l, l) - dot1 * dot1;
Precision r2 = radius * radius;
if (d <= r2)
{
Precision tch = vtkm::Sqrt(r2 - d);
Precision t0 = dot1 - tch;
//float t1 = dot1+tch; /* if t1 is > 0 and t0<0 then the ray is inside the sphere.
if (t0 < closestDistance && t0 > minDistance)
{
hitIndex = pointIndex;
closestDistance = t0;
}
}
}
} // for
}
};
struct IntersectFunctor
{
template <typename Device, typename Precision>
VTKM_CONT bool operator()(Device,
SphereIntersector* self,
Ray<Precision>& rays,
bool returnCellIndex)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->IntersectRaysImp(Device(), rays, returnCellIndex);
return true;
}
};
class CalculateNormals : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CalculateNormals() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
template <typename Precision, typename PointPortalType, typename IndicesPortalType>
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
const vtkm::Vec<Precision, 3>& intersection,
Precision& normalX,
Precision& normalY,
Precision& normalZ,
const PointPortalType& points,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
vtkm::Id pointId = indicesPortal.Get(hitIndex);
vtkm::Vec<Precision, 3> center = points.Get(pointId);
vtkm::Vec<Precision, 3> normal = intersection - center;
vtkm::Normalize(normal);
//flip the normal if its pointing the wrong way
normalX = normal[0];
normalY = normal[1];
normalZ = normal[2];
}
}; //class CalculateNormals
template <typename Precision>
class GetScalar : public vtkm::worklet::WorkletMapField
{
private:
Precision MinScalar;
Precision invDeltaScalar;
public:
VTKM_CONT
GetScalar(const vtkm::Float32& minScalar, const vtkm::Float32& maxScalar)
: MinScalar(minScalar)
{
//Make sure the we don't divide by zero on
//something like an iso-surface
if (maxScalar - MinScalar != 0.f)
invDeltaScalar = 1.f / (maxScalar - MinScalar);
else
invDeltaScalar = 1.f / minScalar;
}
typedef void ControlSignature(FieldIn<>,
FieldInOut<>,
WholeArrayIn<ScalarRenderingTypes>,
WholeArrayIn<>);
typedef void ExecutionSignature(_1, _2, _3, _4);
template <typename ScalarPortalType, typename IndicesPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
Precision& scalar,
const ScalarPortalType& scalars,
const IndicesPortalType& indicesPortal) const
{
if (hitIndex < 0)
return;
vtkm::Id pointId = indicesPortal.Get(hitIndex);
scalar = Precision(scalars.Get(pointId));
//normalize
scalar = (scalar - MinScalar) * invDeltaScalar;
}
}; //class GetScalar
} // namespace detail
SphereIntersector::SphereIntersector()
: ShapeIntersector()
{
}
SphereIntersector::~SphereIntersector()
{
}
void SphereIntersector::SetData(const vtkm::cont::CoordinateSystem& coords,
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
vtkm::cont::ArrayHandle<vtkm::Float32> radii)
{
this->PointIds = pointIds;
this->Radii = radii;
this->CoordsHandle = coords;
AABBs AABB;
vtkm::worklet::DispatcherMapField<detail::FindSphereAABBs>(detail::FindSphereAABBs())
.Invoke(PointIds,
Radii,
AABB.xmins,
AABB.ymins,
AABB.zmins,
AABB.xmaxs,
AABB.ymaxs,
AABB.zmaxs,
CoordsHandle);
this->SetAABBs(AABB);
}
void SphereIntersector::IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
void SphereIntersector::IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex)
{
vtkm::cont::TryExecute(detail::IntersectFunctor(), this, rays, returnCellIndex);
}
template <typename Device, typename Precision>
void SphereIntersector::IntersectRaysImp(Device,
Ray<Precision>& rays,
bool vtkmNotUsed(returnCellIndex))
{
detail::SphereLeafIntersector<Device> leafIntersector(this->PointIds, Radii);
BVHTraverser<detail::SphereLeafIntersector> traverser;
traverser.IntersectRays(rays, this->BVH, leafIntersector, this->CoordsHandle, Device());
RayOperations::UpdateRayStatus(rays);
}
template <typename Precision>
void SphereIntersector::IntersectionDataImp(Ray<Precision>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
ShapeIntersector::IntersectionPoint(rays);
bool isSupportedField =
(scalarField->GetAssociation() == vtkm::cont::Field::Association::POINTS ||
scalarField->GetAssociation() == vtkm::cont::Field::Association::CELL_SET);
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue(
"SphereIntersector: Field not accociated with a cell set or field");
vtkm::worklet::DispatcherMapField<detail::CalculateNormals>(detail::CalculateNormals())
.Invoke(rays.HitIdx,
rays.Intersection,
rays.NormalX,
rays.NormalY,
rays.NormalZ,
CoordsHandle,
PointIds);
vtkm::worklet::DispatcherMapField<detail::GetScalar<Precision>>(
detail::GetScalar<Precision>(vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
.Invoke(rays.HitIdx, rays.Scalar, *scalarField, PointIds);
}
void SphereIntersector::IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
void SphereIntersector::IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange)
{
IntersectionDataImp(rays, scalarField, scalarRange);
}
vtkm::Id SphereIntersector::GetNumberOfShapes() const
{
return PointIds.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,73 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Sphere_Intersector_h
#define vtk_m_rendering_raytracing_Sphere_Intersector_h
#include <vtkm/rendering/raytracing/ShapeIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class SphereIntersector : public ShapeIntersector
{
protected:
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
vtkm::cont::ArrayHandle<vtkm::Float32> Radii;
public:
SphereIntersector();
virtual ~SphereIntersector() override;
void SetData(const vtkm::cont::CoordinateSystem& coords,
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
vtkm::cont::ArrayHandle<vtkm::Float32> radii);
void IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex = false) override;
void IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex = false) override;
template <typename Device, typename Precision>
void IntersectRaysImp(Device, Ray<Precision>& rays, bool returnCellIndex);
template <typename Precision>
void IntersectionDataImp(Ray<Precision>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange);
void IntersectionData(Ray<vtkm::Float32>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) override;
void IntersectionData(Ray<vtkm::Float64>& rays,
const vtkm::cont::Field* scalarField,
const vtkm::Range& scalarRange) override;
vtkm::Id GetNumberOfShapes() const override;
}; // class ShapeIntersector
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Shape_Intersector_h

@ -0,0 +1,48 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/rendering/internal/RunTriangulator.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
void TriangleExtractor::ExtractCells(const vtkm::cont::DynamicCellSet& cells)
{
vtkm::Id numberOfTriangles;
vtkm::rendering::internal::RunTriangulator(cells, this->Triangles, numberOfTriangles);
}
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> TriangleExtractor::GetTriangles()
{
return this->Triangles;
}
vtkm::Id TriangleExtractor::GetNumberOfTriangles() const
{
return this->Triangles.GetNumberOfValues();
}
}
}
} //namespace vtkm::rendering::raytracing

@ -0,0 +1,46 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#ifndef vtk_m_rendering_raytracing_Triangle_Extractor_h
#define vtk_m_rendering_raytracing_Triangle_Extractor_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/vtkm_rendering_export.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT TriangleExtractor
{
protected:
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Triangles; // (cellid, v0, v1, v2)
public:
void ExtractCells(const vtkm::cont::DynamicCellSet& cells);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> GetTriangles();
vtkm::Id GetNumberOfTriangles() const;
}; // class TriangleExtractor
}
}
} //namespace vtkm::rendering::raytracing
#endif //vtk_m_rendering_raytracing_Triangle_Extractor_h

@ -0,0 +1,68 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperPoint.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/rendering/testing/RenderTest.h>
namespace
{
void RenderTests()
{
using M = vtkm::rendering::MapperPoint;
using C = vtkm::rendering::CanvasRayTracer;
using V3 = vtkm::rendering::View3D;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::ColorTable colorTable("inferno");
M mapper;
std::cout << "Testing uniform delta raduis\n";
mapper.SetRadiusDelta(4.0f);
vtkm::rendering::testing::Render<M, C, V3>(
mapper, maker.Make3DUniformDataSet1(), "pointvar", colorTable, "points_vr_reg3D.pnm");
// restore defaults
mapper.SetRadiusDelta(0.5f);
mapper.UseVariableRadius(false);
mapper.SetRadius(0.2f);
vtkm::rendering::testing::Render<M, C, V3>(
mapper, maker.Make3DUniformDataSet1(), "pointvar", colorTable, "points_reg3D.pnm");
mapper.UseCells();
mapper.SetRadius(1.f);
vtkm::rendering::testing::Render<M, C, V3>(
mapper, maker.Make3DExplicitDataSet7(), "cellvar", colorTable, "spheres.pnm");
}
} //namespace
int UnitTestMapperPoints(int, char* [])
{
return vtkm::cont::testing::Testing::Run(RenderTests);
}

@ -0,0 +1,64 @@
//============================================================================
// 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.
//
// Copyright 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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.
//============================================================================
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperQuad.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/rendering/testing/RenderTest.h>
namespace
{
void RenderTests()
{
typedef vtkm::rendering::MapperQuad M;
typedef vtkm::rendering::CanvasRayTracer C;
typedef vtkm::rendering::View3D V3;
typedef vtkm::rendering::View2D V2;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::ColorTable colorTable("inferno");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRegularDataSet0(), "pointvar", colorTable, "rt_reg3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRectilinearDataSet0(), "pointvar", colorTable, "rt_rect3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSet4(), "pointvar", colorTable, "rt_expl3D.pnm");
vtkm::rendering::testing::Render<M, C, V2>(
maker.Make2DUniformDataSet1(), "pointvar", colorTable, "uni2D.pnm");
//hexahedron, wedge, pyramid, tetrahedron
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSet5(), "cellvar", colorTable, "rt_hex3d.pnm");
}
} //namespace
int UnitTestMapperQuads(int, char* [])
{
return vtkm::cont::testing::Testing::Run(RenderTests);
}