refactoring ray tracing

This commit is contained in:
mclarsen 2018-09-10 19:25:42 -07:00
parent bc9772021c
commit 1c2f78ca92
43 changed files with 2238 additions and 4192 deletions

@ -28,9 +28,10 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/internal/RunTriangulator.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/RayTracer.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
#include <vtkm/exec/FunctorBase.h>
@ -66,18 +67,24 @@ struct BenchRayTracing
camera.ResetToBounds(bounds);
vtkm::cont::DynamicCellSet cellset = Data.GetCellSet();
vtkm::rendering::internal::RunTriangulator(cellset, Indices, NumberOfTriangles);
vtkm::rendering::raytracing::TriangleExtractor triExtractor;
triExtractor.ExtractCells(cellset);
vtkm::rendering::raytracing::TriangleIntersector* triIntersector =
new vtkm::rendering::raytracing::TriangleIntersector();
triIntersector->SetData(Coords, triExtractor.GetTriangles());
Tracer.AddShapeIntersector(triIntersector);
vtkm::rendering::CanvasRayTracer canvas(1920, 1080);
RayCamera.SetParameters(camera, canvas);
RayCamera.CreateRays(Rays, Coords);
RayCamera.CreateRays(Rays, Coords.GetBounds());
Rays.Buffers.at(0).InitConst(0.f);
vtkm::cont::Field field = Data.GetField("pointvar");
vtkm::Range range = field.GetRange().GetPortalConstControl().Get(0);
Tracer.SetData(Coords.GetData(), Indices, field, NumberOfTriangles, range, bounds);
Tracer.SetField(field, range);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 4>> temp;
vtkm::cont::ColorTable table("cool to warm");
@ -107,7 +114,7 @@ struct BenchRayTracing
{
vtkm::cont::Timer<VTKM_DEFAULT_DEVICE_ADAPTER_TAG> timer;
RayCamera.CreateRays(Rays, Coords);
RayCamera.CreateRays(Rays, Coords.GetBounds());
Tracer.Render(Rays);
return timer.GetElapsedTime();

@ -74,6 +74,9 @@ public:
vtkm::cont::DataSet Make3DExplicitDataSet4();
vtkm::cont::DataSet Make3DExplicitDataSet5();
vtkm::cont::DataSet Make3DExplicitDataSet6();
vtkm::cont::DataSet Make3DExplicitDataSet7();
vtkm::cont::DataSet Make3DExplicitDataSet8();
vtkm::cont::DataSet Make3DExplicitDataSetZoo();
vtkm::cont::DataSet Make3DExplicitDataSetPolygonal();
vtkm::cont::DataSet Make3DExplicitDataSetCowNose();
};
@ -924,6 +927,400 @@ inline vtkm::cont::DataSet MakeTestDataSet::Make3DExplicitDataSet6()
return dataSet;
}
inline vtkm::cont::DataSet MakeTestDataSet::Make3DExplicitDataSetZoo()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
vtkm::cont::DataSetFieldAdd dsf;
// Coordinates
const int nVerts = 30;
const int nCells = 27;
using CoordType = vtkm::Vec<vtkm::Float32, 3>;
std::vector<CoordType> coords =
{ { 0.00f, 0.00f, 0.00f }, { 1.00f, 0.00f, 0.00f }, { 2.00f, 0.00f, 0.00f },
{ 0.00f, 0.00f, 1.00f }, { 1.00f, 0.00f, 1.00f }, { 2.00f, 0.00f, 1.00f },
{ 0.00f, 1.00f, 0.00f }, { 1.00f, 1.00f, 0.00f }, { 2.00f, 1.00f, 0.00f },
{ 0.00f, 1.00f, 1.00f }, { 1.00f, 1.00f, 1.00f }, { 2.00f, 1.00f, 1.00f },
{ 0.00f, 2.00f, 0.00f }, { 1.00f, 2.00f, 0.00f }, { 2.00f, 2.00f, 0.00f },
{ 0.00f, 2.00f, 1.00f }, { 1.00f, 2.00f, 1.00f }, { 2.00f, 2.00f, 1.00f },
{ 1.00f, 3.00f, 1.00f }, { 2.75f, 0.00f, 1.00f }, { 3.00f, 0.00f, 0.75f },
{ 3.00f, 0.25f, 1.00f }, { 3.00f, 1.00f, 1.00f }, { 3.00f, 1.00f, 0.00f },
{ 2.57f, 2.00f, 1.00f }, { 3.00f, 1.75f, 1.00f }, { 3.00f, 1.75f, 0.75f },
{ 3.00f, 0.00f, 0.00f }, { 2.57f, 0.42f, 0.57f }, { 2.59f, 1.43f, 0.71f } };
// Connectivity
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numindices;
std::vector<vtkm::Id> conn;
shapes.push_back(vtkm::CELL_SHAPE_HEXAHEDRON);
numindices.push_back(8);
conn.push_back(0);
conn.push_back(3);
conn.push_back(4);
conn.push_back(1);
conn.push_back(6);
conn.push_back(9);
conn.push_back(10);
conn.push_back(7);
shapes.push_back(vtkm::CELL_SHAPE_HEXAHEDRON);
numindices.push_back(8);
conn.push_back(1);
conn.push_back(4);
conn.push_back(5);
conn.push_back(2);
conn.push_back(7);
conn.push_back(10);
conn.push_back(11);
conn.push_back(8);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(23);
conn.push_back(26);
conn.push_back(24);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(24);
conn.push_back(26);
conn.push_back(25);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(8);
conn.push_back(17);
conn.push_back(11);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(17);
conn.push_back(24);
conn.push_back(25);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(24);
conn.push_back(17);
conn.push_back(8);
conn.push_back(23);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(23);
conn.push_back(8);
conn.push_back(11);
conn.push_back(22);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(25);
conn.push_back(22);
conn.push_back(11);
conn.push_back(17);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(26);
conn.push_back(23);
conn.push_back(22);
conn.push_back(25);
conn.push_back(29);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(23);
conn.push_back(8);
conn.push_back(2);
conn.push_back(27);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(22);
conn.push_back(11);
conn.push_back(8);
conn.push_back(23);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(11);
conn.push_back(5);
conn.push_back(2);
conn.push_back(8);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(21);
conn.push_back(19);
conn.push_back(5);
conn.push_back(11);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(11);
conn.push_back(22);
conn.push_back(21);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(5);
conn.push_back(19);
conn.push_back(20);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(23);
conn.push_back(27);
conn.push_back(20);
conn.push_back(21);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(20);
conn.push_back(27);
conn.push_back(2);
conn.push_back(5);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(19);
conn.push_back(21);
conn.push_back(20);
conn.push_back(28);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(7);
conn.push_back(6);
conn.push_back(12);
conn.push_back(13);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(6);
conn.push_back(9);
conn.push_back(15);
conn.push_back(12);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_PYRAMID);
numindices.push_back(5);
conn.push_back(6);
conn.push_back(7);
conn.push_back(10);
conn.push_back(9);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_TETRA);
numindices.push_back(4);
conn.push_back(12);
conn.push_back(15);
conn.push_back(16);
conn.push_back(18);
shapes.push_back(vtkm::CELL_SHAPE_WEDGE);
numindices.push_back(6);
conn.push_back(8);
conn.push_back(14);
conn.push_back(17);
conn.push_back(7);
conn.push_back(13);
conn.push_back(16);
shapes.push_back(vtkm::CELL_SHAPE_WEDGE);
numindices.push_back(6);
conn.push_back(11);
conn.push_back(8);
conn.push_back(17);
conn.push_back(10);
conn.push_back(7);
conn.push_back(16);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates", "cells");
// Field data
vtkm::Float32 pointvar[nVerts] =
{ 4.0, 5.0f, 9.5f, 5.5f, 6.0f, 9.5f, 5.0f, 5.5f, 5.7f, 6.5f, 6.4f, 6.9f, 6.6f, 6.1f, 7.1f,
7.2f, 7.3f, 7.4f, 9.1f, 9.2f, 9.3f, 5.4f, 9.5f, 9.6f, 6.7f, 9.8f, 6.0f, 4.3f, 4.9f, 4.1f };
vtkm::Float32 cellvar[nCells] =
{ 4.0f, 5.0f, 9.5f, 5.5f, 6.0f, 9.5f, 5.0f, 5.5f, 5.7f, 6.5f, 6.4f, 6.9f, 6.6f, 6.1f,
7.1f, 7.2f, 7.3f, 7.4f, 9.1f, 9.2f, 9.3f, 5.4f, 9.5f, 9.6f, 6.7f, 9.8f, 6.0f };
dsf.AddPointField(dataSet, "pointvar", pointvar, nVerts);
dsf.AddCellField(dataSet, "cellvar", cellvar, nCells, "cells");
return dataSet;
}
inline vtkm::cont::DataSet MakeTestDataSet::Make3DExplicitDataSet7()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
vtkm::cont::DataSetFieldAdd dsf;
// Coordinates
const int nVerts = 8;
const int nCells = 8;
using CoordType = vtkm::Vec<vtkm::Float32, 3>;
std::vector<CoordType> coords = { { -0.707f, -0.354f, -0.354f }, { 0.000f, -0.854f, 0.146f },
{ 0.000f, -0.146f, 0.854f }, { -0.707f, 0.354f, 0.354f },
{ 10.0f, 10.0f, 10.0f }, { 5.0f, 5.0f, 5.0f },
{ 0.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, -2.0f } };
// Connectivity
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numindices;
std::vector<vtkm::Id> conn;
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(0);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(1);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(2);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(3);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(4);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(5);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(6);
shapes.push_back(vtkm::CELL_SHAPE_VERTEX);
numindices.push_back(1);
conn.push_back(7);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates", "cells");
// Field data
vtkm::Float32 pointvar[nVerts] = { 100.0f, 78.0f, 49.0f, 17.0f, 10.f, 20.f, 33.f, 52.f };
vtkm::Float32 cellvar[nCells] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f };
dsf.AddPointField(dataSet, "pointvar", pointvar, nVerts);
dsf.AddCellField(dataSet, "cellvar", cellvar, nCells, "cells");
return dataSet;
}
inline vtkm::cont::DataSet MakeTestDataSet::Make3DExplicitDataSet8()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
vtkm::cont::DataSetFieldAdd dsf;
// Coordinates
const int nVerts = 8;
const int nCells = 10;
using CoordType = vtkm::Vec<vtkm::Float32, 3>;
std::vector<CoordType> coords = { { -0.707f, -0.354f, -0.354f }, { 0.000f, -0.854f, 0.146f },
{ 0.000f, -0.146f, 0.854f }, { -0.707f, 0.354f, 0.354f },
{ 10.0f, 10.0f, 10.0f }, { 5.0f, 5.0f, 5.0f },
{ 0.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, -2.0f } };
// Connectivity
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numindices;
std::vector<vtkm::Id> conn;
//I need two triangles because the leaf needs four nodes otherwise segfault?
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(0);
conn.push_back(1);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(1);
conn.push_back(2);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(2);
conn.push_back(3);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(3);
conn.push_back(4);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(4);
conn.push_back(5);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(5);
conn.push_back(6);
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numindices.push_back(2);
conn.push_back(6);
conn.push_back(7);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
numindices.push_back(3);
conn.push_back(2);
conn.push_back(5);
conn.push_back(4);
shapes.push_back(vtkm::CELL_SHAPE_TRIANGLE);
numindices.push_back(3);
conn.push_back(4);
conn.push_back(5);
conn.push_back(6);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates", "cells");
// Field data
vtkm::Float32 pointvar[nVerts] = { 100.0f, 78.0f, 49.0f, 17.0f, 94.0f, 71.0f, 47.0f, 57.0f };
vtkm::Float32 cellvar[nCells] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
dsf.AddPointField(dataSet, "pointvar", pointvar, nVerts);
dsf.AddCellField(dataSet, "cellvar", cellvar, nCells, "cells");
return dataSet;
}
inline vtkm::cont::DataSet MakeTestDataSet::Make3DExplicitDataSetPolygonal()
{
vtkm::cont::DataSet dataSet;

@ -59,15 +59,20 @@ set(headers
ColorBarAnnotation.h
ColorLegendAnnotation.h
ConnectivityProxy.h
Cylinderizer.h
DecodePNG.h
LineRenderer.h
MatrixHelpers.h
Scene.h
Mapper.h
MapperCylinder.h
MapperPoint.h
MapperQuad.h
MapperRayTracer.h
MapperVolume.h
MapperConnectivity.h
MapperWireframer.h
Quadralizer.h
TextAnnotation.h
TextAnnotationBillboard.h
TextAnnotationScreen.h
@ -96,8 +101,12 @@ set(sources
DecodePNG.cxx
LineRenderer.cxx
MapperConnectivity.cxx
MapperCylinder.cxx
MapperPoint.cxx
MapperQuad.cxx
MapperRayTracer.cxx
MapperVolume.cxx
#MapperWireframer.cxx
Scene.cxx
TextAnnotation.cxx
TextAnnotationBillboard.cxx
@ -107,10 +116,6 @@ set(sources
View2D.cxx
View3D.cxx
WorldAnnotator.cxx
raytracing/ConnectivityBase.cxx
raytracing/ConnectivityTracerBase.cxx
raytracing/ConnectivityTracerFactory.cxx
raytracing/Logger.cxx
)
@ -161,8 +166,18 @@ set(device_sources
raytracing/Camera.cxx
raytracing/ChannelBuffer.cxx
raytracing/ConnectivityTracer.cxx
raytracing/RayOperations.cxx
raytracing/CylinderExtractor.cxx
raytracing/CylinderIntersector.cxx
raytracing/MeshConnectivityBuilder.cxx
raytracing/MeshConnectivityContainers.cxx
raytracing/QuadExtractor.cxx
raytracing/QuadIntersector.cxx
raytracing/RayTracer.cxx
raytracing/RayOperations.cxx
raytracing/ShapeIntersector.cxx
raytracing/SphereExtractor.cxx
raytracing/SphereIntersector.cxx
raytracing/TriangleExtractor.cxx
raytracing/VolumeRendererStructured.cxx
)

@ -313,8 +313,11 @@ void Canvas::Activate()
void Canvas::Clear()
{
vtkm::worklet::DispatcherMapField<internal::ClearBuffers>().Invoke(this->GetColorBuffer(),
this->GetDepthBuffer());
// TODO: Should the rendering library support policies or some other way to
// configure with custom devices?
internal::ClearBuffers worklet;
vtkm::worklet::DispatcherMapField<internal::ClearBuffers> dispatcher(worklet);
dispatcher.Invoke(this->GetColorBuffer(), this->GetDepthBuffer());
}
void Canvas::Finish()
@ -323,9 +326,9 @@ void Canvas::Finish()
void Canvas::BlendBackground()
{
vtkm::worklet::DispatcherMapField<internal::BlendBackground>(
this->GetBackgroundColor().Components)
.Invoke(this->GetColorBuffer());
internal::BlendBackground worklet(GetBackgroundColor().Components);
vtkm::worklet::DispatcherMapField<internal::BlendBackground> dispatcher(worklet);
dispatcher.Invoke(this->GetColorBuffer());
}
void Canvas::ResizeBuffers(vtkm::Id width, vtkm::Id height)

@ -21,7 +21,7 @@
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/ConnectivityProxy.h>
#include <vtkm/rendering/Mapper.h>
#include <vtkm/rendering/raytracing/ConnectivityTracerFactory.h>
#include <vtkm/rendering/raytracing/ConnectivityTracer.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
@ -34,9 +34,9 @@ struct ConnectivityProxy::InternalsType
{
protected:
using ColorMapType = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>;
using BaseType = vtkm::rendering::raytracing::ConnectivityBase;
using TracerType = vtkm::rendering::raytracing::ConnectivityTracer;
BaseType* Tracer;
TracerType Tracer;
vtkm::cont::Field ScalarField;
vtkm::cont::Field EmissionField;
vtkm::cont::DynamicCellSet Cells;
@ -48,29 +48,6 @@ protected:
vtkm::Range ScalarRange;
bool CompositeBackground;
struct BoundsFunctor
{
vtkm::rendering::ConnectivityProxy::InternalsType* Internals;
const vtkm::cont::CoordinateSystem& Coordinates;
VTKM_CONT
BoundsFunctor(vtkm::rendering::ConnectivityProxy::InternalsType* self,
const vtkm::cont::CoordinateSystem& coordinates)
: Internals(self)
, Coordinates(coordinates)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
Internals->SpatialBounds = Internals->Coords.GetBounds();
return true;
}
};
public:
InternalsType(vtkm::cont::DataSet& dataSet)
{
@ -87,11 +64,9 @@ public:
{
this->SetScalarField(Dataset.GetField(0).GetName());
}
Tracer = raytracing::ConnectivityTracerFactory::CreateTracer(Cells, Coords);
}
~InternalsType() { delete Tracer; }
~InternalsType() {}
void SetSampleDistance(const vtkm::Float32& distance)
{
@ -100,7 +75,7 @@ public:
std::cout << "Volume Tracer Error: must set volume mode before setting sample dist\n";
return;
}
Tracer->SetSampleDistance(distance);
Tracer.SetSampleDistance(distance);
}
VTKM_CONT
@ -120,14 +95,14 @@ public:
VTKM_CONT
void SetColorMap(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colormap)
{
Tracer->SetColorMap(colormap);
Tracer.SetColorMap(colormap);
}
VTKM_CONT
void SetCompositeBackground(bool on) { CompositeBackground = on; }
VTKM_CONT
void SetDebugPrints(bool on) { Tracer->SetDebugOn(on); }
void SetDebugPrints(bool vtkmNotUsed(on)) { /*Tracer->SetDebugOn(on);*/}
VTKM_CONT
void SetEmissionField(const std::string& fieldName)
@ -155,15 +130,18 @@ public:
if (Mode == VOLUME_MODE)
{
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
Tracer.SetVolumeData(this->ScalarField, this->ScalarRange, this->Cells, this->Coords);
}
else
{
Tracer->SetEnergyData(
this->ScalarField, rays.Buffers.at(0).GetNumChannels(), this->EmissionField);
Tracer.SetEnergyData(this->ScalarField,
rays.Buffers.at(0).GetNumChannels(),
this->Cells,
this->Coords,
this->EmissionField);
}
Tracer->Trace(rays);
Tracer.Trace(rays);
}
VTKM_CONT
@ -171,14 +149,18 @@ public:
{
if (Mode == VOLUME_MODE)
{
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
Tracer.SetVolumeData(this->ScalarField, this->ScalarRange, this->Cells, this->Coords);
}
else
{
Tracer->SetEnergyData(
this->ScalarField, rays.Buffers.at(0).GetNumChannels(), this->EmissionField);
Tracer.SetEnergyData(this->ScalarField,
rays.Buffers.at(0).GetNumChannels(),
this->Cells,
this->Coords,
this->EmissionField);
}
Tracer->Trace(rays);
Tracer.Trace(rays);
}
VTKM_CONT
@ -193,20 +175,20 @@ public:
vtkm::rendering::raytracing::Camera rayCamera;
rayCamera.SetParameters(camera, *canvas);
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
rayCamera.CreateRays(rays, this->Coords);
rayCamera.CreateRays(rays, this->Coords.GetBounds());
rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(rays, camera, *canvas);
if (Mode == VOLUME_MODE)
{
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
Tracer.SetVolumeData(this->ScalarField, this->ScalarRange, this->Cells, this->Coords);
}
else
{
throw vtkm::cont::ErrorBadValue("ENERGY MODE Not implemented for this use case\n");
}
Tracer->Trace(rays);
Tracer.Trace(rays);
canvas->WriteToCanvas(rays, rays.Buffers.at(0).Buffer, camera);
if (CompositeBackground)

@ -24,10 +24,8 @@
#include <vtkm/rendering/MapperConnectivity.h>
#include <vtkm/rendering/View.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/ConnectivityTracerFactory.h>
#include <cstdlib>
#include <vtkm/rendering/raytracing/Camera.h>
namespace vtkm
{

@ -29,6 +29,9 @@
#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
{
@ -91,25 +94,38 @@ void MapperRayTracer::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
logger->OpenLogEntry("mapper_ray_tracer");
vtkm::cont::Timer<> tot_timer;
vtkm::cont::Timer<> timer;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> indices;
vtkm::Id numberOfTriangles;
vtkm::rendering::internal::RunTriangulator(cellset, indices, numberOfTriangles);
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("triangulator", time);
// make sure we start fresh
this->Internals->Tracer.Clear();
//
// Add supported shapes
//
vtkm::Bounds shapeBounds;
raytracing::TriangleExtractor triExtractor;
triExtractor.ExtractCells(cellset);
if (triExtractor.GetNumberOfTriangles() > 0)
{
raytracing::TriangleIntersector* triIntersector = new raytracing::TriangleIntersector();
triIntersector->SetData(coords, triExtractor.GetTriangles());
this->Internals->Tracer.AddShapeIntersector(triIntersector);
shapeBounds.Include(triIntersector->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, coords);
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);
vtkm::Bounds dataBounds = coords.GetBounds();
vtkm::cont::Field& field = const_cast<vtkm::cont::Field&>(scalarField);
this->Internals->Tracer.SetData(
coords.GetData(), indices, field, numberOfTriangles, scalarRange, dataBounds);
this->Internals->Tracer.SetField(scalarField, scalarRange);
this->Internals->Tracer.SetColorMap(this->ColorMap);
this->Internals->Tracer.Render(this->Internals->Rays);
@ -123,7 +139,7 @@ void MapperRayTracer::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
this->Internals->Canvas->BlendBackground();
}
time = timer.GetElapsedTime();
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("write_to_canvas", time);
time = tot_timer.GetElapsedTime();
logger->CloseLogEntry(time);

@ -114,7 +114,7 @@ void MapperVolume::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
rayCamera.SetParameters(camera, *this->Internals->Canvas);
rayCamera.CreateRays(rays, coords);
rayCamera.CreateRays(rays, coords.GetBounds());
rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(rays, camera, *this->Internals->Canvas);

@ -21,7 +21,7 @@
#ifndef vtk_m_rendering_Texture2D_h
#define vtk_m_rendering_Texture2D_h
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
@ -77,7 +77,7 @@ public:
// We do not know the lifetime of the underlying data source of input `data`. Since it might
// be from a shallow copy of the data source, we make a deep copy of the input data and keep
// it's portal. The copy operation is very fast.
vtkm::cont::ArrayCopy(data, Data);
vtkm::cont::Algorithm::Copy(data, Data);
}
VTKM_CONT

@ -20,11 +20,12 @@
#ifndef vtk_m_rendering_Triangulator_h
#define vtk_m_rendering_Triangulator_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/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
@ -36,35 +37,11 @@ namespace rendering
///
/// This class creates a array of triangle indices from both 3D and 2D
/// explicit cell sets. This list can serve as input to opengl and the
/// ray tracer scene renderers. TODO: Add regular grid support
/// ray tracer scene renderers.
///
template <typename Device>
class Triangulator
{
private:
using IdArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using Vec4ArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
using Vec4ArrayPortalType = typename Vec4ArrayHandle::ExecutionTypes<Device>::Portal;
using IdPortalConstType = typename IdArrayHandle::ExecutionTypes<Device>::PortalConst;
public:
template <class T>
class MemSet : public vtkm::worklet::WorkletMapField
{
T Value;
public:
VTKM_CONT
MemSet(T value)
: Value(value)
{
}
using ControlSignature = void(FieldOut<>);
using ExecutionSignature = void(_1);
VTKM_EXEC
void operator()(T& outValue) const { outValue = Value; }
}; //class MemSet
class CountTriangles : public vtkm::worklet::WorkletMapPointToCell
{
public:
@ -108,27 +85,21 @@ public:
template <int DIM>
class TrianglulateStructured : public vtkm::worklet::WorkletMapPointToCell
{
private:
Vec4ArrayPortalType OutputIndices;
public:
using ControlSignature = void(CellSetIn cellset, FieldInTo<>);
using ExecutionSignature = void(FromIndices, _2);
//using InputDomain = _1;
using ControlSignature = void(CellSetIn cellset, FieldInTo<>, WholeArrayOut<>);
using ExecutionSignature = void(FromIndices, _2, _3);
VTKM_CONT
TrianglulateStructured(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& outputIndices)
{
this->OutputIndices =
outputIndices.PrepareForOutput(outputIndices.GetNumberOfValues(), Device());
}
TrianglulateStructured() {}
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
#endif
//TODO: Remove the if/then with templates.
template <typename CellNodeVecType>
VTKM_EXEC void operator()(const CellNodeVecType& cellIndices, const vtkm::Id& cellIndex) const
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void operator()(const CellNodeVecType& cellIndices,
const vtkm::Id& cellIndex,
OutIndicesPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 4> triangle;
if (DIM == 2)
@ -139,10 +110,10 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellIndex;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
// 0-3-2
triangle[2] = cellIndices[3];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
}
else if (DIM == 3)
{
@ -152,62 +123,62 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[5];
triangle[0] = cellIndex;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[5];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 4, triangle);
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 5, triangle);
outputIndices.Set(triangleOffset + 5, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 6, triangle);
outputIndices.Set(triangleOffset + 6, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 7, triangle);
outputIndices.Set(triangleOffset + 7, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 8, triangle);
outputIndices.Set(triangleOffset + 8, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 9, triangle);
outputIndices.Set(triangleOffset + 9, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 10, triangle);
outputIndices.Set(triangleOffset + 10, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 11, triangle);
outputIndices.Set(triangleOffset + 11, triangle);
}
}
#if defined(VTKM_MSVC)
@ -303,24 +274,19 @@ public:
class Trianglulate : public vtkm::worklet::WorkletMapPointToCell
{
private:
Vec4ArrayPortalType OutputIndices;
public:
VTKM_CONT
Trianglulate(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& outputIndices,
const vtkm::Id& size)
{
this->OutputIndices = outputIndices.PrepareForOutput(size, Device());
}
using ControlSignature = void(CellSetIn cellset, FieldInCell<>);
using ExecutionSignature = void(_2, CellShape, PointIndices, WorkIndex);
Trianglulate() {}
using ControlSignature = void(CellSetIn cellset, FieldInCell<>, WholeArrayOut<>);
using ExecutionSignature = void(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType>
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& triangleOffset,
vtkm::CellShapeTagQuad vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId) const
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 4> triangle;
@ -329,17 +295,18 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[2] = cellIndices[3];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
}
template <typename VecType>
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& triangleOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId) const
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 4> triangle;
@ -347,69 +314,70 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[5];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[5];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 4, triangle);
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 5, triangle);
outputIndices.Set(triangleOffset + 5, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 6, triangle);
outputIndices.Set(triangleOffset + 6, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 7, triangle);
outputIndices.Set(triangleOffset + 7, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 8, triangle);
outputIndices.Set(triangleOffset + 8, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 9, triangle);
outputIndices.Set(triangleOffset + 9, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 10, triangle);
outputIndices.Set(triangleOffset + 10, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 11, triangle);
outputIndices.Set(triangleOffset + 11, triangle);
}
template <typename VecType>
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& triangleOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId) const
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 4> triangle;
@ -420,7 +388,7 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
}
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
@ -429,10 +397,10 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[2] = cellIndices[3];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
}
if (shapeType.Id == vtkm::CELL_SHAPE_TETRA)
{
@ -440,22 +408,22 @@ public:
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[1];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
}
if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
{
@ -463,62 +431,62 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[5];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[5];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 4, triangle);
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 5, triangle);
outputIndices.Set(triangleOffset + 5, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 6, triangle);
outputIndices.Set(triangleOffset + 6, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[7];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 7, triangle);
outputIndices.Set(triangleOffset + 7, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 8, triangle);
outputIndices.Set(triangleOffset + 8, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 9, triangle);
outputIndices.Set(triangleOffset + 9, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[6];
OutputIndices.Set(triangleOffset + 10, triangle);
outputIndices.Set(triangleOffset + 10, triangle);
triangle[1] = cellIndices[4];
triangle[2] = cellIndices[6];
triangle[3] = cellIndices[7];
OutputIndices.Set(triangleOffset + 11, triangle);
outputIndices.Set(triangleOffset + 11, triangle);
}
if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
{
@ -526,42 +494,42 @@ public:
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[2];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[0];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[5];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[5];
OutputIndices.Set(triangleOffset + 4, triangle);
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[5];
triangle[3] = cellIndices[2];
OutputIndices.Set(triangleOffset + 5, triangle);
outputIndices.Set(triangleOffset + 5, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 6, triangle);
outputIndices.Set(triangleOffset + 6, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 7, triangle);
outputIndices.Set(triangleOffset + 7, triangle);
}
if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
{
@ -569,32 +537,32 @@ public:
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[1];
triangle[0] = cellId;
OutputIndices.Set(triangleOffset, triangle);
outputIndices.Set(triangleOffset, triangle);
triangle[1] = cellIndices[1];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 1, triangle);
outputIndices.Set(triangleOffset + 1, triangle);
triangle[1] = cellIndices[2];
triangle[2] = cellIndices[3];
triangle[3] = cellIndices[4];
OutputIndices.Set(triangleOffset + 2, triangle);
outputIndices.Set(triangleOffset + 2, triangle);
triangle[1] = cellIndices[0];
triangle[2] = cellIndices[4];
triangle[3] = cellIndices[3];
OutputIndices.Set(triangleOffset + 3, triangle);
outputIndices.Set(triangleOffset + 3, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[2];
triangle[3] = cellIndices[1];
OutputIndices.Set(triangleOffset + 4, triangle);
outputIndices.Set(triangleOffset + 4, triangle);
triangle[1] = cellIndices[3];
triangle[2] = cellIndices[1];
triangle[3] = cellIndices[0];
OutputIndices.Set(triangleOffset + 5, triangle);
outputIndices.Set(triangleOffset + 5, triangle);
}
}
}; //class Trianglulate
@ -608,16 +576,20 @@ public:
vtkm::Id& outputTriangles)
{
//Eliminate unseen triangles
vtkm::worklet::DispatcherMapField<IndicesSort>().Invoke(outputIndices);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Sort(outputIndices, IndicesLessThan());
vtkm::worklet::DispatcherMapField<IndicesSort> sortInvoker;
sortInvoker.Invoke(outputIndices);
vtkm::cont::Algorithm::Sort(outputIndices, IndicesLessThan());
vtkm::cont::ArrayHandle<vtkm::UInt8> flags;
flags.Allocate(outputTriangles);
vtkm::worklet::DispatcherMapField<MemSet<vtkm::UInt8>>(MemSet<vtkm::UInt8>(1)).Invoke(flags);
vtkm::cont::ArrayHandleConstant<vtkm::Id> one(1, outputTriangles);
vtkm::cont::Algorithm::Copy(one, flags);
//Unique triangles will have a flag = 1
vtkm::worklet::DispatcherMapField<UniqueTriangles>().Invoke(outputIndices, flags);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> subset;
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(outputIndices, flags, subset);
vtkm::cont::Algorithm::CopyIf(outputIndices, flags, subset);
outputIndices = subset;
outputTriangles = subset.GetNumberOfValues();
}
@ -630,13 +602,23 @@ public:
bool fastPath = false;
if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
//vtkm::cont::CellSetStructured<3> cellSetStructured3D =
// cellset.Cast<vtkm::cont::CellSetStructured<3>>();
//raytracing::MeshConnectivityBuilder<Device> builder;
//outputIndices = builder.ExternalTrianglesStructured(cellSetStructured3D);
//outputTriangles = outputIndices.GetNumberOfValues();
//fastPath = true;
vtkm::cont::CellSetStructured<3> cellSetStructured3D =
cellset.Cast<vtkm::cont::CellSetStructured<3>>();
const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells();
raytracing::MeshConnectivityBuilder<Device> builder;
outputIndices = builder.ExternalTrianglesStructured(cellSetStructured3D);
outputTriangles = outputIndices.GetNumberOfValues();
fastPath = true;
vtkm::cont::ArrayHandleCounting<vtkm::Id> cellIdxs(0, 1, numCells);
outputIndices.Allocate(numCells * 12);
vtkm::worklet::DispatcherMapTopology<TrianglulateStructured<3>>(TrianglulateStructured<3>())
.Invoke(cellSetStructured3D, cellIdxs, outputIndices);
outputTriangles = numCells * 12;
}
else if (cellset.IsSameType(vtkm::cont::CellSetStructured<2>()))
{
@ -646,11 +628,12 @@ public:
vtkm::cont::ArrayHandleCounting<vtkm::Id> cellIdxs(0, 1, numCells);
outputIndices.Allocate(numCells * 2);
vtkm::worklet::DispatcherMapTopology<TrianglulateStructured<2>>(
TrianglulateStructured<2>(outputIndices))
.Invoke(cellSetStructured2D, cellIdxs);
vtkm::worklet::DispatcherMapTopology<TrianglulateStructured<2>>(TrianglulateStructured<2>())
.Invoke(cellSetStructured2D, cellIdxs, outputIndices);
outputTriangles = numCells * 2;
// no need to do external faces on 2D cell set
fastPath = true;
}
else
{
@ -659,16 +642,14 @@ public:
.Invoke(cellset, trianglesPerCell);
vtkm::Id totalTriangles = 0;
totalTriangles =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(trianglesPerCell, vtkm::Id(0));
totalTriangles = vtkm::cont::Algorithm::Reduce(trianglesPerCell, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExclusive(trianglesPerCell, cellOffsets);
vtkm::cont::Algorithm::ScanExclusive(trianglesPerCell, cellOffsets);
outputIndices.Allocate(totalTriangles);
vtkm::worklet::DispatcherMapTopology<Trianglulate>(
Trianglulate(outputIndices, totalTriangles))
.Invoke(cellset, cellOffsets);
vtkm::worklet::DispatcherMapTopology<Trianglulate>(Trianglulate())
.Invoke(cellset, cellOffsets, outputIndices);
outputTriangles = totalTriangles;
}

@ -496,10 +496,8 @@ private:
if (ShowInternalZones && !IsOverlay)
{
using MemSet =
typename vtkm::rendering::Triangulator<DeviceTag>::template MemSet<vtkm::Int64>;
MemSet memSet(ClearValue);
vtkm::worklet::DispatcherMapField<MemSet>(memSet).Invoke(FrameBuffer);
vtkm::cont::ArrayHandleConstant<vtkm::Int64> clear(ClearValue, pixelCount);
vtkm::cont::Algorithm::Copy(clear, FrameBuffer);
}
else
{

@ -30,47 +30,12 @@ namespace rendering
namespace internal
{
namespace
{
struct TriangulatorFunctor
{
vtkm::cont::DynamicCellSet CellSet;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Indices;
vtkm::Id NumberOfTriangles;
VTKM_CONT
TriangulatorFunctor(vtkm::cont::DynamicCellSet cellSet)
: CellSet(cellSet)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
vtkm::rendering::Triangulator<Device> triangulator;
triangulator.Run(this->CellSet, this->Indices, this->NumberOfTriangles);
return true;
}
};
} // anonymous namespace
void RunTriangulator(const vtkm::cont::DynamicCellSet& cellSet,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::Id& numberOfTriangles,
vtkm::cont::RuntimeDeviceTracker tracker)
vtkm::Id& numberOfTriangles)
{
// TODO: Should the rendering library support policies or some other way to
// configure with custom devices?
TriangulatorFunctor triangulatorFunctor(cellSet);
if (!vtkm::cont::TryExecute(triangulatorFunctor, tracker))
{
throw vtkm::cont::ErrorExecution("Failed to execute triangulator.");
}
indices = triangulatorFunctor.Indices;
numberOfTriangles = triangulatorFunctor.NumberOfTriangles;
vtkm::rendering::Triangulator triangulator;
triangulator.Run(cellSet, indices, numberOfTriangles);
}
}
}

