adding 2d ortho support to ray tracing and updating WireFramer to support 2d lines and 1D line plots

This commit is contained in:
Matt Larsen 2017-10-26 07:58:02 -07:00
parent 5ec29128de
commit 035814a4a7
13 changed files with 614 additions and 77 deletions

@ -83,7 +83,9 @@ inline vtkm::cont::DataSet MakeTestDataSet::Make1DUniformDataSet0()
vtkm::cont::DataSetFieldAdd dsf;
vtkm::Float32 var[nVerts] = { -1.0f, .5f, -.2f, 1.7f, -.1f, .8f };
vtkm::Float32 var2[nVerts] = { -1.1f, .7f, -.2f, 0.2f, -.1f, .4f };
dsf.AddPointField(dataSet, "pointvar", var, nVerts);
dsf.AddPointField(dataSet, "pointvar2", var2, nVerts);
return dataSet;
}

@ -345,9 +345,20 @@ public:
}
VTKM_CONT
void Pan(vtkm::Vec<vtkm::Float32, 2> direction) { this->Pan(direction[0], direction[1]); }
VTKM_CONT
void Pan(vtkm::Vec<vtkm::Float64, 2> direction) { this->Pan(direction[0], direction[1]); }
VTKM_CONT
vtkm::Vec<vtkm::Float32, 2> GetPan() const
{
vtkm::Vec<vtkm::Float32, 2> pan;
pan[0] = this->Camera3D.XPan;
pan[1] = this->Camera3D.YPan;
return pan;
}
/// \brief Zooms the camera in or out
///
/// Zooming the camera scales everything in the image up or down. Positive
@ -359,6 +370,9 @@ public:
VTKM_CONT
void Zoom(vtkm::Float64 zoom) { this->Zoom(static_cast<vtkm::Float32>(zoom)); }
VTKM_CONT
vtkm::Float32 GetZoom() const { return this->Camera3D.Zoom; }
/// \brief Moves the camera as if a point was dragged along a sphere.
///
/// \c TrackballRotate takes the normalized screen coordinates (in the range

