2016-08-26 21:58:21 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//
|
|
|
|
// Copyright 2016 Sandia Corporation.
|
|
|
|
// Copyright 2016 UT-Battelle, LLC.
|
|
|
|
// Copyright 2016 Los Alamos National Security.
|
|
|
|
//
|
|
|
|
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
|
|
// 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/Canvas.h>
|
|
|
|
|
2017-08-31 17:40:30 +00:00
|
|
|
#include <vtkm/cont/TryExecute.h>
|
|
|
|
#include <vtkm/worklet/DispatcherMapField.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapField.h>
|
|
|
|
|
2016-08-26 21:58:21 +00:00
|
|
|
#include <fstream>
|
2017-05-18 14:51:24 +00:00
|
|
|
#include <iostream>
|
2016-08-26 21:58:21 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace rendering
|
|
|
|
{
|
2017-08-31 17:40:30 +00:00
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
|
|
|
|
struct ClearBuffers : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
typedef void ControlSignature(FieldOut<>, FieldOut<>);
|
|
|
|
typedef void ExecutionSignature(_1, _2);
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
ClearBuffers() {}
|
|
|
|
|
|
|
|
VTKM_EXEC
|
|
|
|
void operator()(vtkm::Vec<vtkm::Float32, 4>& color, vtkm::Float32& depth) const
|
|
|
|
{
|
|
|
|
color[0] = 0.f;
|
|
|
|
color[1] = 0.f;
|
|
|
|
color[2] = 0.f;
|
|
|
|
color[3] = 0.f;
|
|
|
|
// The depth is set to slightly larger than 1.0f, ensuring this color value always fails a
|
|
|
|
// depth check
|
|
|
|
depth = 1.001f;
|
|
|
|
}
|
|
|
|
}; // struct ClearBuffers
|
|
|
|
|
|
|
|
struct ClearBuffersExecutor
|
|
|
|
{
|
|
|
|
typedef vtkm::rendering::Canvas::ColorBufferType ColorBufferType;
|
|
|
|
typedef vtkm::rendering::Canvas::DepthBufferType DepthBufferType;
|
|
|
|
|
|
|
|
ColorBufferType ColorBuffer;
|
|
|
|
DepthBufferType DepthBuffer;
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
ClearBuffersExecutor(const ColorBufferType& colorBuffer, const DepthBufferType& depthBuffer)
|
|
|
|
: ColorBuffer(colorBuffer)
|
|
|
|
, DepthBuffer(depthBuffer)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT bool operator()(Device) const
|
|
|
|
{
|
|
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
|
|
|
|
|
|
|
ClearBuffers worklet;
|
|
|
|
vtkm::worklet::DispatcherMapField<ClearBuffers, Device> dispatcher(worklet);
|
|
|
|
dispatcher.Invoke(this->ColorBuffer, this->DepthBuffer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}; // struct ClearBuffersExecutor
|
|
|
|
|
|
|
|
struct BlendBackground : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
BlendBackground(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
|
|
|
: BackgroundColor(backgroundColor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void ControlSignature(FieldInOut<>);
|
|
|
|
typedef void ExecutionSignature(_1);
|
|
|
|
|
|
|
|
VTKM_EXEC void operator()(vtkm::Vec<vtkm::Float32, 4>& color) const
|
|
|
|
{
|
|
|
|
if (color[3] >= 1.f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vtkm::Float32 alpha = BackgroundColor[3] * (1.f - color[3]);
|
|
|
|
color[0] = color[0] + BackgroundColor[0] * alpha;
|
|
|
|
color[1] = color[1] + BackgroundColor[1] * alpha;
|
|
|
|
color[2] = color[2] + BackgroundColor[2] * alpha;
|
|
|
|
color[3] = alpha + color[3];
|
|
|
|
}
|
|
|
|
}; // struct BlendBackground
|
|
|
|
|
|
|
|
struct BlendBackgroundExecutor
|
|
|
|
{
|
|
|
|
typedef vtkm::rendering::Canvas::ColorBufferType ColorBufferType;
|
|
|
|
|
|
|
|
ColorBufferType ColorBuffer;
|
|
|
|
BlendBackground Worklet;
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
BlendBackgroundExecutor(const ColorBufferType& colorBuffer,
|
|
|
|
const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
|
|
|
: ColorBuffer(colorBuffer)
|
|
|
|
, Worklet(backgroundColor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT bool operator()(Device) const
|
|
|
|
{
|
|
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
|
|
|
|
|
|
|
vtkm::worklet::DispatcherMapField<BlendBackground, Device> dispatcher(this->Worklet);
|
|
|
|
dispatcher.Invoke(this->ColorBuffer);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}; // struct BlendBackgroundExecutor
|
|
|
|
|
|
|
|
} // namespace internal
|
2016-08-26 21:58:21 +00:00
|
|
|
|
|
|
|
Canvas::Canvas(vtkm::Id width, vtkm::Id height)
|
2017-05-18 14:29:41 +00:00
|
|
|
: Width(0)
|
|
|
|
, Height(0)
|
2016-08-26 21:58:21 +00:00
|
|
|
{
|
|
|
|
this->ResizeBuffers(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
Canvas::~Canvas()
|
2017-05-18 14:29:41 +00:00
|
|
|
{
|
|
|
|
}
|
2016-08-26 21:58:21 +00:00
|
|
|
|
2017-08-31 17:40:30 +00:00
|
|
|
vtkm::rendering::Canvas* Canvas::NewCopy() const
|
|
|
|
{
|
|
|
|
return new vtkm::rendering::Canvas(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::Initialize()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::Activate()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::Clear()
|
|
|
|
{
|
|
|
|
// TODO: Should the rendering library support policies or some other way to
|
|
|
|
// configure with custom devices?
|
|
|
|
vtkm::cont::TryExecute(
|
|
|
|
internal::ClearBuffersExecutor(this->GetColorBuffer(), this->GetDepthBuffer()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::Finish()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::BlendBackground()
|
|
|
|
{
|
|
|
|
vtkm::cont::TryExecute(internal::BlendBackgroundExecutor(this->GetColorBuffer(),
|
|
|
|
this->GetBackgroundColor().Components));
|
|
|
|
}
|
|
|
|
|
2017-08-31 17:50:28 +00:00
|
|
|
void Canvas::AddColorSwatch(const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point0),
|
|
|
|
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point1),
|
|
|
|
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point2),
|
|
|
|
const vtkm::Vec<vtkm::Float64, 2>& vtkmNotUsed(point3),
|
|
|
|
const vtkm::rendering::Color& vtkmNotUsed(color)) const
|
2017-08-31 17:40:30 +00:00
|
|
|
{
|
2017-08-31 17:50:28 +00:00
|
|
|
// Not implemented
|
2017-08-31 17:40:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::AddColorSwatch(const vtkm::Float64 x0,
|
|
|
|
const vtkm::Float64 y0,
|
|
|
|
const vtkm::Float64 x1,
|
|
|
|
const vtkm::Float64 y1,
|
|
|
|
const vtkm::Float64 x2,
|
|
|
|
const vtkm::Float64 y2,
|
|
|
|
const vtkm::Float64 x3,
|
|
|
|
const vtkm::Float64 y3,
|
|
|
|
const vtkm::rendering::Color& color) const
|
|
|
|
{
|
|
|
|
this->AddColorSwatch(vtkm::make_Vec(x0, y0),
|
|
|
|
vtkm::make_Vec(x1, y1),
|
|
|
|
vtkm::make_Vec(x2, y2),
|
|
|
|
vtkm::make_Vec(x3, y3),
|
|
|
|
color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::AddLine(const vtkm::Vec<vtkm::Float64, 2>& point0,
|
|
|
|
const vtkm::Vec<vtkm::Float64, 2>& point1,
|
2017-08-31 17:50:28 +00:00
|
|
|
vtkm::Float32 vtkmNotUsed(linewidth),
|
2017-08-31 17:40:30 +00:00
|
|
|
const vtkm::rendering::Color& color) const
|
|
|
|
{
|
|
|
|
const vtkm::Float32 width = static_cast<vtkm::Float32>(this->Width);
|
|
|
|
const vtkm::Float32 height = static_cast<vtkm::Float32>(this->Height);
|
|
|
|
vtkm::Id x0 = static_cast<vtkm::Id>(vtkm::Round((point0[0] * 0.5f + 0.5f) * width));
|
|
|
|
vtkm::Id y0 = static_cast<vtkm::Id>(vtkm::Round((point0[1] * 0.5f + 0.5f) * height));
|
|
|
|
vtkm::Id x1 = static_cast<vtkm::Id>(vtkm::Round((point1[0] * 0.5f + 0.5f) * width));
|
|
|
|
vtkm::Id y1 = static_cast<vtkm::Id>(vtkm::Round((point1[1] * 0.5f + 0.5f) * height));
|
|
|
|
vtkm::Id dx = vtkm::Abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
|
|
|
vtkm::Id dy = -vtkm::Abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
|
|
|
vtkm::Id err = dx + dy, err2 = 0;
|
|
|
|
ColorBufferType::PortalControl colorPortal =
|
|
|
|
ColorBufferType(this->ColorBuffer).GetPortalControl();
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
vtkm::Id index = y0 * this->Width + x0;
|
|
|
|
colorPortal.Set(index, color.Components);
|
|
|
|
if (x0 == x1 && y0 == y1)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
err2 = err * 2;
|
|
|
|
if (err2 >= dy)
|
|
|
|
{
|
|
|
|
err += dy;
|
|
|
|
x0 += sx;
|
|
|
|
}
|
|
|
|
if (err2 <= dx)
|
|
|
|
{
|
|
|
|
err += dx;
|
|
|
|
y0 += sy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::AddLine(vtkm::Float64 x0,
|
|
|
|
vtkm::Float64 y0,
|
|
|
|
vtkm::Float64 x1,
|
|
|
|
vtkm::Float64 y1,
|
|
|
|
vtkm::Float32 linewidth,
|
|
|
|
const vtkm::rendering::Color& color) const
|
|
|
|
{
|
|
|
|
this->AddLine(vtkm::make_Vec(x0, y0), vtkm::make_Vec(x1, y1), linewidth, color);
|
|
|
|
}
|
|
|
|
|
2017-08-31 17:50:28 +00:00
|
|
|
void Canvas::AddColorBar(const vtkm::Bounds& vtkmNotUsed(bounds),
|
|
|
|
const vtkm::rendering::ColorTable& vtkmNotUsed(colorTable),
|
|
|
|
bool vtkmNotUsed(horizontal)) const
|
2017-08-31 17:40:30 +00:00
|
|
|
{
|
|
|
|
// Not implemented
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::AddColorBar(vtkm::Float32 x,
|
|
|
|
vtkm::Float32 y,
|
|
|
|
vtkm::Float32 width,
|
|
|
|
vtkm::Float32 height,
|
|
|
|
const vtkm::rendering::ColorTable& colorTable,
|
|
|
|
bool horizontal) const
|
|
|
|
{
|
|
|
|
this->AddColorBar(
|
|
|
|
vtkm::Bounds(vtkm::Range(x, x + width), vtkm::Range(y, y + height), vtkm::Range(0, 0)),
|
|
|
|
colorTable,
|
|
|
|
horizontal);
|
|
|
|
}
|
|
|
|
|
2017-08-31 17:50:28 +00:00
|
|
|
void Canvas::AddText(const vtkm::Vec<vtkm::Float32, 2>& vtkmNotUsed(position),
|
|
|
|
vtkm::Float32 vtkmNotUsed(scale),
|
|
|
|
vtkm::Float32 vtkmNotUsed(angle),
|
|
|
|
vtkm::Float32 vtkmNotUsed(windowAspect),
|
|
|
|
const vtkm::Vec<vtkm::Float32, 2>& vtkmNotUsed(anchor),
|
|
|
|
const vtkm::rendering::Color& vtkmNotUsed(color),
|
|
|
|
const std::string& vtkmNotUsed(text)) const
|
2017-08-31 17:40:30 +00:00
|
|
|
{
|
|
|
|
// Not implemented
|
|
|
|
}
|
|
|
|
|
|
|
|
void Canvas::AddText(vtkm::Float32 x,
|
|
|
|
vtkm::Float32 y,
|
|
|
|
vtkm::Float32 scale,
|
|
|
|
vtkm::Float32 angle,
|
|
|
|
vtkm::Float32 windowAspect,
|
|
|
|
vtkm::Float32 anchorX,
|
|
|
|
vtkm::Float32 anchorY,
|
|
|
|
const vtkm::rendering::Color& color,
|
|
|
|
const std::string& text) const
|
|
|
|
{
|
|
|
|
this->AddText(vtkm::make_Vec(x, y),
|
|
|
|
scale,
|
|
|
|
angle,
|
|
|
|
windowAspect,
|
|
|
|
vtkm::make_Vec(anchorX, anchorY),
|
|
|
|
color,
|
|
|
|
text);
|
|
|
|
}
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
void Canvas::SaveAs(const std::string& fileName) const
|
2016-08-26 21:58:21 +00:00
|
|
|
{
|
|
|
|
this->RefreshColorBuffer();
|
2017-07-06 18:55:16 +00:00
|
|
|
std::ofstream of(fileName.c_str(), std::ios_base::binary | std::ios_base::out);
|
2017-05-18 14:29:41 +00:00
|
|
|
of << "P6" << std::endl << this->Width << " " << this->Height << std::endl << 255 << std::endl;
|
|
|
|
ColorBufferType::PortalConstControl colorPortal = this->ColorBuffer.GetPortalConstControl();
|
|
|
|
for (vtkm::Id yIndex = this->Height - 1; yIndex >= 0; yIndex--)
|
2016-08-26 21:58:21 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
for (vtkm::Id xIndex = 0; xIndex < this->Width; xIndex++)
|
2016-08-26 21:58:21 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
vtkm::Vec<vtkm::Float32, 4> tuple = colorPortal.Get(yIndex * this->Width + xIndex);
|
|
|
|
of << (unsigned char)(tuple[0] * 255);
|
|
|
|
of << (unsigned char)(tuple[1] * 255);
|
|
|
|
of << (unsigned char)(tuple[2] * 255);
|
2016-08-26 21:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
of.close();
|
|
|
|
}
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
vtkm::rendering::WorldAnnotator* Canvas::CreateWorldAnnotator() const
|
2016-08-26 21:58:21 +00:00
|
|
|
{
|
|
|
|
return new vtkm::rendering::WorldAnnotator;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // vtkm::rendering
|