@ -39,11 +39,9 @@ namespace internal
/// filters, and filters should be compiled in a library (for the same reason).
///
VTKM_RENDERING_EXPORT
void RunTriangulator(
const vtkm::cont::DynamicCellSet& cellSet,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::Id& numberOfTriangles,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker());
void RunTriangulator(const vtkm::cont::DynamicCellSet& cellSet,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::Id& numberOfTriangles);
}
}
} // namespace vtkm::rendering::internal

@ -23,6 +23,7 @@
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
@ -49,11 +50,11 @@ namespace raytracing
{
namespace detail
{
class LinearBVHBuilder
{
public:
class CountingIterator;
class FindAABBs;
template <typename Device>
class GatherFloat32;
@ -61,6 +62,8 @@ public:
template <typename Device>
class GatherVecCast;
class CreateLeafs;
class BVHData;
template <typename Device>
@ -73,11 +76,10 @@ public:
LinearBVHBuilder() {}
template <typename Device>
VTKM_CONT void SortAABBS(
BVHData& bvh,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& triangleIndices,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>& outputTriangleIndices,
Device vtkmNotUsed(device));
VTKM_CONT void SortAABBS(BVHData& bvh, Device vtkmNotUsed(device));
template <typename Device>
VTKM_CONT void BuildHierarchy(BVHData& bvh);
template <typename Device>
VTKM_CONT void RunOnDevice(LinearBVH& linearBVH, Device device);
@ -94,70 +96,6 @@ public:
void operator()(const vtkm::Id& index, vtkm::Id& outId) const { outId = index; }
}; //class countingIterator
class LinearBVHBuilder::FindAABBs : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
FindAABBs() {}
using ControlSignature = void(FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7, _8);
template <typename PointPortalType>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Id, 4> indices,
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;
point = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(indices[1]));
xmin = point[0];
ymin = point[1];
zmin = point[2];
xmax = xmin;
ymax = ymin;
zmax = zmin;
point = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(indices[2]));
xmin = vtkm::Min(xmin, point[0]);
ymin = vtkm::Min(ymin, point[1]);
zmin = vtkm::Min(zmin, point[2]);
xmax = vtkm::Max(xmax, point[0]);
ymax = vtkm::Max(ymax, point[1]);
zmax = vtkm::Max(zmax, point[2]);
point = static_cast<vtkm::Vec<vtkm::Float32, 3>>(points.Get(indices[3]));
xmin = vtkm::Min(xmin, point[0]);
ymin = vtkm::Min(ymin, point[1]);
zmin = vtkm::Min(zmin, point[2]);
xmax = vtkm::Max(xmax, point[0]);
ymax = vtkm::Max(ymax, point[1]);
zmax = vtkm::Max(zmax, point[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
template <typename Device>
class LinearBVHBuilder::GatherFloat32 : public vtkm::worklet::WorkletMapField
{
@ -186,6 +124,27 @@ public:
}
}; //class GatherFloat
class LinearBVHBuilder::CreateLeafs : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CreateLeafs() {}
typedef void ControlSignature(FieldIn<>, WholeArrayOut<>);
typedef void ExecutionSignature(_1, _2, WorkIndex);
template <typename LeafPortalType>
VTKM_EXEC void operator()(const vtkm::Id& dataIndex,
LeafPortalType& leafs,
const vtkm::Id& index) const
{
const vtkm::Id offset = index * 2;
leafs.Set(offset, 1); // number of primitives
leafs.Set(offset + 1, dataIndex); // number of primitives
}
}; //class createLeafs
template <typename Device>
class LinearBVHBuilder::GatherVecCast : public vtkm::worklet::WorkletMapField
{
@ -221,48 +180,34 @@ class LinearBVHBuilder::BVHData
{
public:
//TODO: make private
vtkm::cont::ArrayHandle<vtkm::Float32>* xmins;
vtkm::cont::ArrayHandle<vtkm::Float32>* ymins;
vtkm::cont::ArrayHandle<vtkm::Float32>* zmins;
vtkm::cont::ArrayHandle<vtkm::Float32>* xmaxs;
vtkm::cont::ArrayHandle<vtkm::Float32>* ymaxs;
vtkm::cont::ArrayHandle<vtkm::Float32>* zmaxs;
vtkm::cont::ArrayHandle<vtkm::UInt32> mortonCodes;
vtkm::cont::ArrayHandle<vtkm::Id> parent;
vtkm::cont::ArrayHandle<vtkm::Id> leftChild;
vtkm::cont::ArrayHandle<vtkm::Id> rightChild;
vtkm::cont::ArrayHandle<vtkm::Id> leafs;
vtkm::cont::ArrayHandle<vtkm::Bounds> innerBounds;
vtkm::cont::ArrayHandleCounting<vtkm::Id> leafOffsets;
AABBs& AABB;
template <typename Device>
VTKM_CONT BVHData(vtkm::Id numPrimitives, Device vtkmNotUsed(device))
: NumPrimitives(numPrimitives)
VTKM_CONT BVHData(vtkm::Id numPrimitives, AABBs& aabbs, Device vtkmNotUsed(device))
: leafOffsets(0, 2, numPrimitives)
, AABB(aabbs)
, NumPrimitives(numPrimitives)
{
InnerNodeCount = NumPrimitives - 1;
vtkm::Id size = NumPrimitives + InnerNodeCount;
xmins = new vtkm::cont::ArrayHandle<vtkm::Float32>();
ymins = new vtkm::cont::ArrayHandle<vtkm::Float32>();
zmins = new vtkm::cont::ArrayHandle<vtkm::Float32>();
xmaxs = new vtkm::cont::ArrayHandle<vtkm::Float32>();
ymaxs = new vtkm::cont::ArrayHandle<vtkm::Float32>();
zmaxs = new vtkm::cont::ArrayHandle<vtkm::Float32>();
parent.PrepareForOutput(size, Device());
leftChild.PrepareForOutput(InnerNodeCount, Device());
rightChild.PrepareForOutput(InnerNodeCount, Device());
innerBounds.PrepareForOutput(InnerNodeCount, Device());
mortonCodes.PrepareForOutput(NumPrimitives, Device());
}
VTKM_CONT
~BVHData()
{
//
delete xmins;
delete ymins;
delete zmins;
delete xmaxs;
delete ymaxs;
delete zmaxs;
}
~BVHData() {}
VTKM_CONT
vtkm::Id GetNumberOfPrimitives() const { return NumPrimitives; }
VTKM_CONT
@ -295,8 +240,6 @@ private:
IdConstPortal LeftChildren;
IdConstPortal RightChildren;
vtkm::Int32 LeafCount;
//Int8Handle Counters;
//Int8ArrayPortal CountersPortal;
vtkm::exec::AtomicArrayExecutionObject<vtkm::Int32, Device> Counters;
public:
@ -321,17 +264,19 @@ public:
WholeArrayIn<Scalar>,
WholeArrayIn<Scalar>,
WholeArrayIn<Scalar>,
WholeArrayIn<Scalar>);
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4, _5, _6);
WholeArrayIn<Scalar>,
WholeArrayIn<>);
using ExecutionSignature = void(WorkIndex, _1, _2, _3, _4, _5, _6, _7);
template <typename InputPortalType>
template <typename InputPortalType, typename OffsetPortalType>
VTKM_EXEC_CONT void operator()(const vtkm::Id workIndex,
const InputPortalType& xmin,
const InputPortalType& ymin,
const InputPortalType& zmin,
const InputPortalType& xmax,
const InputPortalType& ymax,
const InputPortalType& zmax) const
const InputPortalType& zmax,
const OffsetPortalType& leafOffsets) const
{
//move up into the inner nodes
vtkm::Id currentNode = LeafCount - 1 + workIndex;
@ -348,6 +293,8 @@ public:
childVector[1] = RightChildren.Get(currentNode);
if (childVector[0] > (LeafCount - 2))
{
//our left child is a leaf, so just grab the AABB
//and set it in the current node
childVector[0] = childVector[0] - LeafCount + 1;
vtkm::Vec<vtkm::Float32, 4>
@ -363,11 +310,15 @@ public:
second4Vec[0] = ymax.Get(childVector[0]);
second4Vec[1] = zmax.Get(childVector[0]);
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
childVector[0] = -(childVector[0] + 1);
// set index to leaf
vtkm::Id leafIndex = leafOffsets.Get(childVector[0]);
childVector[0] = -(leafIndex + 1);
}
else
{
//our left child is an inner node, so gather
//both AABBs in the child and join them for
//the current node left AABB.
vtkm::Id child = childVector[0] * 4;
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
@ -389,6 +340,8 @@ public:
if (childVector[1] > (LeafCount - 2))
{
//our right child is a leaf, so just grab the AABB
//and set it in the current node
childVector[1] = childVector[1] - LeafCount + 1;
@ -404,11 +357,16 @@ public:
third4Vec[2] = ymax.Get(childVector[1]);
third4Vec[3] = zmax.Get(childVector[1]);
FlatBVH.Set(currentNodeOffset + 2, third4Vec);
childVector[1] = -(childVector[1] + 1);
// set index to leaf
vtkm::Id leafIndex = leafOffsets.Get(childVector[1]);
childVector[1] = -(leafIndex + 1);
}
else
{
//our left child is an inner node, so gather
//both AABBs in the child and join them for
//the current node left AABB.
vtkm::Id child = childVector[1] * 4;
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
@ -426,7 +384,7 @@ public:
cThird4Vec[3] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
FlatBVH.Set(currentNodeOffset + 2, cThird4Vec);
}
vtkm::Vec<vtkm::Float32, 4> fourth4Vec(0.f, 0.f, 0.f, 0.f);
vtkm::Vec<vtkm::Float32, 4> fourth4Vec;
vtkm::Int32 leftChild =
static_cast<vtkm::Int32>((childVector[0] >= 0) ? childVector[0] * 4 : childVector[0]);
memcpy(&fourth4Vec[0], &leftChild, 4);
@ -438,7 +396,6 @@ public:
}
}; //class PropagateAABBs
template <typename Device>
class LinearBVHBuilder::TreeBuilder : public vtkm::worklet::WorkletMapField
{
@ -453,7 +410,7 @@ private:
IdPortalType ParentPortal;
vtkm::Id LeafCount;
vtkm::Id InnerCount;
//TODO: get intrinsic support
//TODO: get instrinsic support
VTKM_EXEC
inline vtkm::Int32 CountLeadingZeros(vtkm::UInt32& x) const
{
@ -555,7 +512,7 @@ public:
vtkm::Int32 deltaNode = delta(idx, j);
vtkm::Int32 s = 0;
vtkm::Float32 divFactor = 2.f;
//find the split position using a binary search
//find the split postition using a binary search
for (vtkm::Int32 t = (vtkm::Int32)ceil(vtkm::Float32(l) / divFactor);;
divFactor *= 2, t = (vtkm::Int32)ceil(vtkm::Float32(l) / divFactor))
{
@ -599,11 +556,7 @@ public:
}; // class TreeBuilder
template <typename Device>
VTKM_CONT void LinearBVHBuilder::SortAABBS(
BVHData& bvh,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& triangleIndices,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>& outputTriangleIndices,
Device vtkmNotUsed(device))
VTKM_CONT void LinearBVHBuilder::SortAABBS(BVHData& bvh, Device vtkmNotUsed(device))
{
//create array of indexes to be sorted with morton codes
vtkm::cont::ArrayHandle<vtkm::Id> iterator;
@ -612,92 +565,91 @@ VTKM_CONT void LinearBVHBuilder::SortAABBS(
iteratorDispatcher.SetDevice(Device());
iteratorDispatcher.Invoke(iterator);
//std::cout<<"\n\n\n";
//sort the morton codes
vtkm::cont::DeviceAdapterAlgorithm<Device>::SortByKey(bvh.mortonCodes, iterator);
vtkm::Id arraySize = bvh.GetNumberOfPrimitives();
vtkm::cont::ArrayHandle<vtkm::Float32>* tempStorage;
vtkm::cont::ArrayHandle<vtkm::Float32>* tempPtr;
vtkm::cont::ArrayHandle<vtkm::Float32> temp1;
vtkm::cont::ArrayHandle<vtkm::Float32> temp2;
tempStorage = new vtkm::cont::ArrayHandle<vtkm::Float32>();
//tempStorage = new vtkm::cont::ArrayHandle<vtkm::Float32>();
//xmins
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.xmins, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.xmins, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.xmins;
bvh.xmins = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.xmins;
bvh.AABB.xmins = temp1;
temp1 = temp2;
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.ymins, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.ymins, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.ymins;
bvh.ymins = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.ymins;
bvh.AABB.ymins = temp1;
temp1 = temp2;
//zmins
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.zmins, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.zmins, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.zmins;
bvh.zmins = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.zmins;
bvh.AABB.zmins = temp1;
temp1 = temp2;
//xmaxs
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.xmaxs, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.xmaxs, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.xmaxs;
bvh.xmaxs = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.xmaxs;
bvh.AABB.xmaxs = temp1;
temp1 = temp2;
//ymaxs
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.ymaxs, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.ymaxs, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.ymaxs;
bvh.ymaxs = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.ymaxs;
bvh.AABB.ymaxs = temp1;
temp1 = temp2;
//zmaxs
{
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>> dispatcher(
GatherFloat32<Device>(*bvh.zmaxs, *tempStorage, arraySize));
GatherFloat32<Device>(bvh.AABB.zmaxs, temp1, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
tempPtr = bvh.zmaxs;
bvh.zmaxs = tempStorage;
tempStorage = tempPtr;
temp2 = bvh.AABB.zmaxs;
bvh.AABB.zmaxs = temp1;
temp1 = temp2;
{
vtkm::worklet::DispatcherMapField<GatherVecCast<Device>> dispatcher(
GatherVecCast<Device>(triangleIndices, outputTriangleIndices, arraySize));
dispatcher.SetDevice(Device());
dispatcher.Invoke(iterator);
}
delete tempStorage;
// Create the leaf references
vtkm::cont::ArrayHandleCounting<vtkm::Id> iter(0, 1, arraySize);
bvh.leafs.PrepareForOutput(arraySize * 2, Device());
} // method SortAABBs
vtkm::worklet::DispatcherMapField<CreateLeafs> createDis;
createDis.SetDevice(Device());
createDis.Invoke(iterator, bvh.leafs);
} // method SortAABB
// Adding this as a template parameter to allow restricted types and
// storage for dynamic coordinate system to limit crazy code bloat and
@ -708,52 +660,42 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("bvh_constuct");
logger->AddLogData("device", GetDeviceString(Device()));
vtkm::cont::Timer<Device> constructTimer;
auto coordsHandle = linearBVH.GetCoordsHandle();
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangleIndices = linearBVH.GetTriangles();
vtkm::Id numberOfTriangles = linearBVH.GetNumberOfTriangles();
vtkm::Id numberOfAABBs = linearBVH.GetNumberOfAABBs();
logger->AddLogData("bvh_num_triangles ", numberOfTriangles);
logger->AddLogData("bvh_num_aabbs", numberOfAABBs);
const vtkm::Id numBBoxes = numberOfTriangles;
BVHData bvh(numBBoxes, device);
const vtkm::Id numBBoxes = numberOfAABBs;
BVHData bvh(numBBoxes, linearBVH.GetAABBs(), device);
vtkm::cont::Timer<Device> timer;
vtkm::worklet::DispatcherMapField<FindAABBs> findAABBDispatcher{ (FindAABBs{}) };
findAABBDispatcher.SetDevice(Device());
findAABBDispatcher.Invoke(triangleIndices,
*bvh.xmins,
*bvh.ymins,
*bvh.zmins,
*bvh.xmaxs,
*bvh.ymaxs,
*bvh.zmaxs,
coordsHandle);
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("find_aabb", time);
timer.Reset();
// Find the extent of all bounding boxes to generate normalization for morton codes
vtkm::Vec<vtkm::Float32, 3> minExtent(vtkm::Infinity32(), vtkm::Infinity32(), vtkm::Infinity32());
vtkm::Vec<vtkm::Float32, 3> maxExtent(
vtkm::NegativeInfinity32(), vtkm::NegativeInfinity32(), vtkm::NegativeInfinity32());
maxExtent[0] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.xmaxs, maxExtent[0], MaxValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.xmaxs, maxExtent[0], MaxValue());
maxExtent[1] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.ymaxs, maxExtent[1], MaxValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.ymaxs, maxExtent[1], MaxValue());
maxExtent[2] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.zmaxs, maxExtent[2], MaxValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.zmaxs, maxExtent[2], MaxValue());
minExtent[0] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.xmins, minExtent[0], MinValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.xmins, minExtent[0], MinValue());
minExtent[1] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.ymins, minExtent[1], MinValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.ymins, minExtent[1], MinValue());
minExtent[2] =
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.zmins, minExtent[2], MinValue());
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(bvh.AABB.zmins, minExtent[2], MinValue());
time = timer.GetElapsedTime();
linearBVH.TotalBounds.X.Min = minExtent[0];
linearBVH.TotalBounds.X.Max = maxExtent[0];
linearBVH.TotalBounds.Y.Min = minExtent[1];
linearBVH.TotalBounds.Y.Max = maxExtent[1];
linearBVH.TotalBounds.Z.Min = minExtent[2];
linearBVH.TotalBounds.Z.Max = maxExtent[2];
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("calc_extents", time);
timer.Reset();
@ -765,11 +707,16 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
}
//Generate the morton codes
vtkm::worklet::DispatcherMapField<MortonCodeAABB> mortonCodeAABBDispatcher(
vtkm::worklet::DispatcherMapField<MortonCodeAABB> mortonDis(
MortonCodeAABB(inverseExtent, minExtent));
mortonCodeAABBDispatcher.SetDevice(Device());
mortonCodeAABBDispatcher.Invoke(
*bvh.xmins, *bvh.ymins, *bvh.zmins, *bvh.xmaxs, *bvh.ymaxs, *bvh.zmaxs, bvh.mortonCodes);
mortonDis.SetDevice(Device());
mortonDis.Invoke(bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.mortonCodes);
time = timer.GetElapsedTime();
logger->AddLogData("morton_codes", time);
@ -777,16 +724,16 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
linearBVH.Allocate(bvh.GetNumberOfPrimitives(), Device());
SortAABBS(bvh, triangleIndices, linearBVH.LeafNodes, Device());
SortAABBS(bvh, Device());
time = timer.GetElapsedTime();
logger->AddLogData("sort_aabbs", time);
timer.Reset();
vtkm::worklet::DispatcherMapField<TreeBuilder<Device>> treeBuilderDispatcher(
vtkm::worklet::DispatcherMapField<TreeBuilder<Device>> treeDis(
TreeBuilder<Device>(bvh.mortonCodes, bvh.parent, bvh.GetNumberOfPrimitives()));
treeBuilderDispatcher.SetDevice(Device());
treeBuilderDispatcher.Invoke(bvh.leftChild, bvh.rightChild);
treeDis.SetDevice(Device());
treeDis.Invoke(bvh.leftChild, bvh.rightChild);
time = timer.GetElapsedTime();
logger->AddLogData("build_tree", time);
@ -796,25 +743,25 @@ VTKM_CONT void LinearBVHBuilder::RunOnDevice(LinearBVH& linearBVH, Device device
vtkm::cont::ArrayHandle<vtkm::Int32> counters;
counters.PrepareForOutput(bvh.GetNumberOfPrimitives() - 1, Device());
vtkm::Int32 zero = 0;
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Int32>> resetCountersDispatcher(
(MemSet<vtkm::Int32>(zero)));
resetCountersDispatcher.SetDevice(Device());
resetCountersDispatcher.Invoke(counters);
vtkm::cont::ArrayHandleConstant<vtkm::Int32> zero(0, bvh.GetNumberOfPrimitives() - 1);
vtkm::cont::Algorithm::Copy(Device(), zero, counters);
vtkm::cont::AtomicArray<vtkm::Int32> atomicCounters(counters);
vtkm::worklet::DispatcherMapField<PropagateAABBs<Device>> propagateAABBDispatcher(
PropagateAABBs<Device>(bvh.parent,
bvh.leftChild,
bvh.rightChild,
primitiveCount,
linearBVH.FlatBVH,
atomicCounters));
propagateAABBDispatcher.SetDevice(Device());
propagateAABBDispatcher.Invoke(
*bvh.xmins, *bvh.ymins, *bvh.zmins, *bvh.xmaxs, *bvh.ymaxs, *bvh.zmaxs);
vtkm::worklet::DispatcherMapField<PropagateAABBs<Device>> propDis(PropagateAABBs<Device>(
bvh.parent, bvh.leftChild, bvh.rightChild, primitiveCount, linearBVH.FlatBVH, atomicCounters));
propDis.SetDevice(Device());
propDis.Invoke(bvh.AABB.xmins,
bvh.AABB.ymins,
bvh.AABB.zmins,
bvh.AABB.xmaxs,
bvh.AABB.ymaxs,
bvh.AABB.zmaxs,
bvh.leafOffsets);
linearBVH.Leafs = bvh.leafs;
time = timer.GetElapsedTime();
logger->AddLogData("propagate_aabbs", time);
@ -844,12 +791,8 @@ LinearBVH::LinearBVH()
, CanConstruct(false){};
VTKM_CONT
LinearBVH::LinearBVH(vtkm::cont::ArrayHandleVirtualCoordinates coordsHandle,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles,
vtkm::Bounds coordBounds)
: CoordBounds(coordBounds)
, CoordsHandle(coordsHandle)
, Triangles(triangles)
LinearBVH::LinearBVH(AABBs& aabbs)
: AABB(aabbs)
, IsConstructed(false)
, CanConstruct(true)
{
@ -857,12 +800,10 @@ LinearBVH::LinearBVH(vtkm::cont::ArrayHandleVirtualCoordinates coordsHandle,
VTKM_CONT
LinearBVH::LinearBVH(const LinearBVH& other)
: FlatBVH(other.FlatBVH)
, LeafNodes(other.LeafNodes)
: AABB(other.AABB)
, FlatBVH(other.FlatBVH)
, Leafs(other.Leafs)
, LeafCount(other.LeafCount)
, CoordBounds(other.CoordBounds)
, CoordsHandle(other.CoordsHandle)
, Triangles(other.Triangles)
, IsConstructed(other.IsConstructed)
, CanConstruct(other.CanConstruct)
{
@ -871,7 +812,6 @@ template <typename Device>
VTKM_CONT void LinearBVH::Allocate(const vtkm::Id& leafCount, Device deviceAdapter)
{
LeafCount = leafCount;
LeafNodes.PrepareForOutput(leafCount, deviceAdapter);
FlatBVH.PrepareForOutput((leafCount - 1) * 4, deviceAdapter);
}
@ -889,13 +829,9 @@ void LinearBVH::Construct()
}
VTKM_CONT
void LinearBVH::SetData(vtkm::cont::ArrayHandleVirtualCoordinates coordsHandle,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles,
vtkm::Bounds coordBounds)
void LinearBVH::SetData(AABBs& aabbs)
{
CoordBounds = coordBounds;
CoordsHandle = coordsHandle;
Triangles = triangles;
AABB = aabbs;
IsConstructed = false;
CanConstruct = true;
}
@ -912,15 +848,33 @@ void LinearBVH::ConstructOnDevice(Device device)
if (!IsConstructed)
{
//
// This algorithm needs at least 2 triangles
// This algorithm needs at least 2 AABBs
//
vtkm::Id numTriangles = this->GetNumberOfTriangles();
if (numTriangles == 1)
vtkm::Id numAABBs = this->GetNumberOfAABBs();
if (numAABBs == 1)
{
vtkm::Vec<vtkm::Id, 4> triangle = Triangles.GetPortalControl().Get(0);
Triangles.Allocate(2);
Triangles.GetPortalControl().Set(0, triangle);
Triangles.GetPortalControl().Set(1, triangle);
vtkm::Float32 xmin = AABB.xmins.GetPortalControl().Get(0);
vtkm::Float32 ymin = AABB.ymins.GetPortalControl().Get(0);
vtkm::Float32 zmin = AABB.zmins.GetPortalControl().Get(0);
vtkm::Float32 xmax = AABB.xmaxs.GetPortalControl().Get(0);
vtkm::Float32 ymax = AABB.ymaxs.GetPortalControl().Get(0);
vtkm::Float32 zmax = AABB.zmaxs.GetPortalControl().Get(0);
AABB.xmins.Allocate(2);
AABB.ymins.Allocate(2);
AABB.zmins.Allocate(2);
AABB.xmaxs.Allocate(2);
AABB.ymaxs.Allocate(2);
AABB.zmaxs.Allocate(2);
for (int i = 0; i < 2; ++i)
{
AABB.xmins.GetPortalControl().Set(i, xmin);
AABB.ymins.GetPortalControl().Set(i, ymin);
AABB.zmins.GetPortalControl().Set(i, zmin);
AABB.xmaxs.GetPortalControl().Set(i, xmax);
AABB.ymaxs.GetPortalControl().Set(i, ymax);
AABB.zmaxs.GetPortalControl().Set(i, zmax);
}
}
detail::LinearBVHBuilder builder;
builder.RunOnDevice(*this, device);
@ -952,21 +906,15 @@ bool LinearBVH::GetIsConstructed() const
{
return IsConstructed;
}
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates LinearBVH::GetCoordsHandle() const
vtkm::Id LinearBVH::GetNumberOfAABBs() const
{
return CoordsHandle;
return AABB.xmins.GetPortalConstControl().GetNumberOfValues();
}
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> LinearBVH::GetTriangles() const
AABBs& LinearBVH::GetAABBs()
{
return Triangles;
}
vtkm::Id LinearBVH::GetNumberOfTriangles() const
{
return Triangles.GetPortalConstControl().GetNumberOfValues();
return AABB;
}
}
}

@ -31,6 +31,16 @@ namespace rendering
namespace raytracing
{
struct AABBs
{
vtkm::cont::ArrayHandle<vtkm::Float32> xmins;
vtkm::cont::ArrayHandle<vtkm::Float32> ymins;
vtkm::cont::ArrayHandle<vtkm::Float32> zmins;
vtkm::cont::ArrayHandle<vtkm::Float32> xmaxs;
vtkm::cont::ArrayHandle<vtkm::Float32> ymaxs;
vtkm::cont::ArrayHandle<vtkm::Float32> zmaxs;
};
//
// This is the data structure that is passed to the ray tracer.
//
@ -38,16 +48,15 @@ class VTKM_RENDERING_EXPORT LinearBVH
{
public:
using InnerNodesHandle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>;
using LeafNodesHandle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>;
using LeafNodesHandle = vtkm::cont::ArrayHandle<Id>;
AABBs AABB;
InnerNodesHandle FlatBVH;
LeafNodesHandle LeafNodes;
LeafNodesHandle Leafs;
vtkm::Bounds TotalBounds;
struct ConstructFunctor;
vtkm::Id LeafCount;
vtkm::Bounds CoordBounds;
protected:
vtkm::cont::ArrayHandleVirtualCoordinates CoordsHandle;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Triangles;
bool IsConstructed;
bool CanConstruct;
@ -55,9 +64,7 @@ public:
LinearBVH();
VTKM_CONT
LinearBVH(vtkm::cont::ArrayHandleVirtualCoordinates coordsHandle,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles,
vtkm::Bounds coordBounds);
LinearBVH(AABBs& aabbs);
VTKM_CONT
LinearBVH(const LinearBVH& other);
@ -69,9 +76,10 @@ public:
void Construct();
VTKM_CONT
void SetData(vtkm::cont::ArrayHandleVirtualCoordinates coordsHandle,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles,
vtkm::Bounds coordBounds);
void SetData(AABBs& aabbs);
VTKM_CONT
AABBs& GetAABBs();
template <typename Device>
VTKM_CONT void ConstructOnDevice(Device device);
@ -79,13 +87,7 @@ public:
VTKM_CONT
bool GetIsConstructed() const;
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates GetCoordsHandle() const;
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> GetTriangles() const;
vtkm::Id GetNumberOfTriangles() const;
vtkm::Id GetNumberOfAABBs() const;
}; // class LinearBVH
}
}

@ -20,24 +20,32 @@
set(headers
BoundingVolumeHierarchy.h
BVHTraverser.h
Camera.h
CellIntersector.h
CellSampler.h
CellTables.h
ChannelBuffer.h
ChannelBufferOperations.h
ConnectivityBase.h
ConnectivityTracer.h
ConnectivityTracerBase.h
ConnectivityTracerFactory.h
CylinderExtractor.h
CylinderIntersector.h
Logger.h
MeshConnectivityBuilder.h
MeshConnectivityStructures.h
MeshConnectivityContainers.h
MeshConnectivityBase.h
MortonCodes.h
QuadExtractor.h
QuadIntersector.h
Ray.h
RayOperations.h
RayTracer.h
RayTracingTypeDefs.h
Sampler.h
ShapeIntersector.h
SphereExtractor.h
SphereIntersector.h
TriangleExtractor.h
TriangleIntersector.h
VolumeRendererStructured.h
Worklets.h

@ -29,6 +29,7 @@
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/rendering/raytracing/Sampler.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/worklet/DispatcherMapField.h>
@ -162,6 +163,82 @@ public:
}; // class pixelData
class PerspectiveRayGenJitter : public vtkm::worklet::WorkletMapField
{
public:
vtkm::Int32 w;
vtkm::Int32 h;
vtkm::Vec<vtkm::Float32, 3> nlook; // normalized look
vtkm::Vec<vtkm::Float32, 3> delta_x;
vtkm::Vec<vtkm::Float32, 3> delta_y;
vtkm::Int32 CurrentSample;
VTKM_CONT_EXPORT
PerspectiveRayGenJitter(vtkm::Int32 width,
vtkm::Int32 height,
vtkm::Float32 fovX,
vtkm::Float32 fovY,
vtkm::Vec<vtkm::Float32, 3> look,
vtkm::Vec<vtkm::Float32, 3> up,
vtkm::Float32 _zoom,
vtkm::Int32 currentSample)
: w(width)
, h(height)
{
vtkm::Float32 thx = tanf((fovX * 3.1415926f / 180.f) * .5f);
vtkm::Float32 thy = tanf((fovY * 3.1415926f / 180.f) * .5f);
vtkm::Vec<vtkm::Float32, 3> ru = vtkm::Cross(up, look);
vtkm::Normalize(ru);
vtkm::Vec<vtkm::Float32, 3> rv = vtkm::Cross(ru, look);
vtkm::Normalize(rv);
delta_x = ru * (2 * thx / (float)w);
delta_y = rv * (2 * thy / (float)h);
if (_zoom > 0)
{
delta_x[0] = delta_x[0] / _zoom;
delta_x[1] = delta_x[1] / _zoom;
delta_x[2] = delta_x[2] / _zoom;
delta_y[0] = delta_y[0] / _zoom;
delta_y[1] = delta_y[1] / _zoom;
delta_y[2] = delta_y[2] / _zoom;
}
nlook = look;
vtkm::Normalize(nlook);
CurrentSample = currentSample;
}
typedef void ControlSignature(FieldOut<>, FieldOut<>, FieldOut<>, FieldIn<>);
typedef void ExecutionSignature(WorkIndex, _1, _2, _3, _4);
VTKM_EXEC
void operator()(vtkm::Id idx,
vtkm::Float32& rayDirX,
vtkm::Float32& rayDirY,
vtkm::Float32& rayDirZ,
const vtkm::Int32& seed) const
{
vtkm::Vec<vtkm::Float32, 2> xy;
Halton2D<3>(CurrentSample + seed, xy);
xy[0] -= .5f;
xy[1] -= .5f;
vtkm::Vec<vtkm::Float32, 3> ray_dir(rayDirX, rayDirY, rayDirZ);
vtkm::Float32 i = static_cast<vtkm::Float32>(vtkm::Int32(idx) % w);
vtkm::Float32 j = static_cast<vtkm::Float32>(vtkm::Int32(idx) / w);
i += xy[0];
j += xy[1];
ray_dir = nlook + delta_x * ((2.f * i - vtkm::Float32(w)) / 2.0f) +
delta_y * ((2.f * j - vtkm::Float32(h)) / 2.0f);
vtkm::Normalize(ray_dir);
rayDirX = ray_dir[0];
rayDirY = ray_dir[1];
rayDirZ = ray_dir[2];
}
}; // class perspective ray gen jitter
class Camera::Ortho2DRayGen : public vtkm::worklet::WorkletMapField
{
public:
@ -631,35 +708,6 @@ bool Camera::GetIsViewDirty() const
return this->IsViewDirty;
}
template <typename Precision>
struct Camera::CreateRaysFunctor
{
vtkm::rendering::raytracing::Camera* Self;
const vtkm::cont::CoordinateSystem& Coords;
vtkm::rendering::raytracing::Ray<Precision>& Rays;
VTKM_CONT
CreateRaysFunctor(vtkm::rendering::raytracing::Camera* self,
const vtkm::cont::CoordinateSystem& coords,
vtkm::rendering::raytracing::Ray<Precision>& rays)
: Self(self)
, Coords(coords)
, Rays(rays)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
vtkm::Bounds boundingBox = Coords.GetBounds();
Self->CreateRaysOnDevice(this->Rays, Device(), boundingBox);
return true;
}
};
void Camera::GetPixelData(const vtkm::cont::CoordinateSystem& coords,
vtkm::Int32& activePixels,
vtkm::Float32& aveRayDistance)
@ -695,53 +743,42 @@ void Camera::GetPixelData(const vtkm::cont::CoordinateSystem& coords,
}
VTKM_CONT
void Camera::CreateRays(Ray<vtkm::Float32>& rays, const vtkm::cont::CoordinateSystem& coords)
void Camera::CreateRays(Ray<vtkm::Float32>& rays, vtkm::Bounds bounds)
{
CreateRaysFunctor<Float32> functor(this, coords, rays);
vtkm::cont::TryExecute(functor);
CreateRaysImpl(rays, bounds);
}
VTKM_CONT
void Camera::CreateRays(Ray<vtkm::Float64>& rays, const vtkm::cont::CoordinateSystem& coords)
void Camera::CreateRays(Ray<vtkm::Float64>& rays, vtkm::Bounds bounds)
{
CreateRaysFunctor<Float64> functor(this, coords, rays);
vtkm::cont::TryExecute(functor);
CreateRaysImpl(rays, bounds);
}
template <typename Precision, typename Device>
VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
Device,
const vtkm::Bounds boundingBox)
template <typename Precision>
VTKM_CONT void Camera::CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds boundingBox)
{
Logger* logger = Logger::GetInstance();
vtkm::cont::Timer<Device> createTimer;
vtkm::cont::Timer<vtkm::cont::DeviceAdapterTagSerial> createTimer;
logger->OpenLogEntry("ray_camera");
logger->AddLogData("device", GetDeviceString(Device()));
bool ortho = this->CameraView.GetMode() == vtkm::rendering::Camera::MODE_2D;
this->UpdateDimensions(rays, Device(), boundingBox, ortho);
this->UpdateDimensions(rays, boundingBox, ortho);
this->WriteSettingsToLog();
vtkm::cont::Timer<Device> timer;
vtkm::cont::Timer<vtkm::cont::DeviceAdapterTagSerial> timer;
//Set the origin of the ray back to the camera position
Precision infinity;
GetInfinity(infinity);
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSetInfDispatcher(
(MemSet<Precision>(infinity)));
memSetInfDispatcher.SetDevice(Device());
memSetInfDispatcher.Invoke(rays.MaxDistance);
vtkm::cont::ArrayHandleConstant<Precision> inf(infinity, rays.NumRays);
vtkm::cont::Algorithm::Copy(inf, rays.MaxDistance);
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSet0Dispatcher((MemSet<Precision>(0.f)));
memSet0Dispatcher.SetDevice(Device());
memSet0Dispatcher.Invoke(rays.MinDistance);
memSet0Dispatcher.Invoke(rays.Distance);
vtkm::cont::ArrayHandleConstant<Precision> zero(0, rays.NumRays);
vtkm::cont::Algorithm::Copy(zero, rays.MinDistance);
vtkm::cont::Algorithm::Copy(zero, rays.Distance);
//Reset the Rays Hit Index to -2
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Id>> memSetM2Dispatcher((MemSet<vtkm::Id>(-2)));
memSetM2Dispatcher.SetDevice(Device());
memSetM2Dispatcher.Invoke(rays.HitIdx);
vtkm::cont::ArrayHandleConstant<vtkm::Id> initHit(-2, rays.NumRays);
vtkm::cont::Algorithm::Copy(initHit, rays.HitIdx);
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("camera_memset", time);
@ -760,7 +797,6 @@ VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
this->SubsetMinX,
this->SubsetMinY,
this->CameraView));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.DirX,
rays.DirY,
rays.DirZ,
@ -783,23 +819,19 @@ VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.DirX, rays.DirY, rays.DirZ, rays.PixelIdx); //X Y Z
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSetPos0Dispatcher(
MemSet<Precision>(this->Position[0]));
memSetPos0Dispatcher.SetDevice(Device());
memSetPos0Dispatcher.Invoke(rays.OriginX);
std::cout << "c7\n";
vtkm::cont::ArrayHandleConstant<Precision> posX(this->Position[0], rays.NumRays);
vtkm::cont::Algorithm::Copy(posX, rays.OriginX);
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSetPos1Dispatcher(
MemSet<Precision>(this->Position[1]));
memSetPos1Dispatcher.SetDevice(Device());
memSetPos1Dispatcher.Invoke(rays.OriginY);
vtkm::cont::ArrayHandleConstant<Precision> posY(this->Position[1], rays.NumRays);
vtkm::cont::Algorithm::Copy(posY, rays.OriginY);
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSetPos2Dispatcher(
MemSet<Precision>(this->Position[2]));
memSetPos2Dispatcher.SetDevice(Device());
memSetPos2Dispatcher.Invoke(rays.OriginZ);
vtkm::cont::ArrayHandleConstant<Precision> posZ(this->Position[2], rays.NumRays);
vtkm::cont::Algorithm::Copy(posZ, rays.OriginZ);
std::cout << "c10\n";
}
time = timer.GetElapsedTime();
@ -909,9 +941,8 @@ void Camera::FindSubset(const vtkm::Bounds& bounds)
logger->AddLogData("subset_height", dy);
}
template <typename Device, typename Precision>
template <typename Precision>
VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
Device,
const vtkm::Bounds& boundingBox,
bool ortho2D)
{
@ -971,7 +1002,8 @@ VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
// resize rays and buffers
if (rays.NumRays != SubsetWidth * SubsetHeight)
{
RayOperations::Resize(rays, this->SubsetHeight * this->SubsetWidth, Device());
RayOperations::Resize(
rays, this->SubsetHeight * this->SubsetWidth, VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
}
}

@ -37,8 +37,6 @@ class VTKM_RENDERING_EXPORT Camera
private:
struct PixelDataFunctor;
template <typename Precision>
struct CreateRaysFunctor;
vtkm::rendering::CanvasRayTracer Canvas;
vtkm::Int32 Height;
vtkm::Int32 Width;
@ -134,19 +132,18 @@ public:
bool GetIsViewDirty() const;
VTKM_CONT
void CreateRays(Ray<vtkm::Float32>& rays, const vtkm::cont::CoordinateSystem& coords);
void CreateRays(Ray<vtkm::Float32>& rays, vtkm::Bounds bounds);
VTKM_CONT
void CreateRays(Ray<vtkm::Float64>& rays, const vtkm::cont::CoordinateSystem& coords);
void CreateRays(Ray<vtkm::Float64>& rays, vtkm::Bounds bounds);
VTKM_CONT
void GetPixelData(const vtkm::cont::CoordinateSystem& coords,
vtkm::Int32& activePixels,
vtkm::Float32& aveRayDistance);
template <typename Precision, typename DeviceAdapter>
VTKM_CONT void CreateRaysOnDevice(Ray<Precision>& rays,
DeviceAdapter,
const vtkm::Bounds boundingBox);
template <typename Precision>
VTKM_CONT void CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds boundingBox);
void CreateDebugRay(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<vtkm::Float32>& rays);
@ -160,9 +157,8 @@ private:
VTKM_CONT
void FindSubset(const vtkm::Bounds& bounds);
template <typename DeviceAdapter, typename Precision>
template <typename Precision>
VTKM_CONT void UpdateDimensions(Ray<Precision>& rays,
DeviceAdapter,
const vtkm::Bounds& boundingBox,
bool ortho2D);