@ -140,6 +140,49 @@ struct BlendBackgroundExecutor
}
}; // struct BlendBackgroundExecutor
struct DrawColorSwatch : public vtkm::worklet::WorkletMapField
{
typedef void ControlSignature(FieldIn<>, WholeArrayInOut<>);
typedef void ExecutionSignature(_1, _2);
VTKM_CONT
DrawColorSwatch(vtkm::Id2 dims,
vtkm::Id2 xBounds,
vtkm::Id2 yBounds,
const vtkm::Vec<vtkm::Float32, 4> color)
: Color(color)
{
ImageWidth = dims[0];
ImageHeight = dims[1];
SwatchBottomLeft[0] = xBounds[0];
SwatchBottomLeft[1] = yBounds[0];
SwatchWidth = xBounds[1] - xBounds[0];
SwatchHeight = yBounds[1] - yBounds[0];
}
template <typename FrameBuffer>
VTKM_EXEC void operator()(const vtkm::Id& index, FrameBuffer& frameBuffer) const
{
// local bar coord
vtkm::Id x = index % SwatchWidth;
vtkm::Id y = index / SwatchWidth, yLocal = y;
// offset to global image coord
x += SwatchBottomLeft[0];
y += SwatchBottomLeft[1];
vtkm::Id offset = y * ImageWidth + x;
frameBuffer.Set(offset, Color);
}
vtkm::Id ImageWidth;
vtkm::Id ImageHeight;
vtkm::Id2 SwatchBottomLeft;
vtkm::Id SwatchWidth;
vtkm::Id SwatchHeight;
const vtkm::Vec<vtkm::Float32, 4> Color;
}; // struct DrawColorSwatch
struct DrawColorBar : public vtkm::worklet::WorkletMapField
{
typedef void ControlSignature(FieldIn<>, WholeArrayInOut<>, WholeArrayIn<>);
@ -203,6 +246,42 @@ struct DrawColorBar : public vtkm::worklet::WorkletMapField
bool Horizontal;
}; // struct DrawColorBar
struct ColorSwatchExecutor
{
VTKM_CONT
ColorSwatchExecutor(vtkm::Id2 dims,
vtkm::Id2 xBounds,
vtkm::Id2 yBounds,
const vtkm::Vec<vtkm::Float32, 4>& color,
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorBuffer)
: Dims(dims)
, XBounds(xBounds)
, YBounds(yBounds)
, Color(color)
, ColorBuffer(colorBuffer)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device) const
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
vtkm::Id totalPixels = (XBounds[1] - XBounds[0]) * (YBounds[1] - YBounds[0]);
vtkm::cont::ArrayHandleCounting<vtkm::Id> iterator(0, 1, totalPixels);
vtkm::worklet::DispatcherMapField<DrawColorSwatch, Device> dispatcher(
DrawColorSwatch(this->Dims, this->XBounds, this->YBounds, Color));
dispatcher.Invoke(iterator, this->ColorBuffer);
return true;
}
vtkm::Id2 Dims;
vtkm::Id2 XBounds;
vtkm::Id2 YBounds;
const vtkm::Vec<vtkm::Float32, 4>& Color;
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& ColorBuffer;
}; // struct ColorSwatchExecutor
struct ColorBarExecutor
{
VTKM_CONT
@ -240,7 +319,7 @@ struct ColorBarExecutor
bool Horizontal;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& ColorMap;
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& ColorBuffer;
}; // struct ColorBarExecutor
}; // struct ColorSwatchExecutor
} // namespace internal
@ -365,13 +444,28 @@ void Canvas::ResizeBuffers(vtkm::Id width, vtkm::Id height)
Internals->Height = height;
}
void Canvas::AddColorSwatch(const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point0),
void Canvas::AddColorSwatch(const vtkm::Vec<vtkm::Float64, 2>& point0,
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point1),
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point2),
const vtkm::Vec<vtkm::Float64, 2>& point2,
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point3),
const vtkm::rendering::Color& vtkmNotUsed(color)) const
const vtkm::rendering::Color& color) const
{
// Not implemented
std::cout << point0 << "\n";
std::cout << point2 << "\n";
vtkm::Float64 width = static_cast<vtkm::Float64>(this->GetWidth());
vtkm::Float64 height = static_cast<vtkm::Float64>(this->GetHeight());
vtkm::Id2 x, y;
x[0] = static_cast<vtkm::Id>(((point0[0] + 1.) / 2.) * width + .5);
x[1] = static_cast<vtkm::Id>(((point2[0] + 1.) / 2.) * width + .5);
y[0] = static_cast<vtkm::Id>(((point0[1] + 1.) / 2.) * height + .5);
y[1] = static_cast<vtkm::Id>(((point2[1] + 1.) / 2.) * height + .5);
vtkm::Id swatchWidth = x[1] - x[0];
vtkm::Id swatchHeight = y[1] - y[0];
vtkm::Id2 dims(this->GetWidth(), this->GetHeight());
vtkm::cont::TryExecute(
internal::ColorSwatchExecutor(dims, x, y, color.Components, this->GetColorBuffer()));
}
void Canvas::AddColorSwatch(const vtkm::Float64 x0,

@ -40,6 +40,40 @@ namespace rendering
namespace
{
class Convert1DCoordinates : public vtkm::worklet::WorkletMapField
{
private:
public:
VTKM_CONT
Convert1DCoordinates() {}
typedef void ControlSignature(FieldIn<>,
FieldIn<vtkm::TypeListTagScalarAll>,
FieldOut<>,
FieldOut<>);
typedef void ExecutionSignature(_1, _2, _3, _4);
template <typename ScalarType>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Float32, 3>& inCoord,
const ScalarType& scalar,
vtkm::Vec<vtkm::Float32, 3>& outCoord,
vtkm::Float32& fieldOut) const
{
//
// Rendering supports lines based on a cellSetStructured<1>
// where only the x coord matters. It creates a y based on
// the scalar values and connects all the points with lines.
// So, we need to convert it back to something that can
// actuall be rendered.
//
outCoord[0] = inCoord[0];
outCoord[1] = static_cast<vtkm::Float32>(scalar);
outCoord[2] = 0.f;
// all lines have the same color
fieldOut = 1.f;
}
}; // convert coords
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
@ -220,13 +254,64 @@ void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
const vtkm::Range& scalarRange)
{
vtkm::cont::DynamicCellSet cellSet = inCellSet;
vtkm::cont::Field field = inScalarField;
if (!(this->Internals->ShowInternalZones))
bool is1D = cellSet.IsSameType(vtkm::cont::CellSetStructured<1>());
vtkm::cont::CoordinateSystem actualCoords = coords;
vtkm::cont::Field actualField = inScalarField;
if (is1D)
{
bool isSupportedField = inScalarField.GetAssociation() == vtkm::cont::Field::ASSOC_POINTS;
if (!isSupportedField)
{
throw vtkm::cont::ErrorBadValue(
"WireFramer: field must be associated with points for 1D cell set");
}
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> newCoords;
vtkm::cont::ArrayHandle<vtkm::Float32> newScalars;
//
// Convert the cell set into something we can draw
//
vtkm::worklet::DispatcherMapField<Convert1DCoordinates, vtkm::cont::DeviceAdapterTagSerial>(
Convert1DCoordinates())
.Invoke(coords.GetData(), inScalarField.GetData(), newCoords, newScalars);
actualCoords = vtkm::cont::CoordinateSystem("coords", newCoords);
actualField =
vtkm::cont::Field(inScalarField.GetName(), vtkm::cont::Field::ASSOC_POINTS, newScalars);
vtkm::Id numCells = cellSet.GetNumberOfCells();
vtkm::cont::ArrayHandle<vtkm::Id> conn;
conn.Allocate(numCells * 2);
auto connPortal = conn.GetPortalControl();
for (int i = 0; i < numCells; ++i)
{
connPortal.Set(i * 2 + 0, i);
connPortal.Set(i * 2 + 1, i + 1);
}
vtkm::cont::CellSetSingleType<> newCellSet("cells");
newCellSet.Fill(newCoords.GetNumberOfValues(), vtkm::CELL_SHAPE_LINE, 2, conn);
cellSet = vtkm::cont::DynamicCellSet(newCellSet);
}
bool isLines = false;
// Check for a cell set that is already lines
// Since there is no need to de external faces or
// render the depth of the mesh to hide internal zones
if (cellSet.IsSameType(vtkm::cont::CellSetSingleType<>()))
{
auto singleType = cellSet.Cast<vtkm::cont::CellSetSingleType<>>();
isLines = singleType.GetCellShape(0) == vtkm::CELL_SHAPE_LINE;
}
bool doExternalFaces = !(this->Internals->ShowInternalZones) && !isLines && !is1D;
if (doExternalFaces)
{
// If internal zones are to be hidden, the number of edges processed can be reduced by
// running the external faces filter on the input cell set.
vtkm::cont::DataSet dataSet;
dataSet.AddCoordinateSystem(coords);
dataSet.AddCoordinateSystem(actualCoords);
dataSet.AddCellSet(inCellSet);
vtkm::filter::ExternalFaces externalFaces;
externalFaces.SetCompactPoints(false);
@ -234,7 +319,7 @@ void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
vtkm::filter::Result result = externalFaces.Execute(dataSet);
externalFaces.MapFieldOntoOutput(result, inScalarField);
cellSet = result.GetDataSet().GetCellSet();
field = result.GetDataSet().GetField(0);
actualField = result.GetDataSet().GetField(0);
}
// Extract unique edges from the cell set.
@ -246,7 +331,9 @@ void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
this->Internals->Canvas, this->Internals->ShowInternalZones, this->Internals->IsOverlay);
// Render the cell set using a raytracer, on a separate canvas, and use the generated depth
// buffer, which represents the solid mesh, to avoid drawing on the internal zones
if (!(this->Internals->ShowInternalZones) && !(this->Internals->IsOverlay))
bool renderDepth =
!(this->Internals->ShowInternalZones) && !(this->Internals->IsOverlay) && !isLines && !is1D;
if (renderDepth)
{
CanvasRayTracer canvas(this->Internals->Canvas->GetWidth(),
this->Internals->Canvas->GetHeight());
@ -257,17 +344,17 @@ void MapperWireframer::RenderCells(const vtkm::cont::DynamicCellSet& inCellSet,
MapperRayTracer raytracer;
raytracer.SetCanvas(&canvas);
raytracer.SetActiveColorTable(colorTable);
raytracer.RenderCells(cellSet, coords, field, colorTable, camera, scalarRange);
raytracer.RenderCells(cellSet, actualCoords, actualField, colorTable, camera, scalarRange);
renderer.SetSolidDepthBuffer(canvas.GetDepthBuffer());
}
else if (this->Internals->IsOverlay)
else
{
renderer.SetSolidDepthBuffer(this->Internals->Canvas->GetDepthBuffer());
}
renderer.SetCamera(camera);
renderer.SetColorMap(this->ColorMap);
renderer.SetData(coords, edgeIndices, field, scalarRange);
renderer.SetData(actualCoords, edgeIndices, actualField, scalarRange);
renderer.Render();
}