@ -43,11 +43,10 @@ VTKM_EXEC_CONT inline void IntersectZoo(T xpoints[8],
const vtkm::Int32& shapeType)
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
vtkm::Vec<T, 3> s;
vtkm::Vec<vtkm::Int32, 3> k;
WaterTight intersector;
intersector.FindDir(dir, s, k);
CellTables tables;
const vtkm::Int32 tableOffset = tables.ZooLookUp(tables.CellTypeLookUp(shapeType), 0);
const vtkm::Int32 numTriangles = tables.ZooLookUp(tables.CellTypeLookUp(shapeType), 1);
@ -71,21 +70,7 @@ VTKM_EXEC_CONT inline void IntersectZoo(T xpoints[8],
T distance = -1.f;
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, b, c, s, k, distance, uNotUsed, vNotUsed, origin);
if (distance != -1.f)
{
@ -105,10 +90,10 @@ VTKM_EXEC_CONT inline void IntersectHex(T xpoints[8],
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
vtkm::Vec<T, 3> s;
vtkm::Vec<vtkm::Int32, 3> k;
WaterTight intersector;
intersector.FindDir(dir, s, k);
CellTables tables;
// Decompose each face into two triangles
@ -131,42 +116,14 @@ VTKM_EXEC_CONT inline void IntersectHex(T xpoints[8],
distances[i] = distance; //init to -1
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, b, c, s, k, distance, uNotUsed, vNotUsed, origin);
if (distance != -1.f)
distances[i] = distance;
distance = -1.f;
intersector.IntersectTriSn(a,
c,
d,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, c, d, s, k, distance, uNotUsed, vNotUsed, origin);
@ -188,10 +145,10 @@ VTKM_EXEC_CONT inline void IntersectTet(T xpoints[8],
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
vtkm::Vec<T, 3> s;
vtkm::Vec<vtkm::Int32, 3> k;
WaterTight intersector;
intersector.FindDir(dir, s, k);
CellTables tables;
const vtkm::Int32 tableOffset = tables.FaceLookUp(tables.CellTypeLookUp(CELL_SHAPE_TETRA), 0);
@ -212,21 +169,7 @@ VTKM_EXEC_CONT inline void IntersectTet(T xpoints[8],
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, b, c, s, k, distance, uNotUsed, vNotUsed, origin);
if (distance != -1.f)
distances[i] = distance;
@ -245,10 +188,10 @@ VTKM_EXEC_CONT inline void IntersectWedge(T xpoints[8],
T distances[6])
{
// Some precalc for water tight intersections
T sx, sy, sz;
vtkm::Int32 kx, ky, kz;
WaterTight<T> intersector;
intersector.FindDir(dir, sx, sy, sz, kx, ky, kz);
vtkm::Vec<T, 3> s;
vtkm::Vec<vtkm::Int32, 3> k;
WaterTight intersector;
intersector.FindDir(dir, s, k);
// TODO: try two sepate loops to see performance impact
CellTables tables;
const vtkm::Int32 tableOffset = tables.FaceLookUp(tables.CellTypeLookUp(CELL_SHAPE_WEDGE), 0);
@ -273,21 +216,7 @@ VTKM_EXEC_CONT inline void IntersectWedge(T xpoints[8],
T uNotUsed, vNotUsed;
intersector.IntersectTriSn(a,
b,
c,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, b, c, s, k, distance, uNotUsed, vNotUsed, origin);
if (distance != -1.f)
distances[i] = distance;
@ -298,21 +227,7 @@ VTKM_EXEC_CONT inline void IntersectWedge(T xpoints[8],
continue;
distance = -1.f;
intersector.IntersectTriSn(a,
c,
d,
sx,
sy,
sz,
kx,
ky,
kz,
distance,
uNotUsed,
vNotUsed,
origin[0],
origin[1],
origin[2]);
intersector.IntersectTriSn(a, c, d, s, k, distance, uNotUsed, vNotUsed, origin);
if (distance != -1.f)
{

@ -440,9 +440,15 @@ template <typename Precision>
void ChannelBuffer<Precision>::Normalize(bool invert)
{
NormalizeFunctor<Precision> functor(this->Buffer, invert);
vtkm::cont::TryExecute(functor);
vtkm::cont::Field asField(
"name meaningless", vtkm::cont::Field::Association::POINTS, this->Buffer);
vtkm::Range range;
asField.GetRange(&range);
Precision minScalar = static_cast<Precision>(range.Min);
Precision maxScalar = static_cast<Precision>(range.Max);
vtkm::worklet::DispatcherMapField<NormalizeBuffer<Precision>> dispatcher(
NormalizeBuffer<Precision>(minScalar, maxScalar, invert));
dispatcher.Invoke(this->Buffer);
}
template <typename Precision>
@ -465,30 +471,11 @@ struct ResizeChannelFunctor
}
};
template <typename Precision>
struct InitConstFunctor
{
ChannelBuffer<Precision>* Self;
Precision Value;
InitConstFunctor(ChannelBuffer<Precision>* self, Precision value)
: Self(self)
, Value(value)
{
}
template <typename Device>
bool operator()(Device device)
{
ChannelBufferOperations::InitConst(*Self, Value, device);
return true;
}
};
template <typename Precision>
void ChannelBuffer<Precision>::InitConst(const Precision value)
{
InitConstFunctor<Precision> functor(this, value);
vtkm::cont::TryExecute(functor);
vtkm::cont::ArrayHandleConstant<Precision> valueHandle(value, this->GetBufferLength());
vtkm::cont::Algorithm::Copy(valueHandle, this->Buffer);
}
template <typename Precision>

@ -22,6 +22,7 @@
#include <vtkm/Types.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/rendering/raytracing/ChannelBuffer.h>
@ -143,10 +144,8 @@ public:
template <typename Device, typename Precision>
static void InitConst(ChannelBuffer<Precision>& buffer, const Precision value, Device)
{
vtkm::worklet::DispatcherMapField<MemSet<Precision>> memSetDispatcher(
(MemSet<Precision>(value)));
memSetDispatcher.SetDevice(Device());
memSetDispatcher.Invoke(buffer.Buffer);
vtkm::cont::ArrayHandleConstant<Precision> valueHandle(value, buffer.GetBufferLength());
vtkm::cont::Algorithm::Copy(Device(), valueHandle, buffer.Buffer);
}
};
}

@ -1,38 +0,0 @@
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 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/ConnectivityBase.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
ConnectivityBase::ConnectivityBase()
{
}
ConnectivityBase::~ConnectivityBase()
{
}
}
}
}

@ -1,69 +0,0 @@
//============================================================================
// 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_Connectivity_Base_h
#define vtk_m_rendering_raytracing_Connectivity_Base_h
#include <vtkm/rendering/vtkm_rendering_export.h>
#include <vtkm/rendering/raytracing/Ray.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT ConnectivityBase
{
public:
enum IntegrationMode
{
Volume,
Energy
};
ConnectivityBase();
virtual ~ConnectivityBase();
virtual void Trace(Ray<vtkm::Float64>& rays) = 0;
virtual void Trace(Ray<vtkm::Float32>& rays) = 0;
virtual void SetVolumeData(const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarBounds) = 0;
virtual void SetEnergyData(const vtkm::cont::Field& absorption,
const vtkm::Int32 numBins,
const vtkm::cont::Field& emission = vtkm::cont::Field()) = 0;
virtual void SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor) = 0;
virtual void SetSampleDistance(const vtkm::Float32& distance) = 0;
virtual void SetColorMap(
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap) = 0;
virtual void SetDebugOn(bool on) = 0;
}; // class ConnectivityBase
}
}
} // namespace vtkm::rendering::raytracing
#endif

@ -21,6 +21,7 @@
#include <vtkm/rendering/raytracing/ConnectivityTracer.h>
#include <vtkm/rendering/raytracing/ConnectivityTracer.hxx>
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
namespace vtkm
{
@ -43,34 +44,185 @@ struct RenderFunctor
} //namespace detail
template <vtkm::Int32 CellType, typename ConnectivityType>
void ConnectivityTracer<CellType, ConnectivityType>::Trace(Ray<vtkm::Float32>& rays)
void ConnectivityTracer::Trace(Ray<vtkm::Float32>& rays)
{
detail::RenderFunctor functor;
vtkm::cont::TryExecute(functor, *this, rays);
}
template <vtkm::Int32 CellType, typename ConnectivityType>
void ConnectivityTracer<CellType, ConnectivityType>::Trace(Ray<vtkm::Float64>& rays)
void ConnectivityTracer::Trace(Ray<vtkm::Float64>& rays)
{
detail::RenderFunctor functor;
vtkm::cont::TryExecute(functor, *this, rays);
}
//explicit construct all valid forms ofConnectivityTracer
void ConnectivityTracer::Init()
{
//
// Check to see if a sample distance was set
//
if (SampleDistance <= 0)
{
vtkm::Bounds coordsBounds = Coords.GetBounds();
BoundingBox[0] = vtkm::Float32(coordsBounds.X.Min);
BoundingBox[1] = vtkm::Float32(coordsBounds.X.Max);
BoundingBox[2] = vtkm::Float32(coordsBounds.Y.Min);
BoundingBox[3] = vtkm::Float32(coordsBounds.Y.Max);
BoundingBox[4] = vtkm::Float32(coordsBounds.Z.Min);
BoundingBox[5] = vtkm::Float32(coordsBounds.Z.Max);
BackgroundColor[0] = 1.f;
BackgroundColor[1] = 1.f;
BackgroundColor[2] = 1.f;
BackgroundColor[3] = 1.f;
const vtkm::Float32 defaultSampleRate = 200.f;
// We need to set some default sample distance
vtkm::Vec<vtkm::Float32, 3> extent;
extent[0] = BoundingBox[1] - BoundingBox[0];
extent[1] = BoundingBox[3] - BoundingBox[2];
extent[2] = BoundingBox[5] - BoundingBox[4];
SampleDistance = vtkm::Magnitude(extent) / defaultSampleRate;
}
}
vtkm::Id ConnectivityTracer::GetNumberOfMeshCells() const
{
return CellSet.GetNumberOfCells();
}
void ConnectivityTracer::SetColorMap(
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap)
{
ColorMap = colorMap;
}
void ConnectivityTracer::SetVolumeData(const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarBounds,
const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords)
{
//TODO: Need a way to tell if we have been updated
ScalarField = scalarField;
ScalarBounds = scalarBounds;
CellSet = cellSet;
Coords = coords;
MeshConnIsConstructed = false;
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 cell set or points");
FieldAssocPoints = ScalarField.GetAssociation() == vtkm::cont::Field::Association::POINTS;
this->Integrator = Volume;
if (MeshContainer == nullptr)
{
delete MeshContainer;
}
MeshConnectivityBuilder builder;
MeshContainer = builder.BuildConnectivity(cellSet, coords);
}
void ConnectivityTracer::SetEnergyData(const vtkm::cont::Field& absorption,
const vtkm::Int32 numBins,
const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& emission)
{
bool isSupportedField = absorption.GetAssociation() == vtkm::cont::Field::Association::CELL_SET;
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue("Absorption Field '" + absorption.GetName() +
"' not accociated with cells");
ScalarField = absorption;
CellSet = cellSet;
Coords = coords;
MeshConnIsConstructed = false;
// Check for emission
HasEmission = false;
if (emission.GetAssociation() != vtkm::cont::Field::Association::ANY)
{
if (emission.GetAssociation() != vtkm::cont::Field::Association::CELL_SET)
throw vtkm::cont::ErrorBadValue("Emission Field '" + emission.GetName() +
"' not accociated with cells");
HasEmission = true;
EmissionField = emission;
}
// Do some basic range checking
if (numBins < 1)
throw vtkm::cont::ErrorBadValue("Number of energy bins is less than 1");
vtkm::Id binCount = ScalarField.GetData().GetNumberOfValues();
vtkm::Id cellCount = this->GetNumberOfMeshCells();
if (cellCount != (binCount / vtkm::Id(numBins)))
{
std::stringstream message;
message << "Invalid number of absorption bins\n";
message << "Number of cells: " << cellCount << "\n";
message << "Number of field values: " << binCount << "\n";
message << "Number of bins: " << numBins << "\n";
throw vtkm::cont::ErrorBadValue(message.str());
}
if (HasEmission)
{
binCount = EmissionField.GetData().GetNumberOfValues();
if (cellCount != (binCount / vtkm::Id(numBins)))
{
std::stringstream message;
message << "Invalid number of emission bins\n";
message << "Number of cells: " << cellCount << "\n";
message << "Number of field values: " << binCount << "\n";
message << "Number of bins: " << numBins << "\n";
throw vtkm::cont::ErrorBadValue(message.str());
}
}
//TODO: Need a way to tell if we have been updated
this->Integrator = Energy;
if (MeshContainer == nullptr)
{
delete MeshContainer;
}
MeshConnectivityBuilder builder;
MeshContainer = builder.BuildConnectivity(cellSet, coords);
}
void ConnectivityTracer::SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
{
BackgroundColor = backgroundColor;
}
void ConnectivityTracer::SetSampleDistance(const vtkm::Float32& distance)
{
if (distance <= 0.f)
throw vtkm::cont::ErrorBadValue("Sample distance must be positive.");
SampleDistance = distance;
}
void ConnectivityTracer::ResetTimers()
{
IntersectTime = 0.;
IntegrateTime = 0.;
SampleTime = 0.;
LostRayTime = 0.;
MeshEntryTime = 0.;
}
void ConnectivityTracer::LogTimers()
{
Logger* logger = Logger::GetInstance();
logger->AddLogData("intersect ", IntersectTime);
logger->AddLogData("integrate ", IntegrateTime);
logger->AddLogData("sample_cells ", SampleTime);
logger->AddLogData("lost_rays ", LostRayTime);
logger->AddLogData("mesh_entry", LostRayTime);
}
template class detail::RayTracking<float>;
template class detail::RayTracking<double>;
template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_ZOO, UnstructuredMeshConn>;
template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_HEXAHEDRON, UnstructuredMeshConnSingleType>;
template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_WEDGE, UnstructuredMeshConnSingleType>;
template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_TETRA, UnstructuredMeshConnSingleType>;
template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_STRUCTURED, StructuredMeshConn>;
}
}
} // namespace vtkm::rendering::raytracing

@ -22,9 +22,10 @@
#include <vtkm/rendering/vtkm_rendering_export.h>
#include <iomanip>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/rendering/raytracing/ConnectivityTracerBase.h>
#include <vtkm/rendering/raytracing/MeshConnectivityStructures.h>
#include <vtkm/rendering/raytracing/MeshConnectivityContainers.h>
#ifndef CELL_SHAPE_ZOO
#define CELL_SHAPE_ZOO 255
@ -81,53 +82,94 @@ public:
} //namespace detail
template <vtkm::Int32 CellType, typename ConnectivityType>
class ConnectivityTracer : public ConnectivityTracerBase
class ConnectivityTracer
{
public:
ConnectivityTracer(ConnectivityType& meshConn)
: ConnectivityTracerBase()
, MeshConn(meshConn)
ConnectivityTracer()
: MeshContainer(nullptr)
{
}
template <typename Device>
VTKM_CONT void SetBoundingBox(Device)
~ConnectivityTracer()
{
vtkm::Bounds coordsBounds = MeshConn.GetCoordinateBounds(Device());
BoundingBox[0] = vtkm::Float32(coordsBounds.X.Min);
BoundingBox[1] = vtkm::Float32(coordsBounds.X.Max);
BoundingBox[2] = vtkm::Float32(coordsBounds.Y.Min);
BoundingBox[3] = vtkm::Float32(coordsBounds.Y.Max);
BoundingBox[4] = vtkm::Float32(coordsBounds.Z.Min);
BoundingBox[5] = vtkm::Float32(coordsBounds.Z.Max);
BackgroundColor[0] = 1.f;
BackgroundColor[1] = 1.f;
BackgroundColor[2] = 1.f;
BackgroundColor[3] = 1.f;
if (MeshContainer != nullptr)
{
delete MeshContainer;
}
}
void Trace(Ray<vtkm::Float32>& rays) override;
enum IntegrationMode
{
Volume,
Energy
};
void Trace(Ray<vtkm::Float64>& rays) override;
void SetVolumeData(const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarBounds,
const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords);
ConnectivityType GetMeshConn() { return MeshConn; }
void SetEnergyData(const vtkm::cont::Field& absorption,
const vtkm::Int32 numBins,
const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& emission);
vtkm::Id GetNumberOfMeshCells() override { return MeshConn.GetNumberOfCells(); }
void SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor);
void SetSampleDistance(const vtkm::Float32& distance);
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap);
// template <typename Device>
// VTKM_CONT void SetBoundingBox(Device)
// {
// vtkm::Bounds coordsBounds = MeshConn->GetCoordinateBounds(Device());
// BoundingBox[0] = vtkm::Float32(coordsBounds.X.Min);
// BoundingBox[1] = vtkm::Float32(coordsBounds.X.Max);
// BoundingBox[2] = vtkm::Float32(coordsBounds.Y.Min);
// BoundingBox[3] = vtkm::Float32(coordsBounds.Y.Max);
// BoundingBox[4] = vtkm::Float32(coordsBounds.Z.Min);
// BoundingBox[5] = vtkm::Float32(coordsBounds.Z.Max);
// BackgroundColor[0] = 1.f;
// BackgroundColor[1] = 1.f;
// BackgroundColor[2] = 1.f;
// BackgroundColor[3] = 1.f;
// }
void Trace(Ray<vtkm::Float32>& rays);
void Trace(Ray<vtkm::Float64>& rays);
MeshConnContainer* GetMeshContainer() { return MeshContainer; }
void Init();
vtkm::Id GetNumberOfMeshCells() const;
void ResetTimers();
void LogTimers();
//vtkm::Id GetNumberOfMeshCells() override { return MeshConn.GetNumberOfCells(); }
private:
friend struct detail::RenderFunctor;
template <typename FloatType, typename Device>
void IntersectCell(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device);
void IntersectCell(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device);
template <typename FloatType, typename Device>
void AccumulatePathLengths(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device);
template <typename FloatType, typename Device>
void FindLostRays(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device);
void FindLostRays(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device);
template <typename FloatType, typename Device>
void SampleCells(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device);
void SampleCells(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device);
template <typename FloatType, typename Device>
void IntegrateCells(Ray<FloatType>& rays, detail::RayTracking<FloatType>& tracker, Device);
@ -135,24 +177,60 @@ private:
template <typename FloatType, typename Device>
void OffsetMinDistances(Ray<FloatType>& rays, Device);
template <typename FloatType, typename Device>
void PrintRayStatus(Ray<FloatType>& rays, Device);
protected:
template <typename Device, typename FloatType>
void RenderOnDevice(Ray<FloatType>& rays, Device);
ConnectivityType MeshConn;
// Data set info
vtkm::cont::Field ScalarField;
vtkm::cont::Field EmissionField;
vtkm::cont::DynamicCellSet CellSet;
vtkm::cont::CoordinateSystem Coords;
vtkm::Range ScalarBounds;
vtkm::Float32 BoundingBox[6];
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorMap;
vtkm::cont::ArrayHandle<vtkm::Id> PreviousCellIds;
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
vtkm::Float32 SampleDistance;
vtkm::Id RaysLost;
IntegrationMode Integrator;
//
// flags
bool CountRayStatus;
bool MeshConnIsConstructed;
bool DebugFiltersOn;
bool ReEnterMesh; // Do not try to re-enter the mesh
bool CreatePartialComposites;
bool FieldAssocPoints;
bool HasEmission; // Mode for integrating through energy bins
// timers
vtkm::Float64 IntersectTime;
vtkm::Float64 IntegrateTime;
vtkm::Float64 SampleTime;
vtkm::Float64 LostRayTime;
vtkm::Float64 MeshEntryTime;
MeshConnContainer* MeshContainer;
}; // class ConnectivityTracer<CellType,ConnectivityType>
#ifndef vtk_m_rendering_raytracing_ConnectivityTracer_cxx
//extern explicit instantiations of ConnectivityTracer
extern template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_ZOO, UnstructuredMeshConn>;
extern template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_HEXAHEDRON, UnstructuredMeshConnSingleType>;
extern template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_WEDGE, UnstructuredMeshConnSingleType>;
extern template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_TETRA, UnstructuredMeshConnSingleType>;
extern template class VTKM_RENDERING_TEMPLATE_EXPORT
ConnectivityTracer<CELL_SHAPE_STRUCTURED, StructuredMeshConn>;
//extern template class VTKM_RENDERING_TEMPLATE_EXPORT
// ConnectivityTracer<CELL_SHAPE_ZOO>;
//extern template class VTKM_RENDERING_TEMPLATE_EXPORT
// ConnectivityTracer<CELL_SHAPE_HEXAHEDRON>;
//extern template class VTKM_RENDERING_TEMPLATE_EXPORT
// ConnectivityTracer<CELL_SHAPE_WEDGE>;
//extern template class VTKM_RENDERING_TEMPLATE_EXPORT
// ConnectivityTracer<CELL_SHAPE_TETRA>;
//extern template class VTKM_RENDERING_TEMPLATE_EXPORT
// ConnectivityTracer<CELL_SHAPE_STRUCTURED>;
#endif
}
}