@ -72,12 +72,10 @@ void View2D::RenderScreenAnnotations()
viewportRight,
viewportBottom,
viewportTop);
this->HorizontalAxisAnnotation.SetColor(AxisColor);
this->HorizontalAxisAnnotation.SetScreenPosition(
viewportLeft, viewportBottom, viewportRight, viewportBottom);
vtkm::Bounds viewRange = this->GetCamera().GetViewRange2D();
this->HorizontalAxisAnnotation.SetRangeForAutoTicks(viewRange.X.Min, viewRange.X.Max);
this->HorizontalAxisAnnotation.SetMajorTickSize(0, .05, 1.0);
this->HorizontalAxisAnnotation.SetMinorTickSize(0, .02, 1.0);
@ -138,6 +136,8 @@ void View2D::UpdateCameraProperties()
(static_cast<vtkm::Float32>(this->GetCanvas().GetHeight())) *
(top - bottom) / (right - left));
}
vtkm::Float32 left, right, bottom, top;
this->GetCamera().GetViewRange2D(left, right, bottom, top);
}
}
} // namespace vtkm::rendering

@ -165,6 +165,11 @@ public:
EdgePlotter(const vtkm::Matrix<vtkm::Float32, 4, 4>& worldToProjection,
vtkm::Id width,
vtkm::Id height,
vtkm::Id subsetWidth,
vtkm::Id subsetHeight,
vtkm::Id xOffset,
vtkm::Id yOffset,
bool assocPoints,
const vtkm::Range& fieldRange,
const ColorMapHandle& colorMap,
const AtomicPackedFrameBufferHandle& frameBuffer,
@ -172,6 +177,11 @@ public:
: WorldToProjection(worldToProjection)
, Width(width)
, Height(height)
, SubsetWidth(subsetWidth)
, SubsetHeight(subsetHeight)
, XOffset(xOffset)
, YOffset(yOffset)
, AssocPoints(assocPoints)
, ColorMap(colorMap.PrepareForInput(DeviceTag()))
, ColorMapSize(vtkm::Float32(colorMap.GetNumberOfValues() - 1))
, FrameBuffer(frameBuffer)
@ -191,6 +201,7 @@ public:
vtkm::Vec<vtkm::Float32, 3> point1 = coordsPortal.Get(edgeIndices[0]);
vtkm::Vec<vtkm::Float32, 3> point2 = coordsPortal.Get(edgeIndices[1]);
TransformWorldToViewport(point1);
TransformWorldToViewport(point2);
@ -227,7 +238,16 @@ public:
vtkm::Float32 xPxl1 = xEnd, yPxl1 = IntegerPart(yEnd);
vtkm::Float32 zPxl1 = vtkm::Lerp(z1, z2, (xPxl1 - x1) / dx);
vtkm::Float64 point1Field = fieldPortal.Get(point1Idx);
vtkm::Float64 point2Field = fieldPortal.Get(point2Idx);
vtkm::Float64 point2Field;
if (AssocPoints)
{
point2Field = fieldPortal.Get(point2Idx);
}
else
{
// cell associated field has a solid line color
point2Field = point1Field;
}
// Plot first endpoint
vtkm::Vec<vtkm::Float32, 4> color = GetColor(point1Field);
@ -301,8 +321,8 @@ private:
point[i] = temp[i] / temp[3];
}
// Scale to canvas width and height
point[0] = (point[0] * 0.5f + 0.5f) * vtkm::Float32(Width);
point[1] = (point[1] * 0.5f + 0.5f) * vtkm::Float32(Height);
point[0] = (point[0] * 0.5f + 0.5f) * vtkm::Float32(SubsetWidth) + vtkm::Float32(XOffset);
point[1] = (point[1] * 0.5f + 0.5f) * vtkm::Float32(SubsetHeight) + vtkm::Float32(YOffset);
// Convert from -1/+1 to 0/+1 range
point[2] = point[2] * 0.5f + 0.5f;
// Offset the point to a bit towards the camera. This is to ensure that the front faces of
@ -315,6 +335,7 @@ private:
{
vtkm::Int32 colorIdx =
vtkm::Int32((vtkm::Float32(fieldValue) - FieldMin) * ColorMapSize * InverseFieldDelta);
colorIdx = vtkm::Min(ColorMap.GetNumberOfValues() - 1, vtkm::Max(0, colorIdx));
return ColorMap.Get(colorIdx);
}
@ -353,6 +374,11 @@ private:
vtkm::Matrix<vtkm::Float32, 4, 4> WorldToProjection;
vtkm::Id Width;
vtkm::Id Height;
vtkm::Id SubsetWidth;
vtkm::Id SubsetHeight;
vtkm::Id XOffset;
vtkm::Id YOffset;
bool AssocPoints;
ColorMapPortalConst ColorMap;
vtkm::Float32 ColorMapSize;
AtomicPackedFrameBufferHandle FrameBuffer;
@ -438,10 +464,6 @@ private:
template <typename DeviceTag>
VTKM_CONT void RenderWithDevice(DeviceTag)
{
if (ScalarField.GetAssociation() != vtkm::cont::Field::ASSOC_POINTS)
{
throw vtkm::cont::ErrorBadValue("Field is not associated with points");
}
// The wireframe should appear on top of any prerendered data, and hide away the internal
// zones if `ShowInternalZones` is set to false. Since the prerendered data (or the solid
@ -479,10 +501,47 @@ private:
vtkm::worklet::DispatcherMapField<CopyIntoFrameBuffer>(bufferCopy)
.Invoke(Canvas->GetColorBuffer(), SolidDepthBuffer, FrameBuffer);
}
//
// detect a 2D camera and set the correct viewport.
// The View port specifies what the region of the screen
// to draw to which baiscally modifies the width and the
// height of the "canvas"
//
vtkm::Id xOffset = 0;
vtkm::Id yOffset = 0;
vtkm::Id subsetWidth = width;
vtkm::Id subsetHeight = subsetHeight;
bool ortho2d = Camera.GetMode() == vtkm::rendering::Camera::MODE_2D;
if (ortho2d)
{
vtkm::Float32 vl, vr, vb, vt;
Camera.GetRealViewport(width, height, vl, vr, vb, vt);
vtkm::Float32 _x = static_cast<vtkm::Float32>(width) * (1.f + vl) / 2.f;
vtkm::Float32 _y = static_cast<vtkm::Float32>(height) * (1.f + vb) / 2.f;
vtkm::Float32 _w = static_cast<vtkm::Float32>(width) * (vr - vl) / 2.f;
vtkm::Float32 _h = static_cast<vtkm::Float32>(height) * (vt - vb) / 2.f;
subsetWidth = static_cast<vtkm::Id>(_w);
subsetHeight = static_cast<vtkm::Id>(_h);
yOffset = static_cast<vtkm::Id>(_y);
xOffset = static_cast<vtkm::Id>(_x);
}
bool isSupportedField = (ScalarField.GetAssociation() == vtkm::cont::Field::ASSOC_POINTS ||
ScalarField.GetAssociation() == vtkm::cont::Field::ASSOC_CELL_SET);
if (!isSupportedField)
throw vtkm::cont::ErrorBadValue("Field not associated with cell set or points");
bool isAssocPoints = ScalarField.GetAssociation() == vtkm::cont::Field::ASSOC_POINTS;
EdgePlotter<DeviceTag> plotter(WorldToProjection,
width,
height,
subsetWidth,
subsetHeight,
xOffset,
yOffset,
isAssocPoints,
ScalarFieldRange,
ColorMap,
FrameBuffer,

@ -148,7 +148,7 @@ public:
xEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (xmax - xmin));
yEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (ymax - ymin));
zEpsilon = vtkm::Max(minEpsilon, AABB_EPSILON * (zmax - zmin));
//if(xEpsilon == minEpsilon) std::cout<<"m";
xmin -= xEpsilon;
ymin -= yEpsilon;
zmin -= zEpsilon;