@ -21,13 +21,13 @@
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/DeviceAdapterListHelpers.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/CellIntersector.h>
#include <vtkm/rendering/raytracing/CellSampler.h>
#include <vtkm/rendering/raytracing/CellTables.h>
#include <vtkm/rendering/raytracing/ConnectivityBase.h>
#include <vtkm/rendering/raytracing/MeshConnectivityStructures.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBase.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
@ -110,15 +110,11 @@ void RayTracking<FloatType>::Init(const vtkm::Id size,
// Init the exit faces. This value is used to load the next cell
// base on the cell and face it left
//
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Int32>> initExitFaceDispatcher(
MemSet<vtkm::Int32>(-1));
initExitFaceDispatcher.SetDevice(Device());
initExitFaceDispatcher.Invoke(ExitFace);
vtkm::cont::ArrayHandleConstant<vtkm::Int32> negOne(-1, size);
vtkm::cont::Algorithm::Copy(Device(), negOne, ExitFace);
vtkm::worklet::DispatcherMapField<MemSet<FloatType>> initExitDistanceDispatcher(
MemSet<FloatType>(-1));
initExitDistanceDispatcher.SetDevice(Device());
initExitDistanceDispatcher.Invoke(*ExitDist);
vtkm::cont::ArrayHandleConstant<FloatType> negOnef(-1.f, size);
vtkm::cont::Algorithm::Copy(Device(), negOnef, *ExitDist);
}
template <typename FloatType>
@ -131,6 +127,20 @@ void RayTracking<FloatType>::Swap()
}
} //namespace detail
template <typename FloatType, typename Device>
void ConnectivityTracer::PrintRayStatus(Ray<FloatType>& rays, Device)
{
vtkm::Id raysExited = RayOperations::GetStatusCount(rays, RAY_EXITED_MESH, Device());
vtkm::Id raysActive = RayOperations::GetStatusCount(rays, RAY_ACTIVE, Device());
vtkm::Id raysAbandoned = RayOperations::GetStatusCount(rays, RAY_ABANDONED, Device());
vtkm::Id raysExitedDom = RayOperations::GetStatusCount(rays, RAY_EXITED_DOMAIN, Device());
std::cout << "\r Ray Status " << std::setw(10) << std::left << " Lost " << std::setw(10)
<< std::left << RaysLost << std::setw(10) << std::left << " Exited " << std::setw(10)
<< std::left << raysExited << std::setw(10) << std::left << " Active " << std::setw(10)
<< raysActive << std::setw(10) << std::left << " Abandoned " << std::setw(10)
<< raysAbandoned << " Exited Domain " << std::setw(10) << std::left << raysExitedDom
<< "\n";
}
//
// Advance Ray
@ -160,16 +170,15 @@ public:
}
}; //class AdvanceRay
template <vtkm::Int32 CellType, typename FloatType, typename MeshType>
template <typename FloatType>
class LocateCell : public vtkm::worklet::WorkletMapField
{
private:
MeshType MeshConn;
CellIntersector<CellType> Intersector;
const MeshConnectivityBase* MeshConn;
CellIntersector<255> Intersector;
public:
template <typename ConnectivityType>
LocateCell(ConnectivityType& meshConn)
LocateCell(const MeshConnectivityBase* meshConn)
: MeshConn(meshConn)
{
}
@ -196,7 +205,7 @@ public:
{
if (enterFace != -1 && rayStatus == RAY_ACTIVE)
{
currentCell = MeshConn.GetConnectingCell(currentCell, enterFace);
currentCell = MeshConn->GetConnectingCell(currentCell, enterFace);
if (currentCell == -1)
rayStatus = RAY_EXITED_MESH;
enterFace = -1;
@ -212,7 +221,7 @@ public:
vtkm::Id cellConn[8];
FloatType distances[6];
const vtkm::Int32 numIndices = MeshConn.GetCellIndices(cellConn, currentCell);
const vtkm::Int32 numIndices = MeshConn->GetCellIndices(cellConn, currentCell);
//load local cell data
for (int i = 0; i < numIndices; ++i)
{
@ -222,7 +231,7 @@ public:
ypoints[i] = point[1];
zpoints[i] = point[2];
}
const vtkm::UInt8 cellShape = MeshConn.GetCellShape(currentCell);
const vtkm::UInt8 cellShape = MeshConn->GetCellShape(currentCell);
Intersector.IntersectCell(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
CellTables tables;
@ -267,7 +276,7 @@ public:
} //operator
}; //class LocateCell
template <vtkm::Int32 CellType, typename FloatType, typename Device, typename MeshType>
template <typename FloatType, typename Device>
class RayBumper : public vtkm::worklet::WorkletMapField
{
private:
@ -276,15 +285,14 @@ private:
FloatTypePortal DirectionsX;
FloatTypePortal DirectionsY;
FloatTypePortal DirectionsZ;
MeshType MeshConn;
CellIntersector<CellType> Intersector;
const MeshConnectivityBase* MeshConn;
CellIntersector<255> Intersector;
const vtkm::UInt8 FailureStatus; // the status to assign ray if we fail to find the intersection
public:
template <typename ConnectivityType>
RayBumper(FloatTypeHandle dirsx,
FloatTypeHandle dirsy,
FloatTypeHandle dirsz,
ConnectivityType meshConn,
const MeshConnectivityBase* meshConn,
vtkm::UInt8 failureStatus = RAY_ABANDONED)
: DirectionsX(dirsx.PrepareForInPlace(Device()))
, DirectionsY(dirsy.PrepareForInPlace(Device()))
@ -327,7 +335,7 @@ public:
FloatType distances[6];
vtkm::Vec<FloatType, 3> centroid(0., 0., 0.);
const vtkm::Int32 numIndices = MeshConn.GetCellIndices(cellConn, currentCell);
const vtkm::Int32 numIndices = MeshConn->GetCellIndices(cellConn, currentCell);
//load local cell data
for (int i = 0; i < numIndices; ++i)
{
@ -358,7 +366,7 @@ public:
DirectionsY.Set(pixelIndex, dir[1]);
DirectionsZ.Set(pixelIndex, dir[2]);
const vtkm::UInt8 cellShape = MeshConn.GetCellShape(currentCell);
const vtkm::UInt8 cellShape = MeshConn->GetCellShape(currentCell);
Intersector.IntersectCell(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
CellTables tables;
@ -674,7 +682,7 @@ public:
}
};
template <vtkm::Int32 CellType, typename FloatType, typename Device, typename MeshType>
template <typename FloatType, typename Device>
class SampleCellAssocCells : public vtkm::worklet::WorkletMapField
{
private:
@ -683,23 +691,22 @@ private:
using ColorConstPortal = typename ColorHandle::ExecutionTypes<Device>::PortalConst;
using ColorPortal = typename ColorBuffer::template ExecutionTypes<Device>::Portal;
CellSampler<CellType> Sampler;
CellSampler<255> Sampler;
FloatType SampleDistance;
FloatType MinScalar;
FloatType InvDeltaScalar;
ColorPortal FrameBuffer;
ColorConstPortal ColorMap;
MeshType MeshConn;
const MeshConnectivityBase* MeshConn;
vtkm::Int32 ColorMapSize;
public:
template <typename ConnectivityType>
SampleCellAssocCells(const FloatType& sampleDistance,
const FloatType& minScalar,
const FloatType& maxScalar,
ColorHandle& colorMap,
ColorBuffer& frameBuffer,
ConnectivityType& meshConn)
const MeshConnectivityBase* meshConn)
: SampleDistance(sampleDistance)
, MinScalar(minScalar)
, ColorMap(colorMap.PrepareForInput(Device()))
@ -792,7 +799,7 @@ public:
}
}; //class Sample cell
template <vtkm::Int32 CellType, typename FloatType, typename Device, typename MeshType>
template <typename FloatType, typename Device>
class SampleCellAssocPoints : public vtkm::worklet::WorkletMapField
{
private:
@ -801,9 +808,9 @@ private:
using ColorConstPortal = typename ColorHandle::ExecutionTypes<Device>::PortalConst;
using ColorPortal = typename ColorBuffer::template ExecutionTypes<Device>::Portal;
CellSampler<CellType> Sampler;
CellSampler<255> Sampler;
FloatType SampleDistance;
MeshType MeshConn;
const MeshConnectivityBase* MeshConn;
FloatType MinScalar;
FloatType InvDeltaScalar;
ColorPortal FrameBuffer;
@ -811,13 +818,12 @@ private:
vtkm::Id ColorMapSize;
public:
template <typename ConnectivityType>
SampleCellAssocPoints(const FloatType& sampleDistance,
const FloatType& minScalar,
const FloatType& maxScalar,
ColorHandle& colorMap,
ColorBuffer& frameBuffer,
ConnectivityType& meshConn)
const MeshConnectivityBase* meshConn)
: SampleDistance(sampleDistance)
, MeshConn(meshConn)
, MinScalar(minScalar)
@ -881,7 +887,7 @@ public:
}
//load local scalar cell data
vtkm::Id cellConn[8];
const vtkm::Int32 numIndices = MeshConn.GetCellIndices(cellConn, currentCell);
const vtkm::Int32 numIndices = MeshConn->GetCellIndices(cellConn, currentCell);
for (int i = 0; i < numIndices; ++i)
{
BOUNDS_CHECK(scalarPortal, cellConn[i]);
@ -900,7 +906,7 @@ public:
currentDistance = enterDistance;
}
const vtkm::Int32 cellShape = MeshConn.GetCellShape(currentCell);
const vtkm::Int32 cellShape = MeshConn->GetCellShape(currentCell);
while (enterDistance <= currentDistance && currentDistance <= exitDistance)
{
vtkm::Vec<FloatType, 3> sampleLoc = origin + currentDistance * dir;
@ -952,37 +958,34 @@ public:
}
}; //class Sample cell
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::IntersectCell(
Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
void ConnectivityTracer::IntersectCell(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device)
{
using LocateC = LocateCell<CellType, FloatType, MeshConnExec<ConnectivityType, Device>>;
using LocateC = LocateCell<FloatType>;
vtkm::cont::Timer<Device> timer;
vtkm::worklet::DispatcherMapField<LocateC> dispatcher((LocateC(MeshConn)));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.HitIdx,
this->MeshConn.GetCoordinates(),
rays.Dir,
*(tracker.EnterDist),
*(tracker.ExitDist),
tracker.ExitFace,
rays.Status,
rays.Origin);
vtkm::worklet::DispatcherMapField<LocateC> locateDispatch(meshConn);
locateDispatch.SetDevice(Device());
locateDispatch.Invoke(rays.HitIdx,
this->Coords,
rays.Dir,
*(tracker.EnterDist),
*(tracker.ExitDist),
tracker.ExitFace,
rays.Status,
rays.Origin);
if (this->CountRayStatus)
RaysLost = RayOperations::GetStatusCount(rays, RAY_LOST, Device());
this->IntersectTime += timer.GetElapsedTime();
}
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::AccumulatePathLengths(
Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
void ConnectivityTracer::AccumulatePathLengths(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
{
vtkm::worklet::DispatcherMapField<AddPathLengths<FloatType>> dispatcher(
(AddPathLengths<FloatType>()));
@ -991,41 +994,37 @@ void ConnectivityTracer<CellType, ConnectivityType>::AccumulatePathLengths(
rays.Status, *(tracker.EnterDist), *(tracker.ExitDist), rays.GetBuffer("path_lengths").Buffer);
}
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::FindLostRays(
Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
void ConnectivityTracer::FindLostRays(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device)
{
using RayB = RayBumper<CellType, FloatType, Device, MeshConnExec<ConnectivityType, Device>>;
using RayB = RayBumper<FloatType, Device>;
vtkm::cont::Timer<Device> timer;
vtkm::worklet::DispatcherMapField<RayB> dispatcher(
RayB(rays.DirX, rays.DirY, rays.DirZ, this->MeshConn));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.HitIdx,
this->MeshConn.GetCoordinates(),
*(tracker.EnterDist),
*(tracker.ExitDist),
tracker.ExitFace,
rays.Status,
rays.Origin);
vtkm::worklet::DispatcherMapField<RayB> bumpDispatch(
RayB(rays.DirX, rays.DirY, rays.DirZ, meshConn));
bumpDispatch.SetDevice(Device());
bumpDispatch.Invoke(rays.HitIdx,
this->Coords,
*(tracker.EnterDist),
*(tracker.ExitDist),
tracker.ExitFace,
rays.Status,
rays.Origin);
this->LostRayTime += timer.GetElapsedTime();
}
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::SampleCells(
Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
void ConnectivityTracer::SampleCells(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
const MeshConnectivityBase* meshConn,
Device)
{
using SampleP =
SampleCellAssocPoints<CellType, FloatType, Device, MeshConnExec<ConnectivityType, Device>>;
using SampleC =
SampleCellAssocCells<CellType, FloatType, Device, MeshConnExec<ConnectivityType, Device>>;
using SampleP = SampleCellAssocPoints<FloatType, Device>;
using SampleC = SampleCellAssocCells<FloatType, Device>;
vtkm::cont::Timer<Device> timer;
VTKM_ASSERT(rays.Buffers.at(0).GetNumChannels() == 4);
@ -1038,10 +1037,10 @@ void ConnectivityTracer<CellType, ConnectivityType>::SampleCells(
vtkm::Float32(this->ScalarBounds.Max),
this->ColorMap,
rays.Buffers.at(0).Buffer,
this->MeshConn));
meshConn));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.HitIdx,
this->MeshConn.GetCoordinates(),
this->Coords,
this->ScalarField.GetData(),
*(tracker.EnterDist),
*(tracker.ExitDist),
@ -1058,7 +1057,7 @@ void ConnectivityTracer<CellType, ConnectivityType>::SampleCells(
vtkm::Float32(this->ScalarBounds.Max),
this->ColorMap,
rays.Buffers.at(0).Buffer,
this->MeshConn));
meshConn));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.HitIdx,
this->ScalarField.GetData(),
@ -1071,12 +1070,10 @@ void ConnectivityTracer<CellType, ConnectivityType>::SampleCells(
this->SampleTime += timer.GetElapsedTime();
}
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::IntegrateCells(
Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
void ConnectivityTracer::IntegrateCells(Ray<FloatType>& rays,
detail::RayTracking<FloatType>& tracker,
Device)
{
vtkm::cont::Timer<Device> timer;
if (HasEmission)
@ -1114,9 +1111,9 @@ void ConnectivityTracer<CellType, ConnectivityType>::IntegrateCells(
IntegrateTime += timer.GetElapsedTime();
}
// template <vtkm::Int32 CellType, typename ConnectivityType>
// template <vtkm::Int32 CellType>
// template <typename FloatType>
// void ConnectivityTracer<CellType,ConnectivityType>::PrintDebugRay(Ray<FloatType>& rays, vtkm::Id rayId)
// void ConnectivityTracer<CellType>::PrintDebugRay(Ray<FloatType>& rays, vtkm::Id rayId)
// {
// vtkm::Id index = -1;
// for (vtkm::Id i = 0; i < rays.NumRays; ++i)
@ -1142,10 +1139,8 @@ void ConnectivityTracer<CellType, ConnectivityType>::IntegrateCells(
// std::cout << "+++++++++++++++++++++++++\n";
// }
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename FloatType, typename Device>
void ConnectivityTracer<CellType, ConnectivityType>::OffsetMinDistances(Ray<FloatType>& rays,
Device)
void ConnectivityTracer::OffsetMinDistances(Ray<FloatType>& rays, Device)
{
vtkm::worklet::DispatcherMapField<AdvanceRay<FloatType>> dispatcher(
AdvanceRay<FloatType>(FloatType(0.001)));
@ -1153,22 +1148,26 @@ void ConnectivityTracer<CellType, ConnectivityType>::OffsetMinDistances(Ray<Floa
dispatcher.Invoke(rays.Status, rays.MinDistance);
}
template <vtkm::Int32 CellType, typename ConnectivityType>
template <typename Device, typename FloatType>
void ConnectivityTracer<CellType, ConnectivityType>::RenderOnDevice(Ray<FloatType>& rays, Device)
void ConnectivityTracer::RenderOnDevice(Ray<FloatType>& rays, Device)
{
this->RaysLost = 0;
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("conn_tracer");
logger->AddLogData("device", GetDeviceString(Device()));
this->ResetTimers();
vtkm::cont::Timer<Device> renderTimer;
this->SetBoundingBox(Device());
vtkm::cont::DeviceAdapterId devId = Device();
const MeshConnectivityBase* meshConn = MeshContainer->Construct(devId);
//this->SetBoundingBox(Device());
bool hasPathLengths = rays.HasBuffer("path_lengths");
vtkm::cont::Timer<Device> timer;
this->Init();
this->Init(); // sets sample distance
//
// All Rays begin as exited to force intersection
//
@ -1180,9 +1179,7 @@ void ConnectivityTracer<CellType, ConnectivityType>::RenderOnDevice(Ray<FloatTyp
vtkm::Float64 time = timer.GetElapsedTime();
logger->AddLogData("init", time);
MeshConn.Construct(Device());
//CountRayStatus = true;
bool cullMissedRays = true;
bool workRemaining = true;
if (this->CountRayStatus)
@ -1197,7 +1194,7 @@ void ConnectivityTracer<CellType, ConnectivityType>::RenderOnDevice(Ray<FloatTyp
//
// if ray misses the external face it will be marked RAY_EXITED_MESH
//
MeshConn.FindEntry(rays, Device());
MeshContainer->FindEntry(rays, devId);
MeshEntryTime += entryTimer.GetElapsedTime();
}
@ -1225,17 +1222,17 @@ void ConnectivityTracer<CellType, ConnectivityType>::RenderOnDevice(Ray<FloatTyp
{
//
// Rays the leave the mesh will be marked as RAYEXITED_MESH
this->IntersectCell(rays, rayTracker, Device());
this->IntersectCell(rays, rayTracker, meshConn, Device());
//
// If the ray was lost due to precision issues, we find it.
// If it is marked RAY_ABANDONED, then something went wrong.
//
this->FindLostRays(rays, rayTracker, Device());
this->FindLostRays(rays, rayTracker, meshConn, Device());
//
// integrate along the ray
//
if (this->Integrator == Volume)
this->SampleCells(rays, rayTracker, Device());
this->SampleCells(rays, rayTracker, meshConn, Device());
else
this->IntegrateCells(rays, rayTracker, Device());

@ -1,170 +0,0 @@
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 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/ConnectivityTracerBase.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/rendering/raytracing/Logger.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
ConnectivityTracerBase::ConnectivityTracerBase()
: ConnectivityBase()
, CountRayStatus(false)
{
}
ConnectivityTracerBase::~ConnectivityTracerBase()
{
}
void ConnectivityTracerBase::SetDebugOn(bool on)
{
CountRayStatus = on;
}
void ConnectivityTracerBase::Init()
{
//
// Check to see if a sample distance was set
//
if (SampleDistance <= 0)
{
const vtkm::Float32 defaultSampleRate = 200.f;
// We need to set some default sample distance
vtkm::Vec<vtkm::Float32, 3> extent;
extent[0] = BoundingBox[1] - BoundingBox[0];
extent[1] = BoundingBox[3] - BoundingBox[2];
extent[2] = BoundingBox[5] - BoundingBox[4];
SampleDistance = vtkm::Magnitude(extent) / defaultSampleRate;
}
}
void ConnectivityTracerBase::SetColorMap(
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap)
{
ColorMap = colorMap;
}
void ConnectivityTracerBase::SetVolumeData(const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarBounds)
{
//TODO: Need a way to tell if we have been updated
ScalarField = scalarField;
ScalarBounds = scalarBounds;
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 cell set or points");
FieldAssocPoints = ScalarField.GetAssociation() == vtkm::cont::Field::Association::POINTS;
this->Integrator = Volume;
}
void ConnectivityTracerBase::SetEnergyData(const vtkm::cont::Field& absorption,
const vtkm::Int32 numBins,
const vtkm::cont::Field& emission)
{
bool isSupportedField = absorption.GetAssociation() == vtkm::cont::Field::Association::CELL_SET;
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue("Absorption Field '" + absorption.GetName() +
"' not accociated with cells");
ScalarField = absorption;
// Check for emission
HasEmission = false;
if (emission.GetAssociation() != vtkm::cont::Field::Association::ANY)
{
if (emission.GetAssociation() != vtkm::cont::Field::Association::CELL_SET)
throw vtkm::cont::ErrorBadValue("Emission Field '" + emission.GetName() +
"' not accociated with cells");
HasEmission = true;
EmissionField = emission;
}
// Do some basic range checking
if (numBins < 1)
throw vtkm::cont::ErrorBadValue("Number of energy bins is less than 1");
vtkm::Id binCount = ScalarField.GetData().GetNumberOfValues();
vtkm::Id cellCount = this->GetNumberOfMeshCells();
if (cellCount != (binCount / vtkm::Id(numBins)))
{
std::stringstream message;
message << "Invalid number of absorption bins\n";
message << "Number of cells: " << cellCount << "\n";
message << "Number of field values: " << binCount << "\n";
message << "Number of bins: " << numBins << "\n";
throw vtkm::cont::ErrorBadValue(message.str());
}
if (HasEmission)
{
binCount = EmissionField.GetData().GetNumberOfValues();
if (cellCount != (binCount / vtkm::Id(numBins)))
{
std::stringstream message;
message << "Invalid number of emission bins\n";
message << "Number of cells: " << cellCount << "\n";
message << "Number of field values: " << binCount << "\n";
message << "Number of bins: " << numBins << "\n";
throw vtkm::cont::ErrorBadValue(message.str());
}
}
//TODO: Need a way to tell if we have been updated
this->Integrator = Energy;
}
void ConnectivityTracerBase::SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
{
BackgroundColor = backgroundColor;
}
void ConnectivityTracerBase::SetSampleDistance(const vtkm::Float32& distance)
{
if (distance <= 0.f)
throw vtkm::cont::ErrorBadValue("Sample distance must be positive.");
SampleDistance = distance;
}
void ConnectivityTracerBase::ResetTimers()
{
IntersectTime = 0.;
IntegrateTime = 0.;
SampleTime = 0.;
LostRayTime = 0.;
MeshEntryTime = 0.;
}
void ConnectivityTracerBase::LogTimers()
{
Logger* logger = Logger::GetInstance();
logger->AddLogData("intersect ", IntersectTime);
logger->AddLogData("integrate ", IntegrateTime);
logger->AddLogData("sample_cells ", SampleTime);
logger->AddLogData("lost_rays ", LostRayTime);
logger->AddLogData("mesh_entry", LostRayTime);
}
}
}
}

@ -1,118 +0,0 @@
//============================================================================
// 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_ConnectivityTracerBase_h
#define vtk_m_rendering_raytracing_ConnectivityTracerBase_h
#include <vtkm/rendering/vtkm_rendering_export.h>
#include <vtkm/rendering/raytracing/ConnectivityBase.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/Bounds.h>
#include <vtkm/Range.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/Field.h>
#include <iomanip>
#include <iostream>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT ConnectivityTracerBase : public ConnectivityBase
{
public:
ConnectivityTracerBase();
virtual ~ConnectivityTracerBase();
void Init();
virtual vtkm::Id GetNumberOfMeshCells() = 0;
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap) override;
void SetVolumeData(const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarBounds) override;
void SetEnergyData(const vtkm::cont::Field& absorption,
const vtkm::Int32 numBins,
const vtkm::cont::Field& emission) override;
void SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor) override;
void SetSampleDistance(const vtkm::Float32& distance) override;
void SetDebugOn(bool on) override;
protected:
vtkm::cont::Field ScalarField;
vtkm::cont::Field EmissionField;
vtkm::Range ScalarBounds;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorMap;
vtkm::Float32 BoundingBox[6];
vtkm::cont::ArrayHandle<vtkm::Id> PreviousCellIds;
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
vtkm::Float32 SampleDistance;
bool CountRayStatus;
vtkm::Id RaysLost;
IntegrationMode Integrator;
bool DebugFiltersOn;
bool ReEnterMesh; // Do not try to re-enter the mesh
bool CreatePartialComposites;
bool FieldAssocPoints;
bool HasEmission; // Mode for integrating through energy bins
// timers
vtkm::Float64 IntersectTime;
vtkm::Float64 IntegrateTime;
vtkm::Float64 SampleTime;
vtkm::Float64 LostRayTime;
vtkm::Float64 MeshEntryTime;
template <typename FloatType, typename Device>
void PrintRayStatus(Ray<FloatType>& rays, Device)
{
vtkm::Id raysExited = RayOperations::GetStatusCount(rays, RAY_EXITED_MESH, Device());
vtkm::Id raysActive = RayOperations::GetStatusCount(rays, RAY_ACTIVE, Device());
vtkm::Id raysAbandoned = RayOperations::GetStatusCount(rays, RAY_ABANDONED, Device());
vtkm::Id raysExitedDom = RayOperations::GetStatusCount(rays, RAY_EXITED_DOMAIN, Device());
std::cout << "\r Ray Status " << std::setw(10) << std::left << " Lost " << std::setw(10)
<< std::left << RaysLost << std::setw(10) << std::left << " Exited " << std::setw(10)
<< std::left << raysExited << std::setw(10) << std::left << " Active "
<< std::setw(10) << raysActive << std::setw(10) << std::left << " Abandoned "
<< std::setw(10) << raysAbandoned << " Exited Domain " << std::setw(10) << std::left
<< raysExitedDom << "\n";
}
void ResetTimers();
void LogTimers();
};
}
}
}
#endif

@ -1,112 +0,0 @@
//============================================================================
// 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/ConnectivityTracer.h>
#include <vtkm/rendering/raytracing/ConnectivityTracerFactory.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#ifndef CELL_SHAPE_ZOO
#define CELL_SHAPE_ZOO 255
#endif
#ifndef CELL_SHAPE_STRUCTURED
#define CELL_SHAPE_STRUCTURED 254
#endif
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
//----------------------------------------------------------------------------
ConnectivityTracerFactory::TracerType ConnectivityTracerFactory::DetectCellSetType(
const vtkm::cont::DynamicCellSet& cellset)
{
ConnectivityTracerFactory::TracerType type = Unsupported;
if (cellset.IsSameType(vtkm::cont::CellSetExplicit<>()))
{
type = Unstructured;
}
else if (cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))
{
vtkm::cont::CellSetSingleType<> singleType = cellset.Cast<vtkm::cont::CellSetSingleType<>>();
//
// Now we need to determine what type of cells this holds
//
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
singleType.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::UInt8 shapeType = shapes.GetPortalConstControl().Get(0);
if (shapeType == CELL_SHAPE_HEXAHEDRON)
type = UnstructuredHex;
if (shapeType == CELL_SHAPE_TETRA)
type = UnstructuredTet;
if (shapeType == CELL_SHAPE_WEDGE)
type = UnstructuredWedge;
if (shapeType == CELL_SHAPE_PYRAMID)
type = UnstructuredPyramid;
}
else if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
type = Structured;
}
return type;
}
//----------------------------------------------------------------------------
ConnectivityBase* ConnectivityTracerFactory::CreateTracer(
const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords)
{
ConnectivityTracerFactory::TracerType type = DetectCellSetType(cellset);
if (type == Unstructured)
{
UnstructuredMeshConn meshConn(cellset, coords);
return new ConnectivityTracer<CELL_SHAPE_ZOO, UnstructuredMeshConn>(meshConn);
}
else if (type == UnstructuredHex)
{
UnstructuredMeshConnSingleType meshConn(cellset, coords);
return new ConnectivityTracer<CELL_SHAPE_HEXAHEDRON, UnstructuredMeshConnSingleType>(meshConn);
}
else if (type == UnstructuredWedge)
{
UnstructuredMeshConnSingleType meshConn(cellset, coords);
return new ConnectivityTracer<CELL_SHAPE_WEDGE, UnstructuredMeshConnSingleType>(meshConn);
}
else if (type == UnstructuredTet)
{
UnstructuredMeshConnSingleType meshConn(cellset, coords);
return new ConnectivityTracer<CELL_SHAPE_TETRA, UnstructuredMeshConnSingleType>(meshConn);
}
else if (type == Structured)
{
StructuredMeshConn meshConn(cellset, coords);
return new ConnectivityTracer<CELL_SHAPE_STRUCTURED, StructuredMeshConn>(meshConn);
}
throw vtkm::cont::ErrorBadValue("Connectivity tracer: cell set type unsupported");
}
}
}
} // namespace vtkm::rendering::raytracing

@ -1,64 +0,0 @@
//============================================================================
// 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 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 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_ConnectivityTracerFactory_h
#define vtk_m_rendering_raytracing_ConnectivityTracerFactory_h
#include <vtkm/rendering/raytracing/ConnectivityBase.h>
#include <vtkm/rendering/vtkm_rendering_export.h>
#include <vtkm/cont/DynamicCellSet.h>
namespace vtkm
{
namespace cont
{ //forward declares
class CoordinateSystem;
}
namespace rendering
{
namespace raytracing
{
class VTKM_RENDERING_EXPORT ConnectivityTracerFactory
{
public:
enum TracerType
{
Unsupported = 0,
Structured = 1,
Unstructured = 2,
UnstructuredHex = 3,
UnstructuredTet = 4,
UnstructuredWedge = 5,
UnstructuredPyramid = 6
};
//----------------------------------------------------------------------------
static TracerType DetectCellSetType(const vtkm::cont::DynamicCellSet& cellset);
//----------------------------------------------------------------------------
static ConnectivityBase* CreateTracer(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords);
};
}
}
} // namespace vtkm::rendering::raytracing
#endif