@ -161,6 +161,108 @@ public:
}; // class pixelData
class Camera::Ortho2DRayGen : public vtkm::worklet::WorkletMapField
{
public:
vtkm::Int32 w;
vtkm::Int32 h;
vtkm::Int32 Minx;
vtkm::Int32 Miny;
vtkm::Int32 SubsetWidth;
vtkm::Vec<vtkm::Float32, 3> nlook; // normalized look
vtkm::Vec<vtkm::Float32, 3> PixelDelta;
vtkm::Vec<vtkm::Float32, 3> delta_y;
vtkm::Vec<vtkm::Float32, 3> StartOffset;
VTKM_CONT
Ortho2DRayGen(vtkm::Int32 width,
vtkm::Int32 height,
vtkm::Float32 vtkmNotUsed(_zoom),
vtkm::Int32 subsetWidth,
vtkm::Int32 minx,
vtkm::Int32 miny,
const vtkm::rendering::Camera& camera)
: w(width)
, h(height)
, Minx(minx)
, Miny(miny)
, SubsetWidth(subsetWidth)
{
vtkm::Float32 left, right, bottom, top;
camera.GetViewRange2D(left, right, bottom, top);
vtkm::Float32 vl, vr, vb, vt;
camera.GetRealViewport(width, height, vl, vr, vb, vt);
vtkm::Float32 _w = static_cast<vtkm::Float32>(width) * (vr - vl) / 2.f;
vtkm::Float32 _h = static_cast<vtkm::Float32>(height) * (vt - vb) / 2.f;
vtkm::Vec<vtkm::Float32, 2> minPoint(left, bottom);
vtkm::Vec<vtkm::Float32, 2> maxPoint(right, top);
vtkm::Vec<vtkm::Float32, 2> delta = maxPoint - minPoint;
//delta[0] /= vtkm::Float32(width);
//delta[1] /= vtkm::Float32(height);
delta[0] /= vtkm::Float32(_w);
delta[1] /= vtkm::Float32(_h);
PixelDelta[0] = delta[0];
PixelDelta[1] = delta[1];
PixelDelta[2] = 0.f;
vtkm::Vec<vtkm::Float32, 2> startOffset = minPoint + delta / 2.f;
StartOffset[0] = startOffset[0];
StartOffset[1] = startOffset[1];
// always push the rays back from the origin
StartOffset[2] = -1.f;
vtkm::Normalize(nlook);
}
typedef void ControlSignature(FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>,
FieldOut<>);
typedef void ExecutionSignature(WorkIndex, _1, _2, _3, _4, _5, _6, _7);
template <typename Precision>
VTKM_EXEC void operator()(vtkm::Id idx,
Precision& rayDirX,
Precision& rayDirY,
Precision& rayDirZ,
Precision& rayOriginX,
Precision& rayOriginY,
Precision& rayOriginZ,
vtkm::Id& pixelIndex) const
{
// this is 2d so always look down z
rayDirX = 0.f;
rayDirY = 0.f;
rayDirZ = 1.f;
//
// Pixel subset is the pixels in the 2d viewport
// not where the rays might intersect data like
// the perspective ray gen
//
int i = vtkm::Int32(idx) % SubsetWidth;
int j = vtkm::Int32(idx) / SubsetWidth;
vtkm::Vec<vtkm::Float32, 3> pos;
pos[0] = vtkm::Float32(i);
pos[1] = vtkm::Float32(j);
pos[2] = 0.f;
vtkm::Vec<vtkm::Float32, 3> origin = StartOffset + pos * PixelDelta;
rayOriginX = origin[0];
rayOriginY = origin[1];
rayOriginZ = origin[2];
i += Minx;
j += Miny;
pixelIndex = static_cast<vtkm::Id>(j * w + i);
}
}; // class perspective ray gen
class Camera::PerspectiveRayGen : public vtkm::worklet::WorkletMapField
{
public:
@ -330,6 +432,7 @@ void Camera::SetParameters(const vtkm::rendering::Camera& camera,
this->SetUp(camera.GetViewUp());
this->SetLookAt(camera.GetLookAt());
this->SetPosition(camera.GetPosition());
this->SetZoom(camera.GetZoom());
this->SetFieldOfView(camera.GetFieldOfView());
this->SetHeight(static_cast<vtkm::Int32>(canvas.GetHeight()));
this->SetWidth(static_cast<vtkm::Int32>(canvas.GetWidth()));
@ -621,20 +724,13 @@ VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
vtkm::cont::Timer<Device> createTimer;
logger->OpenLogEntry("ray_camera");
logger->AddLogData("device", GetDeviceString(Device()));
this->UpdateDimensions(rays, Device(), boundingBox);
bool ortho = this->CameraView.GetMode() == vtkm::rendering::Camera::MODE_2D;
this->UpdateDimensions(rays, Device(), boundingBox, ortho);
this->WriteSettingsToLog();
vtkm::cont::Timer<Device> timer;
//Set the origin of the ray back to the camera position
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(this->Position[0]))
.Invoke(rays.OriginX);
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(this->Position[1]))
.Invoke(rays.OriginY);
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(this->Position[2]))
.Invoke(rays.OriginZ);
Precision infinity;
GetInfinity(infinity);
@ -656,21 +752,55 @@ VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
//Reset the camera look vector
this->Look = this->LookAt - this->Position;
vtkm::Normalize(this->Look);
//Create the ray direction
vtkm::worklet::DispatcherMapField<PerspectiveRayGen, Device>(PerspectiveRayGen(this->Width,
this->Height,
this->FovX,
this->FovY,
this->Look,
this->Up,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY))
.Invoke(rays.DirX,
rays.DirY,
rays.DirZ,
rays.PixelIdx); //X Y Z
if (ortho)
{
vtkm::worklet::DispatcherMapField<Ortho2DRayGen, Device>(Ortho2DRayGen(this->Width,
this->Height,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY,
this->CameraView))
.Invoke(rays.DirX,
rays.DirY,
rays.DirZ,
rays.OriginX,
rays.OriginY,
rays.OriginZ,
rays.PixelIdx); //X Y Z
}
else
{
//Create the ray direction
vtkm::worklet::DispatcherMapField<PerspectiveRayGen, Device>(
PerspectiveRayGen(this->Width,
this->Height,
this->FovX,
this->FovY,
this->Look,
this->Up,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY))
.Invoke(rays.DirX,
rays.DirY,
rays.DirZ,
rays.PixelIdx); //X Y Z
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(
MemSet<Precision>(this->Position[0]))
.Invoke(rays.OriginX);
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(
MemSet<Precision>(this->Position[1]))
.Invoke(rays.OriginY);
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(
MemSet<Precision>(this->Position[2]))
.Invoke(rays.OriginZ);
}
time = timer.GetElapsedTime();
logger->AddLogData("ray_gen", time);
@ -782,36 +912,53 @@ void Camera::FindSubset(const vtkm::Bounds& bounds)
template <typename Device, typename Precision>
VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
Device,
const vtkm::Bounds& boundingBox)
const vtkm::Bounds& boundingBox,
bool ortho2D)
{
// If bounds have been provided, only cast rays that could hit the data
bool imageSubsetModeOn = boundingBox.IsNonEmpty();
//Create a transform matrix using the rendering::camera class
vtkm::rendering::Camera camera;
camera.SetFieldOfView(this->GetFieldOfView());
camera.SetLookAt(this->GetLookAt());
camera.SetPosition(this->GetPosition());
camera.SetViewUp(this->GetUp());
//
// Just create come clipping range, we ignore the zmax value in subsetting
//
vtkm::Float64 maxDim = vtkm::Max(
boundingBox.X.Max - boundingBox.X.Min,
vtkm::Max(boundingBox.Y.Max - boundingBox.Y.Min, boundingBox.Z.Max - boundingBox.Z.Min));
maxDim *= 100;
camera.SetClippingRange(.0001, maxDim);
this->CameraView = camera;
//Update our ViewProjection matrix
this->ViewProjectionMat =
vtkm::MatrixMultiply(this->CameraView.CreateProjectionMatrix(this->Width, this->Height),
this->CameraView.CreateViewMatrix());
//Find the pixel footprint
if (imageSubsetModeOn)
if (imageSubsetModeOn && !ortho2D)
{
//Create a transform matrix using the rendering::camera class
vtkm::rendering::Camera camera = this->CameraView;
camera.SetFieldOfView(this->GetFieldOfView());
camera.SetLookAt(this->GetLookAt());
camera.SetPosition(this->GetPosition());
camera.SetViewUp(this->GetUp());
//
// Just create come clipping range, we ignore the zmax value in subsetting
//
vtkm::Float64 maxDim = vtkm::Max(
boundingBox.X.Max - boundingBox.X.Min,
vtkm::Max(boundingBox.Y.Max - boundingBox.Y.Min, boundingBox.Z.Max - boundingBox.Z.Min));
maxDim *= 100;
camera.SetClippingRange(.0001, maxDim);
//Update our ViewProjection matrix
this->ViewProjectionMat =
vtkm::MatrixMultiply(this->CameraView.CreateProjectionMatrix(this->Width, this->Height),
this->CameraView.CreateViewMatrix());
this->FindSubset(boundingBox);
}
else if (ortho2D)
{
// 2D rendering has a viewport that represents the area of the canvas where the image
// is drawn. Thus, we have to create rays cooresponding to that region of the
// canvas, so annotations are correctly rendered
vtkm::Float32 vl, vr, vb, vt;
this->CameraView.GetRealViewport(this->GetWidth(), this->GetHeight(), vl, vr, vb, vt);
vtkm::Float32 _x = static_cast<vtkm::Float32>(this->GetWidth()) * (1.f + vl) / 2.f;
vtkm::Float32 _y = static_cast<vtkm::Float32>(this->GetHeight()) * (1.f + vb) / 2.f;
vtkm::Float32 _w = static_cast<vtkm::Float32>(this->GetWidth()) * (vr - vl) / 2.f;
vtkm::Float32 _h = static_cast<vtkm::Float32>(this->GetHeight()) * (vt - vb) / 2.f;
this->SubsetWidth = static_cast<vtkm::Int32>(_w);
this->SubsetHeight = static_cast<vtkm::Int32>(_h);
this->SubsetMinY = static_cast<vtkm::Int32>(_y);
this->SubsetMinX = static_cast<vtkm::Int32>(_x);
}
else
{
//Update the image dimensions

@ -67,6 +67,7 @@ public:
// cuda does not compile if this is private
class PerspectiveRayGen;
class Ortho2DRayGen;
std::string ToString();
@ -162,7 +163,8 @@ private:
template <typename DeviceAdapter, typename Precision>
VTKM_CONT void UpdateDimensions(Ray<Precision>& rays,
DeviceAdapter,
const vtkm::Bounds& boundingBox);
const vtkm::Bounds& boundingBox,
bool ortho2D);
}; // class camera
}