@ -20,23 +20,8 @@
#ifndef vtk_m_rendering_raytracing_MeshConnectivityBuilder_h
#define vtk_m_rendering_raytracing_MeshConnectivityBuilder_h
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/CellSetSingleType.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/rendering/raytracing/CellTables.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/MortonCodes.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/MeshConnectivityContainers.h>
namespace vtkm
{
@ -45,790 +30,36 @@ namespace rendering
namespace raytracing
{
struct IsExternal
{
VTKM_EXEC_CONT
inline bool operator()(const vtkm::Id& x) const { return (x < 0); }
}; //struct IsExternal
class CountFaces : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CountFaces() {}
using ControlSignature = void(WholeArrayIn<>, FieldOut<>);
using ExecutionSignature = void(_1, _2, WorkIndex);
template <typename ShapePortalType>
VTKM_EXEC inline void operator()(const ShapePortalType& shapes,
vtkm::Id& faces,
const vtkm::Id& index) const
{
BOUNDS_CHECK(shapes, index);
vtkm::UInt8 shapeType = shapes.Get(index);
if (shapeType == vtkm::CELL_SHAPE_TETRA)
{
faces = 4;
}
else if (shapeType == vtkm::CELL_SHAPE_HEXAHEDRON)
{
faces = 6;
}
else if (shapeType == vtkm::CELL_SHAPE_WEDGE)
{
faces = 5;
}
else if (shapeType == vtkm::CELL_SHAPE_PYRAMID)
{
faces = 5;
}
else
{
faces = 0;
}
}
}; //class CountFaces
class MortonNeighbor : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
MortonNeighbor() {}
using ControlSignature = void(WholeArrayIn<>,
WholeArrayInOut<Id3Type>,
WholeArrayIn<>,
WholeArrayIn<>,
WholeArrayIn<>,
WholeArrayOut<>);
using ExecutionSignature = void(_1, _2, WorkIndex, _3, _4, _5, _6);
VTKM_EXEC
inline vtkm::Int32 GetShapeOffset(const vtkm::UInt8& shapeType) const
{
CellTables tables;
//TODO: This might be better as if if if
vtkm::Int32 tableOffset = 0;
if (shapeType == vtkm::CELL_SHAPE_TETRA)
{
tableOffset = tables.FaceLookUp(1, 0);
}
else if (shapeType == vtkm::CELL_SHAPE_HEXAHEDRON)
{
tableOffset = tables.FaceLookUp(0, 0);
}
else if (shapeType == vtkm::CELL_SHAPE_WEDGE)
{
tableOffset = tables.FaceLookUp(2, 0);
}
else if (shapeType == vtkm::CELL_SHAPE_PYRAMID)
{
tableOffset = tables.FaceLookUp(3, 0);
}
else
printf("Error shape not recognized %d\n", (int)shapeType);
return tableOffset;
}
VTKM_EXEC
inline bool IsIn(const vtkm::Id& needle,
const vtkm::Vec<vtkm::Id, 4>& heystack,
const vtkm::Int32& numIndices) const
{
bool isIn = false;
for (vtkm::Int32 i = 0; i < numIndices; ++i)
{
if (needle == heystack[i])
isIn = true;
}
return isIn;
}
template <typename MortonPortalType,
typename FaceIdPairsPortalType,
typename ConnPortalType,
typename ShapePortalType,
typename OffsetPortalType,
typename ExternalFaceFlagType>
VTKM_EXEC inline void operator()(const MortonPortalType& mortonCodes,
FaceIdPairsPortalType& faceIdPairs,
const vtkm::Id& index,
const ConnPortalType& connectivity,
const ShapePortalType& shapes,
const OffsetPortalType& offsets,
ExternalFaceFlagType& flags) const
{
if (index == 0)
{
return;
}
vtkm::Id currentIndex = index - 1;
BOUNDS_CHECK(mortonCodes, index);
vtkm::UInt32 myCode = mortonCodes.Get(index);
BOUNDS_CHECK(mortonCodes, currentIndex);
vtkm::UInt32 myNeighbor = mortonCodes.Get(currentIndex);
bool isInternal = false;
vtkm::Id connectedCell = -1;
CellTables tables;
while (currentIndex > -1 && myCode == myNeighbor)
{
myNeighbor = mortonCodes.Get(currentIndex);
// just because the codes are equal does not mean that
// they are the same face. We need to double check.
if (myCode == myNeighbor)
{
//get the index of the shape face in the table.
BOUNDS_CHECK(faceIdPairs, index);
vtkm::Id cellId1 = faceIdPairs.Get(index)[0];
BOUNDS_CHECK(faceIdPairs, currentIndex);
vtkm::Id cellId2 = faceIdPairs.Get(currentIndex)[0];
BOUNDS_CHECK(shapes, cellId1);
BOUNDS_CHECK(shapes, cellId2);
vtkm::Int32 shape1Offset =
GetShapeOffset(shapes.Get(cellId1)) + static_cast<vtkm::Int32>(faceIdPairs.Get(index)[1]);
vtkm::Int32 shape2Offset = GetShapeOffset(shapes.Get(cellId2)) +
static_cast<vtkm::Int32>(faceIdPairs.Get(currentIndex)[1]);
const vtkm::Int32 icount1 = tables.ShapesFaceList(shape1Offset, 0);
const vtkm::Int32 icount2 = tables.ShapesFaceList(shape2Offset, 0);
//Check to see if we have the same number of idices
if (icount1 != icount2)
continue;
//TODO: we can do better than this
vtkm::Vec<vtkm::Id, 4> indices1;
vtkm::Vec<vtkm::Id, 4> indices2;
const auto faceLength = tables.ShapesFaceList(shape1Offset, 0);
for (vtkm::Int32 i = 1; i <= faceLength; ++i)
{
BOUNDS_CHECK(offsets, cellId1);
BOUNDS_CHECK(offsets, cellId2);
BOUNDS_CHECK(connectivity,
(offsets.Get(cellId1) + tables.ShapesFaceList(shape1Offset, i)));
BOUNDS_CHECK(connectivity,
(offsets.Get(cellId2) + tables.ShapesFaceList(shape2Offset, i)));
indices1[i - 1] =
connectivity.Get(offsets.Get(cellId1) + tables.ShapesFaceList(shape1Offset, i));
indices2[i - 1] =
connectivity.Get(offsets.Get(cellId2) + tables.ShapesFaceList(shape2Offset, i));
}
bool isEqual = true;
for (vtkm::Int32 i = 0; i < faceLength; ++i)
{
if (!IsIn(indices1[i], indices2, faceLength))
isEqual = false;
}
if (isEqual)
{
isInternal = true;
connectedCell = cellId2;
break;
}
}
currentIndex--;
}
//this means that this cell is responsible for both itself and the other cell
//set the connection for the other cell
if (isInternal)
{
BOUNDS_CHECK(faceIdPairs, index);
vtkm::Vec<vtkm::Id, 3> facePair = faceIdPairs.Get(index);
vtkm::Id myCell = facePair[0];
facePair[2] = connectedCell;
BOUNDS_CHECK(faceIdPairs, index);
faceIdPairs.Set(index, facePair);
BOUNDS_CHECK(faceIdPairs, currentIndex);
facePair = faceIdPairs.Get(currentIndex);
facePair[2] = myCell;
BOUNDS_CHECK(faceIdPairs, currentIndex);
faceIdPairs.Set(currentIndex, facePair);
BOUNDS_CHECK(flags, currentIndex);
flags.Set(currentIndex, myCell);
BOUNDS_CHECK(flags, index);
flags.Set(index, connectedCell);
}
}
}; //class Neighbor
class ExternalTriangles : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
ExternalTriangles() {}
using ControlSignature =
void(FieldIn<>, WholeArrayIn<>, WholeArrayIn<>, WholeArrayIn<>, WholeArrayOut<>, FieldIn<>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
template <typename ShapePortalType,
typename InIndicesPortalType,
typename OutIndicesPortalType,
typename ShapeOffsetsPortal>
VTKM_EXEC inline void operator()(const vtkm::Vec<vtkm::Id, 3>& faceIdPair,
const ShapePortalType& shapes,
const ShapeOffsetsPortal& shapeOffsets,
const InIndicesPortalType& indices,
const OutIndicesPortalType& outputIndices,
const vtkm::Id& outputOffset) const
{
CellTables tables;
vtkm::Id cellId = faceIdPair[0];
BOUNDS_CHECK(shapeOffsets, cellId);
vtkm::Id offset = shapeOffsets.Get(cellId);
BOUNDS_CHECK(shapes, cellId);
vtkm::Int32 shapeId = static_cast<vtkm::Int32>(shapes.Get(cellId));
vtkm::Int32 shapesFaceOffset = tables.FaceLookUp(tables.CellTypeLookUp(shapeId), 0);
if (shapesFaceOffset == -1)
{
printf("Unsupported Shape Type %d\n", shapeId);
return;
}
vtkm::Vec<vtkm::Id, 4> faceIndices(-1, -1, -1, -1);
vtkm::Int32 tableIndex = static_cast<vtkm::Int32>(shapesFaceOffset + faceIdPair[1]);
const vtkm::Int32 numIndices = tables.ShapesFaceList(tableIndex, 0);
for (vtkm::Int32 i = 1; i <= numIndices; ++i)
{
BOUNDS_CHECK(indices, offset + tables.ShapesFaceList(tableIndex, i));
faceIndices[i - 1] = indices.Get(offset + tables.ShapesFaceList(tableIndex, i));
}
vtkm::Vec<vtkm::Id, 4> triangle;
triangle[0] = cellId;
triangle[1] = faceIndices[0];
triangle[2] = faceIndices[1];
triangle[3] = faceIndices[2];
BOUNDS_CHECK(outputIndices, outputOffset);
outputIndices.Set(outputOffset, triangle);
if (numIndices == 4)
{
triangle[1] = faceIndices[0];
triangle[2] = faceIndices[2];
triangle[3] = faceIndices[3];
BOUNDS_CHECK(outputIndices, outputOffset + 1);
outputIndices.Set(outputOffset + 1, triangle);
}
}
}; //class External Triangles
// Face conn was originally used for filtering out internal
// faces and was sorted with faces. To make it usable,
// we need to scatter back the connectivity into the original
// cell order, i.e., conn for cell 0 at 0,1,2,3,4,5
class WriteFaceConn : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn<>, WholeArrayIn<>, WholeArrayOut<IdType>);
using ExecutionSignature = void(_1, _2, _3);
VTKM_CONT
WriteFaceConn() {}
template <typename FaceOffsetsPortalType, typename FaceConnectivityPortalType>
VTKM_EXEC inline void operator()(const vtkm::Vec<vtkm::Id, 3>& faceIdPair,
const FaceOffsetsPortalType& faceOffsets,
FaceConnectivityPortalType& faceConn) const
{
vtkm::Id cellId = faceIdPair[0];
BOUNDS_CHECK(faceOffsets, cellId);
vtkm::Id faceOffset = faceOffsets.Get(cellId) + faceIdPair[1]; // cellOffset ++ faceId
BOUNDS_CHECK(faceConn, faceOffset);
faceConn.Set(faceOffset, faceIdPair[2]);
}
}; //class WriteFaceConn
class StructuredExternalTriangles : public vtkm::worklet::WorkletMapField
{
protected:
using ConnType = vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell,
3>;
ConnType Connectivity;
vtkm::Id Segments[7];
vtkm::Id3 CellDims;
public:
VTKM_CONT
StructuredExternalTriangles(const ConnType& connectivity)
: Connectivity(connectivity)
{
vtkm::Id3 cellDims = Connectivity.GetPointDimensions();
cellDims[0] -= 1;
cellDims[1] -= 1;
cellDims[2] -= 1;
CellDims = cellDims;
//We have 6 segments for each of the six faces.
Segments[0] = 0;
// 0-1 = the two faces parallel to the x-z plane
Segments[1] = cellDims[0] * cellDims[2];
Segments[2] = Segments[1] + Segments[1];
// 2-3 parallel to the y-z plane
Segments[3] = Segments[2] + cellDims[1] * cellDims[2];
Segments[4] = Segments[3] + cellDims[1] * cellDims[2];
// 4-5 parallel to the x-y plane
Segments[5] = Segments[4] + cellDims[1] * cellDims[0];
Segments[6] = Segments[5] + cellDims[1] * cellDims[0];
}
using ControlSignature = void(FieldIn<>, WholeArrayOut<>);
using ExecutionSignature = void(_1, _2);
template <typename TrianglePortalType>
VTKM_EXEC inline void operator()(const vtkm::Id& index, TrianglePortalType& triangles) const
{
// Each one of size segments will process
// one face of the hex and domain
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 SegmentToFace[6] = { 0, 2, 1, 3, 4, 5 };
// Each face/segment has 2 varying dimensions
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::Int32 SegmentDirections[6][2] = {
{ 0, 2 }, //face 0 and 2 have the same directions
{ 0, 2 }, { 1, 2 }, //1 and 3
{ 1, 2 }, { 0, 1 }, // 4 and 5
{ 0, 1 }
};
//
// We get one index per extenal face
//
//
// Cell face to extract which is also the domain
// face in this segment
//
vtkm::Int32 segment;
for (segment = 0; index >= Segments[segment + 1]; ++segment)
;
if (segment >= 6)
{
printf("OUT OF BOUDNS %d", (int)index);
}
vtkm::Int32 cellFace = SegmentToFace[segment];
// Face relative directions of the
// 2 varying coordinates.
vtkm::Int32 dir1, dir2;
dir1 = SegmentDirections[segment][0];
dir2 = SegmentDirections[segment][1];
// For each face, we will have a relative offset to
// the "bottom corner" of the face. Three are at the
// origin and we have to adjust for the other faces.
vtkm::Id3 cellIndex(0, 0, 0);
if (cellFace == 1)
cellIndex[0] = CellDims[0] - 1;
if (cellFace == 2)
cellIndex[1] = CellDims[1] - 1;
if (cellFace == 5)
cellIndex[2] = CellDims[2] - 1;
// index is the global index of all external faces
// the offset is the relative index of the cell
// on the current 2d face
vtkm::Id offset = index - Segments[segment];
vtkm::Id dir1Offset = offset % CellDims[dir1];
vtkm::Id dir2Offset = offset / CellDims[dir1];
cellIndex[dir1] = cellIndex[dir1] + dir1Offset;
cellIndex[dir2] = cellIndex[dir2] + dir2Offset;
vtkm::Id cellId = Connectivity.LogicalToFlatToIndex(cellIndex);
vtkm::VecVariable<vtkm::Id, 8> cellIndices = Connectivity.GetIndices(cellId);
// Look up the offset into the face list for each cell type
// This should always be zero, but in case this table changes I don't
// want to break anything.
CellTables tables;
vtkm::Int32 shapesFaceOffset =
tables.FaceLookUp(tables.CellTypeLookUp(CELL_SHAPE_HEXAHEDRON), 0);
vtkm::Vec<vtkm::Id, 4> faceIndices;
vtkm::Int32 tableIndex = shapesFaceOffset + cellFace;
// Load the face
for (vtkm::Int32 i = 1; i <= 4; ++i)
{
faceIndices[i - 1] = cellIndices[tables.ShapesFaceList(tableIndex, i)];
}
const vtkm::Id outputOffset = index * 2;
vtkm::Vec<vtkm::Id, 4> triangle;
triangle[0] = cellId;
triangle[1] = faceIndices[0];
triangle[2] = faceIndices[1];
triangle[3] = faceIndices[2];
BOUNDS_CHECK(triangles, outputOffset);
triangles.Set(outputOffset, triangle);
triangle[1] = faceIndices[0];
triangle[2] = faceIndices[2];
triangle[3] = faceIndices[3];
BOUNDS_CHECK(triangles, outputOffset);
triangles.Set(outputOffset + 1, triangle);
}
}; //class StructuredExternalTriangles
//If with output faces or triangles, we still have to calculate the size of the output
//array. TODO: switch to faces only
class CountExternalTriangles : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
CountExternalTriangles() {}
using ControlSignature = void(FieldIn<>, WholeArrayIn<>, FieldOut<>);
using ExecutionSignature = void(_1, _2, _3);
template <typename ShapePortalType>
VTKM_EXEC inline void operator()(const vtkm::Vec<vtkm::Id, 3>& faceIdPair,
const ShapePortalType& shapes,
vtkm::Id& triangleCount) const
{
CellTables tables;
vtkm::Id cellId = faceIdPair[0];
vtkm::Id cellFace = faceIdPair[1];
vtkm::Int32 shapeType = static_cast<vtkm::Int32>(shapes.Get(cellId));
vtkm::Int32 faceStartIndex = tables.FaceLookUp(tables.CellTypeLookUp(shapeType), 0);
if (faceStartIndex == -1)
{
//Unsupported Shape Type this should never happen
triangleCount = 0;
return;
}
vtkm::Int32 faceType =
tables.ShapesFaceList(faceStartIndex + static_cast<vtkm::Int32>(cellFace), 0);
// The face will either have 4 or 3 indices, so quad or tri
triangleCount = (faceType == 4) ? 2 : 1;
//faceConn.Set(faceOffset, faceIdPair[2]);
}
}; //class WriteFaceConn
template <typename DeviceAdapter>
class MeshConnectivityBuilder
{
public:
MeshConnectivityBuilder() {}
~MeshConnectivityBuilder() {}
MeshConnectivityBuilder();
~MeshConnectivityBuilder();
VTKM_CONT
MeshConnContainer* BuildConnectivity(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coordinates);
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> ExternalTrianglesStructured(
vtkm::cont::CellSetStructured<3>& cellSetStructured);
vtkm::cont::ArrayHandle<vtkm::Id> GetFaceConnectivity();
vtkm::cont::ArrayHandle<vtkm::Id> GetFaceOffsets();
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> GetExternalTriangles();
protected:
VTKM_CONT
void BuildConnectivity(vtkm::cont::CellSetSingleType<>& cellSetUnstructured,
const vtkm::cont::ArrayHandleVirtualCoordinates& coordinates,
vtkm::Bounds coordsBounds)
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("mesh_conn");
logger->AddLogData("device", GetDeviceString(DeviceAdapter()));
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::Float32 BoundingBox[6];
BoundingBox[0] = vtkm::Float32(coordsBounds.X.Min);
BoundingBox[1] = vtkm::Float32(coordsBounds.X.Max);
BoundingBox[2] = vtkm::Float32(coordsBounds.Y.Min);
BoundingBox[3] = vtkm::Float32(coordsBounds.Y.Max);
BoundingBox[4] = vtkm::Float32(coordsBounds.Z.Min);
BoundingBox[5] = vtkm::Float32(coordsBounds.Z.Max);
const vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes = cellSetUnstructured.GetShapesArray(
vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray(
vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
const vtkm::cont::ArrayHandleCounting<vtkm::Id> shapeOffsets =
cellSetUnstructured.GetIndexOffsetArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>> cellFaceId;
this->GenerateFaceConnnectivity(cellSetUnstructured,
shapes,
conn,
shapeOffsets,
coordinates,
faceConnectivity,
cellFaceId,
BoundingBox);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> externalTriangles;
//Extenal Faces
externalTriangles =
this->ExtractExternalFaces(cellFaceId, faceConnectivity, shapes, conn, shapeOffsets);
// scatter the coonectivity into the original order
vtkm::worklet::DispatcherMapField<WriteFaceConn> dispatcherWriteFaceConn;
dispatcherWriteFaceConn.SetDevice(DeviceAdapter());
dispatcherWriteFaceConn.Invoke(cellFaceId, this->FaceOffsets, faceConnectivity);
FaceConnectivity = faceConnectivity;
OutsideTriangles = externalTriangles;
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
vtkm::Bounds coordsBounds);
VTKM_CONT
void BuildConnectivity(vtkm::cont::CellSetExplicit<>& cellSetUnstructured,
const vtkm::cont::ArrayHandleVirtualCoordinates& coordinates,
vtkm::Bounds coordsBounds)
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("meah_conn");
logger->AddLogData("device", GetDeviceString(DeviceAdapter()));
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::Float32 BoundingBox[6];
BoundingBox[0] = vtkm::Float32(coordsBounds.X.Min);
BoundingBox[1] = vtkm::Float32(coordsBounds.X.Max);
BoundingBox[2] = vtkm::Float32(coordsBounds.Y.Min);
BoundingBox[3] = vtkm::Float32(coordsBounds.Y.Max);
BoundingBox[4] = vtkm::Float32(coordsBounds.Z.Min);
BoundingBox[5] = vtkm::Float32(coordsBounds.Z.Max);
const vtkm::cont::ArrayHandle<vtkm::UInt8> shapes = cellSetUnstructured.GetShapesArray(
vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray(
vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
const vtkm::cont::ArrayHandle<vtkm::Id> shapeOffsets = cellSetUnstructured.GetIndexOffsetArray(
vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>> cellFaceId;
this->GenerateFaceConnnectivity(cellSetUnstructured,
shapes,
conn,
shapeOffsets,
coordinates,
faceConnectivity,
cellFaceId,
BoundingBox);
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> externalTriangles;
//
//Extenal Faces
externalTriangles =
this->ExtractExternalFaces(cellFaceId, faceConnectivity, shapes, conn, shapeOffsets);
// scatter the coonectivity into the original order
vtkm::worklet::DispatcherMapField<WriteFaceConn> dispatcher{ (WriteFaceConn{}) };
dispatcher.SetDevice(DeviceAdapter());
dispatcher.Invoke(cellFaceId, this->FaceOffsets, faceConnectivity);
FaceConnectivity = faceConnectivity;
OutsideTriangles = externalTriangles;
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
// Should we just make this name BuildConnectivity?
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> ExternalTrianglesStructured(
vtkm::cont::CellSetStructured<3>& cellSetStructured)
{
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::Id3 cellDims = cellSetStructured.GetCellDimensions();
vtkm::Id numFaces =
cellDims[0] * cellDims[1] * 2 + cellDims[1] * cellDims[2] * 2 + cellDims[2] * cellDims[0] * 2;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles;
triangles.PrepareForOutput(numFaces * 2, DeviceAdapter());
vtkm::cont::ArrayHandleCounting<vtkm::Id> counting(0, 1, numFaces);
vtkm::worklet::DispatcherMapField<StructuredExternalTriangles> dispatcher(
StructuredExternalTriangles(cellSetStructured.PrepareForInput(
DeviceAdapter(), vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell())));
dispatcher.SetDevice(DeviceAdapter());
dispatcher.Invoke(counting, triangles);
vtkm::Float64 time = timer.GetElapsedTime();
Logger::GetInstance()->AddLogData("structured_external_faces", time);
return triangles;
}
vtkm::cont::ArrayHandle<vtkm::Id> GetFaceConnectivity() { return FaceConnectivity; }
vtkm::cont::ArrayHandle<vtkm::Id> GetFaceOffsets() { return FaceOffsets; }
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> GetExternalTriangles()
{
return OutsideTriangles;
}
protected:
template <typename CellSetType,
typename ShapeHandleType,
typename ConnHandleType,
typename OffsetsHandleType>
VTKM_CONT void GenerateFaceConnnectivity(
const CellSetType cellSet,
const ShapeHandleType shapes,
const ConnHandleType conn,
const OffsetsHandleType shapeOffsets,
const vtkm::cont::ArrayHandleVirtualCoordinates& coords,
vtkm::cont::ArrayHandle<vtkm::Id>& faceConnectivity,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>>& cellFaceId,
vtkm::Float32 BoundingBox[6])
{
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::Id numCells = shapes.GetNumberOfValues();
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> coordinates;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Copy(coords, coordinates);
/*-----------------------------------------------------------------*/
// Count the number of total faces in the cell set
vtkm::cont::ArrayHandle<vtkm::Id> facesPerCell;
vtkm::worklet::DispatcherMapField<CountFaces> countFacesDispatcher{ (CountFaces{}) };
countFacesDispatcher.SetDevice(DeviceAdapter());
countFacesDispatcher.Invoke(shapes, facesPerCell);
vtkm::Id totalFaces = 0;
totalFaces =
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(facesPerCell, vtkm::Id(0));
// Calculate the offsets so each cell knows where to insert the morton code
// for each face
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
cellOffsets.PrepareForOutput(numCells, DeviceAdapter());
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ScanExclusive(facesPerCell, cellOffsets);
// cell offsets also serve as the offsets into the array that tracks connectivity.
// For example, we have a hex with 6 faces and each face connects to another cell.
// The connecting cells (from each face) are stored beginning at index cellOffsets[cellId]
this->FaceOffsets = cellOffsets;
// We are creating a spatial hash based on morton codes calculated
// from the centriod (point average) of each face. Each centroid is
// calculated in way (consistent order of floating point calcs) that
// ensures that each face maps to the same morton code. It is possbilbe
// that two non-connecting faces map to the same morton code, but if
// if a face has a matching face from another cell, it will be mapped
// to the same morton code. We check for this.
// set up everything we need to gen morton codes
vtkm::Vec<vtkm::Float32, 3> inverseExtent;
inverseExtent[0] = 1.f / (BoundingBox[1] - BoundingBox[0]);
inverseExtent[1] = 1.f / (BoundingBox[3] - BoundingBox[2]);
inverseExtent[2] = 1.f / (BoundingBox[5] - BoundingBox[4]);
vtkm::Vec<vtkm::Float32, 3> minPoint;
minPoint[0] = BoundingBox[0];
minPoint[1] = BoundingBox[2];
minPoint[2] = BoundingBox[4];
// Morton Codes are created for the centroid of each face.
// cellFaceId:
// 0) Cell that the face belongs to
// 1) Face of the the cell (e.g., hex will have 6 faces and this is 1 of the 6)
// 2) cell id of the cell that connects to the corresponding face (1)
vtkm::cont::ArrayHandle<vtkm::UInt32> faceMortonCodes;
cellFaceId.PrepareForOutput(totalFaces, DeviceAdapter());
faceMortonCodes.PrepareForOutput(totalFaces, DeviceAdapter());
vtkm::worklet::DispatcherMapTopology<MortonCodeFace> mortonCodeFaceDispatcher(
MortonCodeFace(inverseExtent, minPoint));
mortonCodeFaceDispatcher.SetDevice(DeviceAdapter());
mortonCodeFaceDispatcher.Invoke(cellSet, coordinates, cellOffsets, faceMortonCodes, cellFaceId);
// Sort the "faces" (i.e., morton codes)
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::SortByKey(faceMortonCodes, cellFaceId);
// Allocate space for the final face-to-face conectivity
faceConnectivity.PrepareForOutput(totalFaces, DeviceAdapter());
// Initialize All connecting faces to -1 (connects to nothing)
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Id>> memSetDispatcher(MemSet<vtkm::Id>(-1));
memSetDispatcher.SetDevice(DeviceAdapter());
memSetDispatcher.Invoke(faceConnectivity);
vtkm::worklet::DispatcherMapField<MortonNeighbor> mortonNeighborDispatcher{ (
MortonNeighbor{}) };
mortonNeighborDispatcher.SetDevice(DeviceAdapter());
mortonNeighborDispatcher.Invoke(
faceMortonCodes, cellFaceId, conn, shapes, shapeOffsets, faceConnectivity);
vtkm::Float64 time = timer.GetElapsedTime();
Logger::GetInstance()->AddLogData("gen_face_conn", time);
}
template <typename ShapeHandleType, typename OffsetsHandleType, typename ConnHandleType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Vec<Id, 4>> ExtractExternalFaces(
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>>
cellFaceId, // Map of cell, face, and connecting cell
vtkm::cont::ArrayHandle<vtkm::Id>
faceConnectivity, // -1 if the face does not connect to any other face
const ShapeHandleType& shapes,
const ConnHandleType& conn,
const OffsetsHandleType& shapeOffsets)
{
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 3>> externalFacePairs;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::CopyIf(
cellFaceId, faceConnectivity, externalFacePairs, IsExternal());
// We need to count the number of triangle per external face
// If it is a single cell type and it is a tet or hex, this is a special case
// i.e., we do not need to calculate it. TODO
// Otherwise, we need to check to see if the face is a quad or triangle
vtkm::Id numExternalFaces = externalFacePairs.GetNumberOfValues();
vtkm::cont::ArrayHandle<vtkm::Id> trianglesPerExternalFace;
trianglesPerExternalFace.PrepareForOutput(numExternalFaces, DeviceAdapter());
vtkm::worklet::DispatcherMapField<CountExternalTriangles> countExternalDispatcher{ (
CountExternalTriangles{}) };
countExternalDispatcher.SetDevice(DeviceAdapter());
countExternalDispatcher.Invoke(externalFacePairs, shapes, trianglesPerExternalFace);
vtkm::cont::ArrayHandle<vtkm::Id> externalTriangleOffsets;
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::ScanExclusive(trianglesPerExternalFace,
externalTriangleOffsets);
vtkm::Id totalExternalTriangles;
totalExternalTriangles = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
trianglesPerExternalFace, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> externalTriangles;
externalTriangles.PrepareForOutput(totalExternalTriangles, DeviceAdapter());
//count the number triangles in the external faces
vtkm::worklet::DispatcherMapField<ExternalTriangles> externalTriDispatcher{ (
ExternalTriangles{}) };
externalTriDispatcher.SetDevice(DeviceAdapter());
externalTriDispatcher.Invoke(
externalFacePairs, shapes, shapeOffsets, conn, externalTriangles, externalTriangleOffsets);
vtkm::Float64 time = timer.GetElapsedTime();
Logger::GetInstance()->AddLogData("external_faces", time);
return externalTriangles;
}
vtkm::Bounds coordsBounds);
vtkm::cont::ArrayHandle<vtkm::Id> FaceConnectivity;
vtkm::cont::ArrayHandle<vtkm::Id> FaceOffsets;

@ -1,772 +0,0 @@
//============================================================================
// 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_MeshConnectivityStructures_h
#define vtk_m_rendering_raytracing_MeshConnectivityStructures_h
#include <sstream>
#include <vtkm/CellShape.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
{
namespace raytracing
{
// MeshConnectivityStrucutures:
// Policy classes for different types of meshes. Each implemented class
// Must implement GetConnetingCell( indexOfCurrentCell, face) that returns
// the index of the cell that connects to the "face" of the current cell.
// Each policy should have a copy constructor to facilitate clean passing
// to worklets (i.e., initialize execution portals if needed).
//
// Primary template for MeshConnExec Object
//
template <typename MeshType, typename Device>
class MeshConnExec
{
};
class UnstructuredMeshConn
{
public:
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
using Id4Handle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
using UCharHandle = vtkm::cont::ArrayHandle<vtkm::UInt8>;
// Control Environment Handles
// FaceConn
IdHandle FaceConnectivity;
IdHandle FaceOffsets;
//Cell Set
IdHandle CellConn;
IdHandle CellOffsets;
UCharHandle Shapes;
// Mesh Boundary
Id4Handle ExternalTriangles;
LinearBVH Bvh;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CellSetExplicit<> Cellset;
vtkm::cont::CoordinateSystem Coords;
protected:
bool IsConstructed;
private:
VTKM_CONT
UnstructuredMeshConn(){};
public:
VTKM_CONT
UnstructuredMeshConn(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords)
: IsConstructed(false)
{
Coords = coords;
if (!cellset.IsSameType(vtkm::cont::CellSetExplicit<>()))
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Error: not an explicit cell set!");
}
Cellset = cellset.Cast<vtkm::cont::CellSetExplicit<>>();
//
// 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());
}
//----------------------------------------------------------------------------
template <typename T>
VTKM_CONT UnstructuredMeshConn(const T& other)
: FaceConnectivity(other.FaceConnectivity)
, FaceOffsets(other.FaceOffsets)
, CellConn(other.CellConn)
, CellOffsets(other.CellOffsets)
, Shapes(other.Shapes)
, ExternalTriangles(other.ExternalTriangles)
, Bvh(other.Bvh)
, CoordinateBounds(other.CoordinateBounds)
, Cellset(other.Cellset)
, Coords(other.Coords)
, IsConstructed(other.IsConstructed)
{
}
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT void Construct(Device)
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("mesh_conn_construction");
vtkm::cont::Timer<Device> timer;
if (!IsConstructed)
{
CoordinateBounds = Coords.GetBounds();
MeshConnectivityBuilder<Device> connBuilder;
//
// Build the face-to-face connectivity
//
connBuilder.BuildConnectivity(Cellset, Coords.GetData(), CoordinateBounds);
//
// Initialize all of the array handles
//
FaceConnectivity = connBuilder.GetFaceConnectivity();
FaceOffsets = connBuilder.GetFaceOffsets();
ExternalTriangles = connBuilder.GetExternalTriangles();
//
// Build BVH on external triangles
//
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
Bvh.ConstructOnDevice(Device());
IsConstructed = true;
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
//----------------------------------------------------------------------------
template <typename T, typename Device>
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
{
if (!IsConstructed)
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Error: FindEntry called before Construct");
}
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
bool getCellIndex = true;
intersector.runHitOnly(rays, Bvh, Coords.GetData(), getCellIndex);
}
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::Id GetNumberOfCells() { return this->Shapes.GetPortalConstControl().GetNumberOfValues(); }
//----------------------------------------------------------------------------
// Control Environment Methods
//----------------------------------------------------------------------------
VTKM_CONT
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates GetCoordinates() { return Coords.GetData(); }
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
{
CoordinateBounds = Coords.GetBounds();
return CoordinateBounds;
}
//----------------------------------------------------------------------------
VTKM_CONT
bool GetIsConstructed() { return IsConstructed; }
}; //Unstructure mesh conn
template <typename Device>
class MeshConnExec<UnstructuredMeshConn, Device>
{
protected:
using IdHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using Id4Handle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
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;
private:
VTKM_CONT
MeshConnExec(){};
public:
VTKM_CONT
MeshConnExec(UnstructuredMeshConn& conn)
: FaceConnPortal(conn.FaceConnectivity.PrepareForInput(Device()))
, FaceOffsetsPortal(conn.FaceOffsets.PrepareForInput(Device()))
, CellConnPortal(conn.CellConn.PrepareForInput(Device()))
, CellOffsetsPortal(conn.CellOffsets.PrepareForInput(Device()))
, ShapesPortal(conn.Shapes.PrepareForInput(Device()))
{
if (!conn.GetIsConstructed())
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Error: GetExecObj called before Construct");
}
}
//----------------------------------------------------------------------------
template <typename T>
VTKM_CONT MeshConnExec(const T& other)
: FaceConnPortal(other.FaceConnPortal)
, FaceOffsetsPortal(other.FaceConnPortal)
, CellConnPortal(other.CellConnPortal)
, CellOffsetsPortal(other.CellOffsetsPortal)
, ShapesPortal(other.ShapesPortal)
{
}
//----------------------------------------------------------------------------
// Execution Environment Methods
//----------------------------------------------------------------------------
VTKM_EXEC
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
{
BOUNDS_CHECK(FaceOffsetsPortal, cellId);
vtkm::Id cellStartIndex = FaceOffsetsPortal.Get(cellId);
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
return FaceConnPortal.Get(cellStartIndex + face);
}
//----------------------------------------------------------------------------
VTKM_EXEC
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const
{
CellTables tables;
const vtkm::Int32 shapeId = static_cast<vtkm::Int32>(ShapesPortal.Get(cellId));
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
inline vtkm::UInt8 GetCellShape(const vtkm::Id& cellId) const
{
BOUNDS_CHECK(ShapesPortal, cellId)
return ShapesPortal.Get(cellId);
}
}; //Unstructure mesh conn exec
// Specialized version for unstructured meshes consisting of
// a single type of cell.
class UnstructuredMeshConnSingleType
{
public:
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
using Id4Handle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
using CountingHandle = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using ShapesHandle = vtkm::cont::ArrayHandleConstant<vtkm::UInt8>;
using NumIndicesHandle = vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>;
// Control Environment Handles
IdHandle FaceConnectivity;
CountingHandle CellOffsets;
IdHandle CellConnectivity;
// Mesh Boundary
LinearBVH Bvh;
Id4Handle ExternalTriangles;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CoordinateSystem Coords;
vtkm::cont::CellSetSingleType<> Cellset;
vtkm::Int32 ShapeId;
vtkm::Int32 NumIndices;
vtkm::Int32 NumFaces;
protected:
bool IsConstructed;
private:
VTKM_CONT
UnstructuredMeshConnSingleType() {}
public:
VTKM_CONT
UnstructuredMeshConnSingleType(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords)
: IsConstructed(false)
{
Coords = coords;
if (!cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Single type Error: not an single type cell set!");
}
Cellset = cellset.Cast<vtkm::cont::CellSetSingleType<>>();
CellConnectivity =
Cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
Cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
CellTables tables;
ShapeId = shapes.GetPortalConstControl().Get(0);
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);
//
// Initialize all of the array portals
//
}
template <typename T>
VTKM_CONT UnstructuredMeshConnSingleType(const T& other)
: FaceConnectivity(other.FaceConnectivity)
, CellOffsets(other.CellOffsets)
, CellConnectivity(other.CellConnectivity)
, Bvh(other.Bvh)
, ExternalTriangles(other.ExternalTriangles)
, CoordinateBounds(other.CoordinateBounds)
, Coords(other.coords)
, Cellset(other.Cellset)
, ShapeId(other.ShapeId)
, NumIndices(other.NumIndices)
, NumFaces(other.NumFaces)
, IsConstructed(other.IsConstructed)
{
}
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT void Construct(Device)
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("mesh_conn_construction");
vtkm::cont::Timer<Device> timer;
if (!IsConstructed)
{
CoordinateBounds = Coords.GetBounds();
MeshConnectivityBuilder<Device> connBuilder;
//
// Build the face-to-face connectivity
//
connBuilder.BuildConnectivity(Cellset, Coords.GetData(), CoordinateBounds);
//
// Initialize all of the array handles
//
FaceConnectivity = connBuilder.GetFaceConnectivity();
ExternalTriangles = connBuilder.GetExternalTriangles();
//
// Build BVH on external triangles
//
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
Bvh.ConstructOnDevice(Device());
IsConstructed = true;
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
//----------------------------------------------------------------------------
template <typename T, typename Device>
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
{
if (!IsConstructed)
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Single Error: FindEntry called before Construct");
}
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
bool getCellIndex = true;
intersector.runHitOnly(rays, Bvh, Coords.GetData(), getCellIndex);
}
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::Id GetNumberOfCells() { return this->Cellset.GetNumberOfCells(); }
//----------------------------------------------------------------------------
VTKM_CONT
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates GetCoordinates() { return Coords.GetData(); }
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
{
CoordinateBounds = Coords.GetBounds();
return CoordinateBounds;
}
//----------------------------------------------------------------------------
VTKM_CONT
bool GetIsConstructed() { return IsConstructed; }
}; //UnstructuredMeshConn Single Type
template <typename Device>
class MeshConnExec<UnstructuredMeshConnSingleType, Device>
{
protected:
using IdHandle = typename vtkm::cont::ArrayHandle<vtkm::Id>;
using Id4Handle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
using CountingHandle = typename vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using ShapesHandle = typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>;
using IdConstPortal = typename IdHandle::ExecutionTypes<Device>::PortalConst;
using CountingPortal = typename CountingHandle::ExecutionTypes<Device>::PortalConst;
using NumIndicesHandle = typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>;
// Constant Portals for the execution Environment
IdConstPortal FaceConnPortal;
IdConstPortal CellConnectivityPortal;
CountingPortal CellOffsetsPortal;
vtkm::Int32 ShapeId;
vtkm::Int32 NumIndices;
vtkm::Int32 NumFaces;
private:
VTKM_CONT
MeshConnExec() {}
public:
VTKM_CONT
MeshConnExec(UnstructuredMeshConnSingleType& conn)
: FaceConnPortal(conn.FaceConnectivity.PrepareForInput(Device()))
, CellConnectivityPortal(conn.CellConnectivity.PrepareForInput(Device()))
, CellOffsetsPortal(conn.CellOffsets.PrepareForInput(Device()))
, ShapeId(conn.ShapeId)
, NumIndices(conn.NumIndices)
, NumFaces(conn.NumFaces)
{
if (!conn.GetIsConstructed())
{
throw vtkm::cont::ErrorBadValue(
"Unstructured Mesh Connecitity Single Error: GetExecObj called before Construct");
}
}
template <typename T>
VTKM_CONT MeshConnExec(const T& other)
: FaceConnPortal(other.FaceConnPortal)
, CellOffsetsPortal(other.CellOffsetsPortal)
, CellConnectivityPortal(other.CellConnectivityPortal)
, ShapeId(other.ShapeId)
, NumIndices(other.NumIndices)
, NumFaces(other.NumFaces)
{
}
//----------------------------------------------------------------------------
// Execution Environment Methods
//----------------------------------------------------------------------------
VTKM_EXEC
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
{
BOUNDS_CHECK(CellOffsetsPortal, cellId);
vtkm::Id cellStartIndex = cellId * NumFaces;
BOUNDS_CHECK(FaceConnPortal, cellStartIndex + face);
return FaceConnPortal.Get(cellStartIndex + face);
}
VTKM_EXEC
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellId) const
{
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
inline vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const
{
return vtkm::UInt8(ShapeId);
}
}; //MeshConn Single type specialization
class StructuredMeshConn
{
public:
using Id4Handle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
vtkm::Id3 CellDims;
vtkm::Id3 PointDims;
vtkm::Bounds CoordinateBounds;
vtkm::cont::CoordinateSystem Coords;
vtkm::cont::CellSetStructured<3> Cellset;
// Mesh Boundary
LinearBVH Bvh;
Id4Handle ExternalTriangles;
protected:
bool IsConstructed;
private:
VTKM_CONT
StructuredMeshConn() {}
public:
VTKM_CONT
StructuredMeshConn(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords)
: IsConstructed(false)
{
Coords = coords;
if (!cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
throw vtkm::cont::ErrorBadValue(
"Structured Mesh Connecitity Error: not a Structured<3> cell set!");
}
Cellset = cellset.Cast<vtkm::cont::CellSetStructured<3>>();
PointDims = Cellset.GetPointDimensions();
CellDims = Cellset.GetCellDimensions();
}
template <typename T>
VTKM_CONT StructuredMeshConn(const T& other)
: CellDims(other.CellDims)
, PointDims(other.PointDims)
, CoordinateBounds(other.CoordinateBounds)
, Coords(other.coords)
, Cellset(other.Cellset)
, Bvh(other.Bvh)
, ExternalTriangles(other.ExternalTriangles)
, IsConstructed(other.IsConstructed)
{
}
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT void Construct(Device)
{
Logger* logger = Logger::GetInstance();
logger->OpenLogEntry("mesh_conn_construction");
vtkm::cont::Timer<Device> timer;
if (!IsConstructed)
{
CoordinateBounds = Coords.GetBounds();
MeshConnectivityBuilder<Device> connBuilder;
ExternalTriangles = connBuilder.ExternalTrianglesStructured(Cellset);
//
// Build BVH on external triangles
//
Bvh.SetData(Coords.GetData(), ExternalTriangles, Coords.GetBounds());
Bvh.ConstructOnDevice(Device());
IsConstructed = true;
}
vtkm::Float64 time = timer.GetElapsedTime();
logger->CloseLogEntry(time);
}
//----------------------------------------------------------------------------
template <typename T, typename Device>
VTKM_CONT void FindEntry(Ray<T>& rays, Device)
{
if (!IsConstructed)
{
throw vtkm::cont::ErrorBadValue(
"Structured Mesh Connecitity Single Error: FindEntry called before Construct");
}
TriangleIntersector<Device, TriLeafIntersector<WaterTight<T>>> intersector;
bool getCellIndex = true;
intersector.runHitOnly(rays, Bvh, Coords.GetData(), getCellIndex);
}
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::Id GetNumberOfCells() { return this->CellDims[0] * this->CellDims[1] * this->CellDims[2]; }
//----------------------------------------------------------------------------
// Control Environment Methods
//----------------------------------------------------------------------------
VTKM_CONT
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
//----------------------------------------------------------------------------
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates GetCoordinates() { return Coords.GetData(); }
//----------------------------------------------------------------------------
template <typename Device>
VTKM_CONT vtkm::Bounds GetCoordinateBounds(Device)
{
CoordinateBounds = Coords.GetBounds();
return CoordinateBounds;
}
//----------------------------------------------------------------------------
VTKM_CONT
bool GetIsConstructed() { return IsConstructed; }
}; //structure mesh conn
template <typename Device>
class MeshConnExec<StructuredMeshConn, Device>
{
protected:
using Id4Handle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>;
vtkm::Id3 CellDims;
vtkm::Id3 PointDims;
vtkm::Bounds CoordinateBounds;
private:
VTKM_CONT
MeshConnExec() {}
public:
VTKM_CONT
MeshConnExec(const StructuredMeshConn& other)
: CellDims(other.CellDims)
, PointDims(other.PointDims)
, CoordinateBounds(other.CoordinateBounds)
{
}
template <typename T>
VTKM_CONT MeshConnExec(const T& other)
: CellDims(other.CellDims)
, PointDims(other.PointDims)
, CoordinateBounds(other.CoordinateBounds)
{
}
//----------------------------------------------------------------------------
// Execution Environment Methods
//----------------------------------------------------------------------------
VTKM_EXEC_CONT
inline vtkm::Id GetConnectingCell(const vtkm::Id& cellId, const vtkm::Id& face) const
{
//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
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8], const vtkm::Id& cellIndex) const
{
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_CONT
inline vtkm::Int32 GetCellIndices(vtkm::Id cellIndices[8],
const vtkm::Vec<vtkm::Id, 3>& cellId) const
{
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
inline vtkm::UInt8 GetCellShape(const vtkm::Id& vtkmNotUsed(cellId)) const
{
return vtkm::UInt8(CELL_SHAPE_HEXAHEDRON);
}
}; //Unstructure mesh conn
}
}
} //namespace vtkm::rendering::raytracing
#endif

@ -25,6 +25,7 @@
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/rendering/raytracing/CellTables.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>

@ -129,6 +129,20 @@ public:
DebugHeight = -1;
}
struct EnableIntersectionDataFunctor
{
template <typename Device>
VTKM_CONT bool operator()(Device, Ray<Precision>* self)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->EnableIntersectionData(Device());
return true;
}
};
void EnableIntersectionData() { vtkm::cont::TryExecute(EnableIntersectionDataFunctor(), this); }
template <typename Device>
void EnableIntersectionData(Device)
{
@ -185,11 +199,18 @@ public:
this->Resize(size, Device());
}
VTKM_CONT void Resize(const vtkm::Int32 size)
struct ResizeFunctor
{
this->Resize(size, vtkm::cont::DeviceAdapterTagSerial());
}
template <typename Device>
VTKM_CONT bool operator()(Device, Ray<Precision>* self, const vtkm::Int32 size)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->Resize(size, Device());
return true;
}
};
VTKM_CONT void Resize(const vtkm::Int32 size) { vtkm::cont::TryExecute(ResizeFunctor(), size); }
template <typename Device>
VTKM_CONT void Resize(const vtkm::Int32 size, Device)

@ -21,7 +21,6 @@
#define vtk_m_rendering_raytracing_Ray_Operations_h
#include <vtkm/Matrix.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/ChannelBufferOperations.h>
@ -117,10 +116,8 @@ public:
template <typename Device, typename T>
static void ResetStatus(Ray<T>& rays, vtkm::UInt8 status, Device)
{
vtkm::worklet::DispatcherMapField<MemSet<vtkm::UInt8>> dispatcher(
(MemSet<vtkm::UInt8>(status)));
dispatcher.SetDevice(Device());
dispatcher.Invoke(rays.Status);
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> statusHandle(status, rays.NumRays);
vtkm::cont::Algorithm::Copy(Device(), statusHandle, rays.Status);
}
//
@ -137,6 +134,14 @@ public:
dispatcher.Invoke(rays.HitIdx, rays.Status);
}
template <typename T>
static void UpdateRayStatus(Ray<T>& rays)
{
vtkm::worklet::DispatcherMapField<detail::RayStatusFilter> dispatcher{ (
detail::RayStatusFilter{}) };
dispatcher.Invoke(rays.HitIdx, rays.Status);
}
static void MapCanvasToRays(Ray<vtkm::Float32>& rays,
const vtkm::rendering::Camera& camera,
const vtkm::rendering::CanvasRayTracer& canvas);

@ -25,13 +25,10 @@
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace vtkm
@ -44,237 +41,12 @@ namespace raytracing
namespace detail
{
class IntersectionPoint : public vtkm::worklet::WorkletMapField
{
public:
VTKM_CONT
IntersectionPoint() {}
using ControlSignature =
void(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, FieldOut<>, FieldOut<>, FieldOut<>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7);
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) const
{
if (hitIndex < 0)
return;
intersectionX = rayOrigin[0] + rayDir[0] * distance;
intersectionY = rayOrigin[1] + rayDir[1] * distance;
intersectionZ = rayOrigin[2] + rayDir[2] * distance;
}
}; //class IntersectionPoint
template <typename Device>
class IntersectionData
{
public:
// Worklet to calutate the normals of a triagle if
// none are stored in the data set
class CalculateNormals : public vtkm::worklet::WorkletMapField
{
private:
using Vec4IntArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>;
using IndicesArrayPortal = typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst;
IndicesArrayPortal IndicesPortal;
public:
VTKM_CONT
CalculateNormals(const Vec4IntArrayHandle& indices)
: IndicesPortal(indices.PrepareForInput(Device()))
{
}
using ControlSignature = void(FieldIn<>,
FieldIn<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
WholeArrayIn<Vec3RenderingTypes>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
template <typename Precision, typename PointPortalType>
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
{
if (hitIndex < 0)
return;
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
vtkm::Vec<Precision, 3> a = points.Get(indices[1]);
vtkm::Vec<Precision, 3> b = points.Get(indices[2]);
vtkm::Vec<Precision, 3> c = points.Get(indices[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 LerpScalar : public vtkm::worklet::WorkletMapField
{
private:
using Vec4IntArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>;
using IndicesArrayPortal = typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst;
IndicesArrayPortal IndicesPortal;
Precision MinScalar;
Precision invDeltaScalar;
public:
VTKM_CONT
LerpScalar(const Vec4IntArrayHandle& indices,
const vtkm::Float32& minScalar,
const vtkm::Float32& maxScalar)
: IndicesPortal(indices.PrepareForInput(Device()))
, 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;
}
using ControlSignature =
void(FieldIn<>, FieldIn<>, FieldIn<>, FieldOut<>, WholeArrayIn<ScalarRenderingTypes>);
using ExecutionSignature = void(_1, _2, _3, _4, _5);
template <typename ScalarPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
const Precision& u,
const Precision& v,
Precision& lerpedScalar,
const ScalarPortalType& scalars) const
{
if (hitIndex < 0)
return;
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
Precision n = 1.f - u - v;
Precision aScalar = Precision(scalars.Get(indices[1]));
Precision bScalar = Precision(scalars.Get(indices[2]));
Precision cScalar = Precision(scalars.Get(indices[3]));
lerpedScalar = aScalar * n + bScalar * u + cScalar * v;
//normalize
lerpedScalar = (lerpedScalar - MinScalar) * invDeltaScalar;
}
}; //class LerpScalar
template <typename Precision>
class NodalScalar : public vtkm::worklet::WorkletMapField
{
private:
using Vec4IntArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>;
using IndicesArrayPortal = typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst;
IndicesArrayPortal IndicesPortal;
Precision MinScalar;
Precision invDeltaScalar;
public:
VTKM_CONT
NodalScalar(const Vec4IntArrayHandle& indices,
const vtkm::Float32& minScalar,
const vtkm::Float32& maxScalar)
: IndicesPortal(indices.PrepareForInput(Device()))
, 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;
}
using ControlSignature = void(FieldIn<>, FieldOut<>, WholeArrayIn<ScalarRenderingTypes>);
using ExecutionSignature = void(_1, _2, _3);
template <typename ScalarPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
Precision& scalar,
const ScalarPortalType& scalars) const
{
if (hitIndex < 0)
return;
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
//Todo: one normalization
scalar = Precision(scalars.Get(indices[0]));
//normalize
scalar = (scalar - MinScalar) * invDeltaScalar;
}
}; //class LerpScalar
template <typename Precision>
VTKM_CONT void run(Ray<Precision>& rays,
LinearBVH& bvh,
vtkm::cont::ArrayHandleVirtualCoordinates& coordsHandle,
const vtkm::cont::Field& scalarField,
const vtkm::Range& scalarRange)
{
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 cell set or points");
bool isAssocPoints = scalarField.GetAssociation() == vtkm::cont::Field::Association::POINTS;
vtkm::worklet::DispatcherMapField<CalculateNormals> calcNormalsDispatcher(
CalculateNormals(bvh.LeafNodes));
calcNormalsDispatcher.SetDevice(Device());
calcNormalsDispatcher.Invoke(
rays.HitIdx, rays.Dir, rays.NormalX, rays.NormalY, rays.NormalZ, coordsHandle);
if (isAssocPoints)
{
vtkm::worklet::DispatcherMapField<LerpScalar<Precision>> lerpScalarDispatcher(
LerpScalar<Precision>(
bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)));
lerpScalarDispatcher.SetDevice(Device());
lerpScalarDispatcher.Invoke(rays.HitIdx, rays.U, rays.V, rays.Scalar, scalarField);
}
else
{
vtkm::worklet::DispatcherMapField<NodalScalar<Precision>> nodalScalarDispatcher(
NodalScalar<Precision>(
bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)));
nodalScalarDispatcher.SetDevice(Device());
nodalScalarDispatcher.Invoke(rays.HitIdx, rays.Scalar, scalarField);
}
} // Run
}; // Class IntersectionData
template <typename Device>
class SurfaceColor
{
public:
class MapScalarToColor : public vtkm::worklet::WorkletMapField
{
private:
using ColorArrayHandle = typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>;
using ColorArrayPortal = typename ColorArrayHandle::ExecutionTypes<Device>::PortalConst;
ColorArrayPortal ColorMap;
vtkm::Int32 ColorMapSize;
vtkm::Vec<vtkm::Float32, 3> LightPosition;
vtkm::Vec<vtkm::Float32, 3> LightAbmient;
vtkm::Vec<vtkm::Float32, 3> LightDiffuse;
@ -285,14 +57,10 @@ public:
public:
VTKM_CONT
MapScalarToColor(const ColorArrayHandle& colorMap,
const vtkm::Int32& colorMapSize,
const vtkm::Vec<vtkm::Float32, 3>& lightPosition,
MapScalarToColor(const vtkm::Vec<vtkm::Float32, 3>& lightPosition,
const vtkm::Vec<vtkm::Float32, 3>& cameraPosition,
const vtkm::Vec<vtkm::Float32, 3>& lookAt)
: ColorMap(colorMap.PrepareForInput(Device()))
, ColorMapSize(colorMapSize)
, LightPosition(lightPosition)
: LightPosition(lightPosition)
, CameraPosition(cameraPosition)
, LookAt(lookAt)
{
@ -308,14 +76,18 @@ public:
LightSpecular[2] = .7f;
SpecularExponent = 20.f;
}
using ControlSignature = void(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, WholeArrayInOut<>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, WorkIndex);
template <typename ColorPortalType, typename Precision>
using ControlSignature =
void(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, WholeArrayInOut<>, WholeArrayIn<>);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, WorkIndex);
template <typename ColorPortalType, typename Precision, typename ColorMapPortalType>
VTKM_EXEC void operator()(const vtkm::Id& hitIdx,
const Precision& scalar,
const vtkm::Vec<Precision, 3>& normal,
const vtkm::Vec<Precision, 3>& intersection,
ColorPortalType& colors,
ColorMapPortalType colorMap,
const vtkm::Id& idx) const
{
vtkm::Vec<Precision, 4> color;
@ -336,23 +108,23 @@ public:
vtkm::Normalize(lightDir);
vtkm::Normalize(viewDir);
//Diffuse lighting
Precision cosTheta = vtkm::Dot(normal, lightDir);
Precision cosTheta = vtkm::dot(normal, lightDir);
//clamp tp [0,1]
const Precision zero = 0.f;
const Precision one = 1.f;
cosTheta = vtkm::Min(vtkm::Max(cosTheta, zero), one);
//Specular lighting
vtkm::Vec<Precision, 3> reflect = 2.f * vtkm::Dot(lightDir, normal) * normal - lightDir;
vtkm::Vec<Precision, 3> reflect = 2.f * vtkm::dot(lightDir, normal) * normal - lightDir;
vtkm::Normalize(reflect);
Precision cosPhi = vtkm::Dot(reflect, viewDir);
Precision specularConstant =
Precision(pow(vtkm::Max(cosPhi, zero), (Precision)SpecularExponent));
vtkm::Int32 colorIdx = vtkm::Int32(scalar * Precision(ColorMapSize - 1));
Precision cosPhi = vtkm::dot(reflect, viewDir);
Precision specularConstant = Precision(pow(vtkm::Max(cosPhi, zero), SpecularExponent));
vtkm::Int32 colorMapSize = static_cast<vtkm::Int32>(colorMap.GetNumberOfValues());
vtkm::Int32 colorIdx = vtkm::Int32(scalar * Precision(colorMapSize - 1));
//Just in case clamp the value to the valid range
colorIdx = (colorIdx < 0) ? 0 : colorIdx;
colorIdx = (colorIdx > ColorMapSize - 1) ? ColorMapSize - 1 : colorIdx;
color = ColorMap.Get(colorIdx);
// clamp color index
colorIdx = vtkm::Max(0, colorIdx);
colorIdx = vtkm::Min(colorMapSize - 1, colorIdx);
color = colorMap.Get(colorIdx);
color[0] *= vtkm::Min(
LightAbmient[0] + LightDiffuse[0] * cosTheta + LightSpecular[0] * specularConstant, one);
@ -377,144 +149,116 @@ public:
// TODO: support light positions
vtkm::Vec<vtkm::Float32, 3> scale(2, 2, 2);
vtkm::Vec<vtkm::Float32, 3> lightPosition = camera.GetPosition() + scale * camera.GetUp();
const vtkm::Int32 colorMapSize = vtkm::Int32(colorMap.GetNumberOfValues());
vtkm::worklet::DispatcherMapField<MapScalarToColor> dispatcher(MapScalarToColor(
colorMap, colorMapSize, lightPosition, camera.GetPosition(), camera.GetLookAt()));
dispatcher.SetDevice(Device());
dispatcher.Invoke(
rays.HitIdx, rays.Scalar, rays.Normal, rays.Intersection, rays.Buffers.at(0).Buffer);
vtkm::worklet::DispatcherMapField<MapScalarToColor>(
MapScalarToColor(lightPosition, camera.GetPosition(), camera.GetLookAt()))
.Invoke(rays.HitIdx,
rays.Scalar,
rays.Normal,
rays.Intersection,
rays.Buffers.at(0).Buffer,
colorMap);
}
}; // class SurfaceColor
} // namespace detail
RayTracer::RayTracer()
: NumberOfShapes(0)
{
}
RayTracer::~RayTracer()
{
Clear();
}
Camera& RayTracer::GetCamera()
{
return camera;
}
void RayTracer::SetData(const vtkm::cont::ArrayHandleVirtualCoordinates& coordsHandle,
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::cont::Field& scalarField,
const vtkm::Id& numberOfTriangles,
const vtkm::Range& scalarRange,
const vtkm::Bounds& dataBounds)
void RayTracer::AddShapeIntersector(ShapeIntersector* intersector)
{
CoordsHandle = coordsHandle;
Indices = indices;
ScalarField = scalarField;
NumberOfTriangles = numberOfTriangles;
ScalarRange = scalarRange;
DataBounds = dataBounds;
Bvh.SetData(coordsHandle, indices, DataBounds);
NumberOfShapes += intersector->GetNumberOfShapes();
Intersectors.push_back(intersector);
}
void RayTracer::SetField(const vtkm::cont::Field& scalarField, const vtkm::Range& scalarRange)
{
ScalarField = &scalarField;
ScalarRange = scalarRange;
}
void RayTracer::SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap)
{
ColorMap = colorMap;
}
template <typename Precision>
struct RayTracer::RenderFunctor
{
protected:
vtkm::rendering::raytracing::RayTracer* Self;
vtkm::rendering::raytracing::Ray<Precision>& Rays;
public:
VTKM_CONT
RenderFunctor(vtkm::rendering::raytracing::RayTracer* self,
vtkm::rendering::raytracing::Ray<Precision>& rays)
: Self(self)
, Rays(rays)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
this->Self->RenderOnDevice(this->Rays, Device());
return true;
}
};
void RayTracer::Render(Ray<vtkm::Float32>& rays)
{
RenderFunctor<vtkm::Float32> functor(this, rays);
vtkm::cont::TryExecute(functor);
}
void
RayTracer::Render(Ray<vtkm::Float64> &rays)
{
RenderFunctor<vtkm::Float64> functor(this, rays);
vtkm::cont::TryExecute(functor);
RenderOnDevice(rays);
}
template <typename Device, typename Precision>
void RayTracer::RenderOnDevice(Ray<Precision>& rays, Device)
void RayTracer::Render(Ray<vtkm::Float64>& rays)
{
rays.EnableIntersectionData(Device());
RenderOnDevice(rays);
}
vtkm::Id RayTracer::GetNumberOfShapes() const
{
return NumberOfShapes;
}
void RayTracer::Clear()
{
size_t numShapes = Intersectors.size();
for (size_t i = 0; i < numShapes; ++i)
{
delete Intersectors[i];
}
Intersectors.clear();
}
template <typename Precision>
void RayTracer::RenderOnDevice(Ray<Precision>& rays)
{
using Timer = vtkm::cont::Timer<vtkm::cont::DeviceAdapterTagSerial>;
Logger* logger = Logger::GetInstance();
vtkm::cont::Timer<Device> renderTimer;
Timer renderTimer;
vtkm::Float64 time = 0.;
logger->OpenLogEntry("ray_tracer");
logger->AddLogData("device", GetDeviceString(Device()));
logger->AddLogData("device", GetDeviceString());
Bvh.ConstructOnDevice(Device());
logger->AddLogData("triangles", NumberOfTriangles);
logger->AddLogData("shapes", NumberOfShapes);
logger->AddLogData("num_rays", rays.NumRays);
if (NumberOfTriangles > 0)
size_t numShapes = Intersectors.size();
if (NumberOfShapes > 0)
{
vtkm::cont::Timer<Device> timer;
// Find distance to intersection
TriangleIntersector<Device, TriLeafIntersector<Moller>> intersector;
intersector.run(rays, Bvh, CoordsHandle);
time = timer.GetElapsedTime();
logger->AddLogData("intersect", time);
timer.Reset();
Timer timer;
// Calculate normal and scalar value (TODO: find a better name)
detail::IntersectionData<Device> intData;
intData.run(rays, Bvh, CoordsHandle, ScalarField, ScalarRange);
for (size_t i = 0; i < numShapes; ++i)
{
Intersectors[i]->IntersectRays(rays);
time = timer.GetElapsedTime();
logger->AddLogData("intersect", time);
time = timer.GetElapsedTime();
logger->AddLogData("intersection_data", time);
timer.Reset();
timer.Reset();
Intersectors[i]->IntersectionData(rays, ScalarField, ScalarRange);
time = timer.GetElapsedTime();
logger->AddLogData("intersection_data", time);
timer.Reset();
// Find the intersection point from hit distance
vtkm::worklet::DispatcherMapField<detail::IntersectionPoint> intersectionPointDispatcher{ (
detail::IntersectionPoint{}) };
intersectionPointDispatcher.SetDevice(Device());
intersectionPointDispatcher.Invoke(rays.HitIdx,
rays.Distance,
rays.Dir,
rays.Origin,
rays.IntersectionX,
rays.IntersectionY,
rays.IntersectionZ);
// Calculate the color at the intersection point
detail::SurfaceColor surfaceColor;
surfaceColor.run(rays, ColorMap, camera);
time = timer.GetElapsedTime();
logger->AddLogData("find_point", time);
timer.Reset();
// Calculate the color at the intersection point
detail::SurfaceColor<Device> surfaceColor;
surfaceColor.run(rays, ColorMap, camera);
time = timer.GetElapsedTime();
logger->AddLogData("shade", time);
timer.Reset();
time = timer.GetElapsedTime();
logger->AddLogData("shade", time);
timer.Reset();
}
}
time = renderTimer.GetElapsedTime();

@ -20,11 +20,12 @@
#ifndef vtk_m_rendering_raytracing_RayTracer_h
#define vtk_m_rendering_raytracing_RayTracer_h
#include <vector>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
namespace vtkm
{
namespace rendering
@ -35,43 +36,47 @@ namespace raytracing
class VTKM_RENDERING_EXPORT RayTracer
{
protected:
LinearBVH Bvh;
std::vector<ShapeIntersector*> Intersectors;
Camera camera;
vtkm::cont::ArrayHandleVirtualCoordinates CoordsHandle;
vtkm::cont::Field ScalarField;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Indices;
const vtkm::cont::Field* ScalarField;
vtkm::cont::ArrayHandle<vtkm::Float32> Scalars;
vtkm::Id NumberOfTriangles;
vtkm::Id NumberOfShapes;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorMap;
vtkm::Range ScalarRange;
vtkm::Bounds DataBounds;
template <typename Precision>
struct RenderFunctor;
template <typename Device, typename Precision>
void RenderOnDevice(Ray<Precision>& rays, Device);
template <typename Precision>
void RenderOnDevice(Ray<Precision>& rays);
public:
VTKM_CONT
RayTracer();
VTKM_CONT
~RayTracer();
VTKM_CONT
Camera& GetCamera();
VTKM_CONT
void SetData(const vtkm::cont::ArrayHandleVirtualCoordinates& coordsHandle,
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
vtkm::cont::Field& scalarField,
const vtkm::Id& numberOfTriangles,
const vtkm::Range& scalarRange,
const vtkm::Bounds& dataBounds);
void AddShapeIntersector(ShapeIntersector* intersector);
VTKM_CONT
void SetField(const vtkm::cont::Field& scalarField, const vtkm::Range& scalarRange);
VTKM_CONT
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap);
VTKM_CONT
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays);
VTKM_CONT
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays);
VTKM_CONT
vtkm::Id GetNumberOfShapes() const;
VTKM_CONT
void Clear();
}; //class RayTracer
}
}

@ -29,6 +29,7 @@
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/TryExecute.h>
namespace vtkm
{
@ -101,6 +102,30 @@ inline std::string GetDeviceString<vtkm::cont::DeviceAdapterTagCuda>(
return "cuda";
}
struct DeviceStringFunctor
{
std::string result;
DeviceStringFunctor()
: result("")
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
result = GetDeviceString(Device());
return true;
}
};
inline std::string GetDeviceString()
{
DeviceStringFunctor functor;
vtkm::cont::TryExecute(functor);
return functor.result;
}
using ColorBuffer4f = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>;
using ColorBuffer4b = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 4>>;

File diff suppressed because it is too large Load Diff

@ -28,6 +28,9 @@ set(unit_tests
UnitTestCanvas.cxx
UnitTestMapperConnectivity.cxx
UnitTestMultiMapper.cxx
UnitTestMapperCylinders.cxx
UnitTestMapperPoints.cxx
UnitTestMapperQuads.cxx
UnitTestMapperRayTracer.cxx
UnitTestMapperWireframer.cxx
UnitTestMapperVolume.cxx

@ -55,8 +55,11 @@ inline void SetCamera<vtkm::rendering::View3D>(vtkm::rendering::Camera& camera,
const vtkm::Bounds& coordBounds,
const vtkm::cont::Field&)
{
vtkm::Bounds b = coordBounds;
b.Z.Min = 0;
b.Z.Max = 4;
camera = vtkm::rendering::Camera();
camera.ResetToBounds(coordBounds);
camera.ResetToBounds(b);
camera.Azimuth(static_cast<vtkm::Float32>(45.0));
camera.Elevation(static_cast<vtkm::Float32>(45.0));
}
@ -124,6 +127,36 @@ void Render(const vtkm::cont::DataSet& ds,
Render<MapperType, CanvasType, ViewType>(view, outputFile);
}
// A render test that allows for testing different mapper params
template <typename MapperType, typename CanvasType, typename ViewType>
void Render(MapperType& mapper,
const vtkm::cont::DataSet& ds,
const std::string& fieldNm,
const vtkm::cont::ColorTable& colorTable,
const std::string& outputFile)
{
CanvasType canvas(512, 512);
vtkm::rendering::Scene scene;
scene.AddActor(vtkm::rendering::Actor(
ds.GetCellSet(), ds.GetCoordinateSystem(), ds.GetField(fieldNm), colorTable));
vtkm::rendering::Camera camera;
SetCamera<ViewType>(camera, ds.GetCoordinateSystem().GetBounds(), ds.GetField(fieldNm));
vtkm::rendering::Color background(1.0f, 1.0f, 1.0f, 1.0f);
vtkm::rendering::Color foreground(0.0f, 0.0f, 0.0f, 1.0f);
ViewType view(scene, mapper, canvas, camera, background, foreground);
// Print the title
vtkm::rendering::TextAnnotationScreen* titleAnnotation =
new vtkm::rendering::TextAnnotationScreen("Test Plot",
vtkm::rendering::Color(1, 1, 1, 1),
.075f,
vtkm::Vec<vtkm::Float32, 2>(-.11f, .92f),
0.f);
view.AddAnnotation(titleAnnotation);
Render<MapperType, CanvasType, ViewType>(view, outputFile);
}
template <typename MapperType, typename CanvasType, typename ViewType>
void Render(const vtkm::cont::DataSet& ds,
const std::vector<std::string>& fields,

@ -27,6 +27,7 @@
#include <vtkm/rendering/MapperConnectivity.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/testing/RenderTest.h>
namespace
@ -34,19 +35,26 @@ namespace
void RenderTests()
{
using M = vtkm::rendering::MapperConnectivity;
using C = vtkm::rendering::CanvasRayTracer;
using V3 = vtkm::rendering::View3D;
try
{
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::ColorTable colorTable("inferno");
using M = vtkm::rendering::MapperConnectivity;
using C = vtkm::rendering::CanvasRayTracer;
using V3 = vtkm::rendering::View3D;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::ColorTable colorTable("inferno");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRegularDataSet0(), "pointvar", colorTable, "reg3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRectilinearDataSet0(), "pointvar", colorTable, "rect3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSet5(), "pointvar", colorTable, "explicit3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRegularDataSet0(), "pointvar", colorTable, "reg3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DRectilinearDataSet0(), "pointvar", colorTable, "rect3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSetZoo(), "pointvar", colorTable, "explicit3D.pnm");
}
catch (const std::exception& e)
{
std::cout << vtkm::rendering::raytracing::Logger::GetInstance()->GetStream().str() << "\n";
std::cout << e.what() << "\n";
}
}
} //namespace

@ -49,7 +49,10 @@ void RenderTests()
maker.Make3DExplicitDataSet4(), "pointvar", colorTable, "rt_expl3D.pnm");
vtkm::rendering::testing::Render<M, C, V2>(
maker.Make2DUniformDataSet1(), "pointvar", colorTable, "rt_uni2D.pnm");
maker.Make2DUniformDataSet1(), "pointvar", colorTable, "uni2D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSet7(), "cellvar", colorTable, "spheres.pnm");
}
} //namespace