@ -375,7 +375,7 @@ public:
const vtkm::rendering::raytracing::Camera& camera)
{
// TODO: support light positions
vtkm::Vec<vtkm::Float32, 3> scale(5, 5, 5);
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, Device>(

@ -42,7 +42,9 @@ namespace testing
{
template <typename ViewType>
inline void SetCamera(vtkm::rendering::Camera& camera, const vtkm::Bounds& coordBounds);
inline void SetCamera(vtkm::rendering::Camera& camera,
const vtkm::Bounds& coordBounds,
const vtkm::cont::Field& field);
template <typename ViewType>
inline void SetCamera(vtkm::rendering::Camera& camera,
const vtkm::Bounds& coordBounds,
@ -50,7 +52,8 @@ inline void SetCamera(vtkm::rendering::Camera& camera,
template <>
inline void SetCamera<vtkm::rendering::View3D>(vtkm::rendering::Camera& camera,
const vtkm::Bounds& coordBounds)
const vtkm::Bounds& coordBounds,
const vtkm::cont::Field&)
{
camera = vtkm::rendering::Camera();
camera.ResetToBounds(coordBounds);
@ -60,7 +63,8 @@ inline void SetCamera<vtkm::rendering::View3D>(vtkm::rendering::Camera& camera,
template <>
inline void SetCamera<vtkm::rendering::View2D>(vtkm::rendering::Camera& camera,
const vtkm::Bounds& coordBounds)
const vtkm::Bounds& coordBounds,
const vtkm::cont::Field&)
{
camera = vtkm::rendering::Camera(vtkm::rendering::Camera::MODE_2D);
camera.ResetToBounds(coordBounds);
@ -105,7 +109,39 @@ void Render(const vtkm::cont::DataSet& ds,
scene.AddActor(vtkm::rendering::Actor(
ds.GetCellSet(), ds.GetCoordinateSystem(), ds.GetField(fieldNm), colorTable));
vtkm::rendering::Camera camera;
SetCamera<ViewType>(camera, ds.GetCoordinateSystem().GetBounds());
SetCamera<ViewType>(camera, ds.GetCoordinateSystem().GetBounds(), ds.GetField(fieldNm));
ViewType view(scene, mapper, canvas, camera, vtkm::rendering::Color(0.2f, 0.2f, 0.2f, 1.0f));
// 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,
const std::vector<vtkm::rendering::Color>& colors,
const std::string& outputFile)
{
MapperType mapper;
CanvasType canvas(512, 512);
canvas.SetBackgroundColor(vtkm::rendering::Color::white);
vtkm::rendering::Scene scene;
size_t numFields = fields.size();
for (size_t i = 0; i < numFields; ++i)
{
scene.AddActor(vtkm::rendering::Actor(
ds.GetCellSet(), ds.GetCoordinateSystem(), ds.GetField(fields[i]), colors[i]));
}
vtkm::rendering::Camera camera;
SetCamera<ViewType>(camera, ds.GetCoordinateSystem().GetBounds(), ds.GetField(fields[0]));
ViewType view(scene, mapper, canvas, camera, vtkm::rendering::Color(0.2f, 0.2f, 0.2f, 1.0f));
// Print the title
@ -167,7 +203,7 @@ void MultiMapperRender(const vtkm::cont::DataSet& ds1,
vtkm::Bounds totalBounds =
ds1.GetCoordinateSystem().GetBounds() + ds2.GetCoordinateSystem().GetBounds();
vtkm::rendering::Camera camera;
SetCamera<ViewType>(camera, totalBounds);
SetCamera<ViewType>(camera, totalBounds, ds1.GetField(fieldNm));
mapper1.SetCanvas(&canvas);
mapper1.SetActiveColorTable(colorTable1);

@ -36,6 +36,7 @@ void RenderTests()
typedef vtkm::rendering::MapperRayTracer M;
typedef vtkm::rendering::CanvasRayTracer C;
typedef vtkm::rendering::View3D V3;
typedef vtkm::rendering::View2D V2;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::rendering::ColorTable colorTable("thermal");
@ -46,6 +47,9 @@ void RenderTests()
maker.Make3DRectilinearDataSet0(), "pointvar", colorTable, "rect3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
maker.Make3DExplicitDataSet4(), "pointvar", colorTable, "expl3D.pnm");
vtkm::rendering::testing::Render<M, C, V2>(
maker.Make2DUniformDataSet1(), "pointvar", colorTable, "uni2D.pnm");
}
} //namespace

@ -21,6 +21,7 @@
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperWireframer.h>
@ -46,11 +47,89 @@ vtkm::cont::DataSet Make3DUniformDataSet(vtkm::Id size = 64)
return dataSet;
}
vtkm::cont::DataSet Make1DUniformDataSet()
{
vtkm::cont::DataSetBuilderUniform builder;
std::vector<vtkm::Float32> x;
x.push_back(0.f);
x.push_back(1.f);
x.push_back(2.f);
x.push_back(3.f);
x.push_back(4.f);
x.push_back(5.f);
std::vector<vtkm::Float32> y;
y.push_back(10.f);
y.push_back(11.f);
y.push_back(11.5f);
y.push_back(13.f);
y.push_back(14.f);
y.push_back(13.f);
vtkm::cont::DataSet dataSet = builder.Create(x.size());
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(dataSet, "something", y);
return dataSet;
}
vtkm::cont::DataSet Make2DExplicitDataSet()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
const int nVerts = 5;
using CoordType = vtkm::Vec<vtkm::Float32, 3>;
std::vector<CoordType> coords(nVerts);
CoordType coordinates[nVerts] = { CoordType(0, 0, 0),
CoordType(1, .5, 0),
CoordType(2, 1, 0),
CoordType(3, 1.7, 0),
CoordType(4, 3, 0) };
std::vector<vtkm::Float32> cellVar;
cellVar.push_back(10);
cellVar.push_back(12);
cellVar.push_back(13);
cellVar.push_back(14);
std::vector<vtkm::Float32> pointVar;
pointVar.push_back(10);
pointVar.push_back(12);
pointVar.push_back(13);
pointVar.push_back(14);
pointVar.push_back(15);
dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates, nVerts));
vtkm::cont::CellSetSingleType<> cellSet("cells");
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
connectivity.Allocate(8);
auto connPortal = connectivity.GetPortalControl();
connPortal.Set(0, 0);
connPortal.Set(1, 1);
connPortal.Set(2, 1);
connPortal.Set(3, 2);
connPortal.Set(4, 2);
connPortal.Set(5, 3);
connPortal.Set(6, 3);
connPortal.Set(7, 4);
cellSet.Fill(nVerts, vtkm::CELL_SHAPE_LINE, 2, connectivity);
dataSet.AddCellSet(cellSet);
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(dataSet, "pointVar", pointVar);
dsf.AddCellField(dataSet, "cellVar", cellVar);
dataSet.PrintSummary(std::cout);
return dataSet;
}
void RenderTests()
{
typedef vtkm::rendering::MapperWireframer M;
typedef vtkm::rendering::CanvasRayTracer C;
typedef vtkm::rendering::View3D V3;
typedef vtkm::rendering::View2D V2;
typedef vtkm::rendering::View1D V1;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::rendering::ColorTable colorTable("thermal");
@ -63,6 +142,19 @@ void RenderTests()
maker.Make3DExplicitDataSet4(), "pointvar", colorTable, "expl3D.pnm");
vtkm::rendering::testing::Render<M, C, V3>(
Make3DUniformDataSet(), "pointvar", colorTable, "uniform3D.pnm");
vtkm::rendering::testing::Render<M, C, V2>(
Make2DExplicitDataSet(), "cellVar", colorTable, "lines2D.pnm");
//
// Test the 1D cell set line plot with multiple lines
//
std::vector<std::string> fields;
fields.push_back("pointvar");
fields.push_back("pointvar2");
std::vector<vtkm::rendering::Color> colors;
colors.push_back(vtkm::rendering::Color(1.f, 0.f, 0.f));
colors.push_back(vtkm::rendering::Color(0.f, 1.f, 0.f));
vtkm::rendering::testing::Render<M, C, V1>(
maker.Make1DUniformDataSet0(), fields, colors, "lines1D.pnm");
}
} //namespace