refactoring ray tracing and adding new renderer
This commit is contained in:
parent
f69ead4bb0
commit
630e871ea7
@ -32,12 +32,14 @@ set(headers
|
||||
Color.h
|
||||
ColorBarAnnotation.h
|
||||
ColorTable.h
|
||||
ConnectivityProxy.h
|
||||
DecodePNG.h
|
||||
MatrixHelpers.h
|
||||
Scene.h
|
||||
Mapper.h
|
||||
MapperRayTracer.h
|
||||
MapperVolume.h
|
||||
MapperConnectivity.h
|
||||
TextAnnotation.h
|
||||
TextAnnotationBillboard.h
|
||||
TextAnnotationScreen.h
|
||||
@ -63,10 +65,12 @@ set(sources
|
||||
Color.cxx
|
||||
ColorBarAnnotation.cxx
|
||||
ColorTable.cxx
|
||||
ConnectivityProxy.cxx
|
||||
DecodePNG.cxx
|
||||
Mapper.cxx
|
||||
MapperRayTracer.cxx
|
||||
MapperVolume.cxx
|
||||
MapperConnectivity.cxx
|
||||
Scene.cxx
|
||||
TextAnnotation.cxx
|
||||
TextAnnotationBillboard.cxx
|
||||
@ -78,7 +82,11 @@ set(sources
|
||||
WorldAnnotator.cxx
|
||||
|
||||
internal/RunTriangulator.cxx
|
||||
raytracing/Ray.cxx
|
||||
raytracing/BoundingVolumeHierarchy.cxx
|
||||
raytracing/Camera.cxx
|
||||
raytracing/ChannelBuffer.cxx
|
||||
raytracing/Logger.cxx
|
||||
raytracing/RayTracer.cxx
|
||||
)
|
||||
|
||||
set(opengl_headers
|
||||
@ -115,6 +123,11 @@ set(osmesa_sources
|
||||
# compiled with a device-specific compiler (like CUDA).
|
||||
set(device_sources
|
||||
CanvasRayTracer.cxx
|
||||
ConnectivityProxy.cxx
|
||||
raytracing/BoundingVolumeHierarchy.cxx
|
||||
raytracing/Camera.cxx
|
||||
raytracing/ChannelBuffer.cxx
|
||||
raytracing/RayTracer.cxx
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <vtkm/exec/ExecutionWholeArray.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
@ -85,6 +86,101 @@ struct ClearBuffersInvokeFunctor
|
||||
}
|
||||
};
|
||||
|
||||
class SurfaceConverter : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::Float32 Proj22;
|
||||
vtkm::Float32 Proj23;
|
||||
vtkm::Float32 Proj32;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
SurfaceConverter(const vtkm::Matrix<vtkm::Float32, 4, 4> projMat)
|
||||
{
|
||||
Proj22 = projMat[2][2];
|
||||
Proj23 = projMat[2][3];
|
||||
Proj32 = projMat[3][2];
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, FieldIn<>, ExecObject, ExecObject);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, WorkIndex);
|
||||
template <typename Precision, typename ColorPortalType>
|
||||
VTKM_EXEC void operator()(
|
||||
const vtkm::Id& pixelIndex,
|
||||
ColorPortalType& colorBufferIn,
|
||||
const Precision& inDepth,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>& depthBuffer,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Float32, 4>>& colorBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
vtkm::Float32 depth = (Proj22 + Proj23 / (-static_cast<vtkm::Float32>(inDepth))) / Proj32;
|
||||
depth = 0.5f * depth + 0.5f;
|
||||
vtkm::Vec<vtkm::Float32, 4> color;
|
||||
color[0] = static_cast<vtkm::Float32>(colorBufferIn.Get(index * 4 + 0));
|
||||
color[1] = static_cast<vtkm::Float32>(colorBufferIn.Get(index * 4 + 1));
|
||||
color[2] = static_cast<vtkm::Float32>(colorBufferIn.Get(index * 4 + 2));
|
||||
color[3] = static_cast<vtkm::Float32>(colorBufferIn.Get(index * 4 + 3));
|
||||
depthBuffer.Set(pixelIndex, depth);
|
||||
colorBuffer.Set(pixelIndex, color);
|
||||
}
|
||||
}; //class SurfaceConverter
|
||||
|
||||
template <typename Precision>
|
||||
struct WriteFunctor
|
||||
{
|
||||
protected:
|
||||
vtkm::rendering::CanvasRayTracer* Canvas;
|
||||
const vtkm::cont::ArrayHandle<Precision>& Distances;
|
||||
const vtkm::cont::ArrayHandle<Precision>& Colors;
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& PixelIds;
|
||||
const vtkm::rendering::Camera& CameraView;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
WriteFunctor(vtkm::rendering::CanvasRayTracer* canvas,
|
||||
const vtkm::cont::ArrayHandle<Precision>& distances,
|
||||
const vtkm::cont::ArrayHandle<Precision>& colors,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::rendering::Camera& camera)
|
||||
: Canvas(canvas)
|
||||
, Distances(distances)
|
||||
, Colors(colors)
|
||||
, PixelIds(pixelIds)
|
||||
, CameraView(camera)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT bool operator()(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::worklet::DispatcherMapField<SurfaceConverter, Device>(
|
||||
SurfaceConverter(
|
||||
this->CameraView.CreateProjectionMatrix(Canvas->GetWidth(), Canvas->GetHeight())))
|
||||
.Invoke(
|
||||
PixelIds,
|
||||
Colors,
|
||||
Distances,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>(Canvas->GetDepthBuffer()),
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Float32, 4>>(Canvas->GetColorBuffer()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_CONT void WriteToCanvas(const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::cont::ArrayHandle<Precision>& distances,
|
||||
const vtkm::cont::ArrayHandle<Precision>& colors,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
vtkm::rendering::CanvasRayTracer* canvas)
|
||||
{
|
||||
WriteFunctor<Precision> functor(canvas, distances, colors, pixelIds, camera);
|
||||
|
||||
vtkm::cont::TryExecute(functor);
|
||||
|
||||
//Force the transfer so the vectors contain data from device
|
||||
canvas->GetColorBuffer().GetPortalControl().Get(0);
|
||||
canvas->GetDepthBuffer().GetPortalControl().Get(0);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
CanvasRayTracer::CanvasRayTracer(vtkm::Id width, vtkm::Id height)
|
||||
@ -119,6 +215,22 @@ void CanvasRayTracer::Clear()
|
||||
this->GetBackgroundColor(), this->GetColorBuffer(), this->GetDepthBuffer()));
|
||||
}
|
||||
|
||||
void CanvasRayTracer::WriteToCanvas(const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float32>& distances,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float32>& colors,
|
||||
const vtkm::rendering::Camera& camera)
|
||||
{
|
||||
internal::WriteToCanvas(pixelIds, distances, colors, camera, this);
|
||||
}
|
||||
|
||||
void CanvasRayTracer::WriteToCanvas(const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& distances,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& colors,
|
||||
const vtkm::rendering::Camera& camera)
|
||||
{
|
||||
internal::WriteToCanvas(pixelIds, distances, colors, camera, this);
|
||||
}
|
||||
|
||||
vtkm::rendering::Canvas* CanvasRayTracer::NewCopy() const
|
||||
{
|
||||
return new vtkm::rendering::CanvasRayTracer(*this);
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
@ -46,6 +45,16 @@ public:
|
||||
|
||||
vtkm::rendering::Canvas* NewCopy() const VTKM_OVERRIDE;
|
||||
|
||||
void WriteToCanvas(const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float32>& distances,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float32>& colors,
|
||||
const vtkm::rendering::Camera& camera);
|
||||
|
||||
void WriteToCanvas(const vtkm::cont::ArrayHandle<vtkm::Id>& pixelIds,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& distances,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float64>& colors,
|
||||
const vtkm::rendering::Camera& camera);
|
||||
|
||||
void AddLine(const vtkm::Vec<vtkm::Float64, 2>& point0,
|
||||
const vtkm::Vec<vtkm::Float64, 2>& point1,
|
||||
vtkm::Float32 linewidth,
|
||||
@ -55,6 +64,7 @@ public:
|
||||
const vtkm::rendering::ColorTable& colorTable,
|
||||
bool horizontal) const VTKM_OVERRIDE;
|
||||
|
||||
|
||||
void AddText(const vtkm::Vec<vtkm::Float32, 2>& position,
|
||||
vtkm::Float32 scale,
|
||||
vtkm::Float32 angle,
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -80,6 +82,11 @@ bool ColorTable::GetSmooth() const
|
||||
return this->Internals->Smooth;
|
||||
}
|
||||
|
||||
void ColorTable::SetSmooth(bool smooth)
|
||||
{
|
||||
this->Internals->Smooth = smooth;
|
||||
}
|
||||
|
||||
void ColorTable::Sample(int numSamples,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colors) const
|
||||
{
|
||||
@ -220,6 +227,28 @@ void ColorTable::Clear()
|
||||
this->Internals->Smooth = false;
|
||||
}
|
||||
|
||||
ColorTable ColorTable::CorrectOpacity(const vtkm::Float32& factor) const
|
||||
{
|
||||
ColorTable corrected;
|
||||
corrected.SetSmooth(this->Internals->Smooth);
|
||||
size_t rgbSize = this->Internals->RGBPoints.size();
|
||||
for (size_t i = 0; i < rgbSize; ++i)
|
||||
{
|
||||
detail::ColorControlPoint point = this->Internals->RGBPoints.at(i);
|
||||
corrected.AddControlPoint(point.Position, point.RGBA);
|
||||
}
|
||||
|
||||
size_t alphaSize = this->Internals->AlphaPoints.size();
|
||||
for (size_t i = 0; i < alphaSize; ++i)
|
||||
{
|
||||
detail::AlphaControlPoint point = this->Internals->AlphaPoints.at(i);
|
||||
vtkm::Float32 alpha = 1.f - vtkm::Pow((1.f - point.AlphaValue), factor);
|
||||
corrected.AddAlphaControlPoint(point.Position, alpha);
|
||||
}
|
||||
|
||||
return corrected;
|
||||
}
|
||||
|
||||
void ColorTable::Reverse()
|
||||
{
|
||||
std::shared_ptr<detail::ColorTableInternals> oldInternals = this->Internals;
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
|
||||
bool GetSmooth() const;
|
||||
|
||||
void SetSmooth(bool smooth);
|
||||
|
||||
void Sample(int numSamples, vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colors) const;
|
||||
|
||||
vtkm::rendering::Color MapRGB(vtkm::Float32 scalar) const;
|
||||
@ -72,6 +74,8 @@ public:
|
||||
|
||||
void Reverse();
|
||||
|
||||
ColorTable CorrectOpacity(const vtkm::Float32& factor) const;
|
||||
|
||||
void AddControlPoint(vtkm::Float32 position, const vtkm::rendering::Color& color);
|
||||
|
||||
void AddControlPoint(vtkm::Float32 position,
|
||||
|
341
vtkm/rendering/ConnectivityProxy.cxx
Normal file
341
vtkm/rendering/ConnectivityProxy.cxx
Normal file
@ -0,0 +1,341 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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 <cstdlib>
|
||||
#include <typeinfo>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/ConnectivityProxy.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
#include <vtkm/rendering/raytracing/ConnectivityTracerFactory.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
struct ConnectivityProxy::InternalsType
|
||||
{
|
||||
protected:
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorMapType;
|
||||
typedef vtkm::rendering::raytracing::ConnectivityBase BaseType;
|
||||
|
||||
BaseType* Tracer;
|
||||
vtkm::cont::Field ScalarField;
|
||||
vtkm::cont::Field EmissionField;
|
||||
vtkm::cont::DynamicCellSet Cells;
|
||||
vtkm::cont::CoordinateSystem Coords;
|
||||
RenderMode Mode;
|
||||
vtkm::Bounds SpatialBounds;
|
||||
ColorMapType ColorMap;
|
||||
vtkm::cont::DataSet Dataset;
|
||||
vtkm::Range ScalarRange;
|
||||
|
||||
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(Device());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
InternalsType(vtkm::cont::DataSet& dataSet)
|
||||
{
|
||||
Dataset = dataSet;
|
||||
Cells = dataSet.GetCellSet();
|
||||
Coords = dataSet.GetCoordinateSystem();
|
||||
Mode = VOLUME_MODE;
|
||||
|
||||
//
|
||||
// Just grab a default scalar field
|
||||
//
|
||||
|
||||
this->SetScalarField(Dataset.GetField(0).GetName());
|
||||
|
||||
Tracer = raytracing::ConnectivityTracerFactory::CreateTracer(Cells, Coords);
|
||||
}
|
||||
|
||||
~InternalsType() { delete Tracer; }
|
||||
|
||||
void SetSampleDistance(const vtkm::Float32& distance)
|
||||
{
|
||||
if (Mode != VOLUME_MODE)
|
||||
{
|
||||
std::cout << "Volume Tracer Error: must set volume mode before setting sample dist\n";
|
||||
return;
|
||||
}
|
||||
Tracer->SetSampleDistance(distance);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void SetRenderMode(RenderMode mode) { Mode = mode; }
|
||||
|
||||
VTKM_CONT
|
||||
RenderMode GetRenderMode() { return Mode; }
|
||||
|
||||
VTKM_CONT
|
||||
void SetScalarField(const std::string& fieldName)
|
||||
{
|
||||
ScalarField = Dataset.GetField(fieldName);
|
||||
const vtkm::cont::ArrayHandle<vtkm::Range> range = this->ScalarField.GetRange();
|
||||
ScalarRange = range.GetPortalConstControl().Get(0);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void SetColorMap(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colormap)
|
||||
{
|
||||
Tracer->SetColorMap(colormap);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void SetCompositeBackground(bool on) { Tracer->SetCompositeBackground(on); }
|
||||
|
||||
VTKM_CONT
|
||||
void SetEmissionField(const std::string& fieldName)
|
||||
{
|
||||
if (Mode != ENERGY_MODE)
|
||||
{
|
||||
std::cout << "Volume Tracer Error: must set energy mode before setting emission field\n";
|
||||
return;
|
||||
}
|
||||
|
||||
EmissionField = Dataset.GetField(fieldName);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Bounds GetSpatialBounds() const { return SpatialBounds; }
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Range GetScalarRange() const { return ScalarRange; }
|
||||
|
||||
VTKM_CONT
|
||||
void SetScalarRange(const vtkm::Range& range) { ScalarRange = range; }
|
||||
|
||||
VTKM_CONT
|
||||
void Trace(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays)
|
||||
{
|
||||
|
||||
if (Mode == VOLUME_MODE)
|
||||
{
|
||||
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tracer->SetEnergyData(this->ScalarField, rays.Buffers.at(0).GetNumChannels());
|
||||
}
|
||||
|
||||
Tracer->Trace(rays);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Trace(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays)
|
||||
{
|
||||
if (Mode == VOLUME_MODE)
|
||||
{
|
||||
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tracer->SetEnergyData(this->ScalarField, rays.Buffers.at(0).GetNumChannels());
|
||||
}
|
||||
Tracer->Trace(rays);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Trace(const vtkm::rendering::Camera& camera, vtkm::rendering::CanvasRayTracer* canvas)
|
||||
{
|
||||
|
||||
if (canvas == NULL)
|
||||
{
|
||||
std::cout << "Conn proxy: canvas is NULL\n";
|
||||
return;
|
||||
}
|
||||
vtkm::rendering::raytracing::Camera rayCamera;
|
||||
rayCamera.SetParameters(camera, *canvas);
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
|
||||
rayCamera.CreateRays(rays, this->Coords);
|
||||
|
||||
|
||||
if (Mode == VOLUME_MODE)
|
||||
{
|
||||
Tracer->SetVolumeData(this->ScalarField, this->ScalarRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "ENGERY MODE Not implementedd yet\n";
|
||||
}
|
||||
|
||||
Tracer->Trace(rays);
|
||||
|
||||
canvas->WriteToCanvas(rays.PixelIdx, rays.Distance, rays.Buffers.at(0).Buffer, camera);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
ConnectivityProxy::ConnectivityProxy(vtkm::cont::DataSet& dataSet)
|
||||
: Internals(new InternalsType(dataSet))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ConnectivityProxy::ConnectivityProxy(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField)
|
||||
{
|
||||
vtkm::cont::DataSet dataset;
|
||||
|
||||
dataset.AddCellSet(cellset);
|
||||
dataset.AddCoordinateSystem(coords);
|
||||
dataset.AddField(scalarField);
|
||||
|
||||
Internals = std::shared_ptr<InternalsType>(new InternalsType(dataset));
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ConnectivityProxy::~ConnectivityProxy()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
ConnectivityProxy::ConnectivityProxy()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetSampleDistance(const vtkm::Float32& distance)
|
||||
{
|
||||
Internals->SetSampleDistance(distance);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetRenderMode(RenderMode mode)
|
||||
{
|
||||
Internals->SetRenderMode(mode);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetScalarField(const std::string& fieldName)
|
||||
{
|
||||
Internals->SetScalarField(fieldName);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetColorMap(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colormap)
|
||||
{
|
||||
Internals->SetColorMap(colormap);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetEmissionField(const std::string& fieldName)
|
||||
{
|
||||
Internals->SetEmissionField(fieldName);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Bounds ConnectivityProxy::GetSpatialBounds()
|
||||
{
|
||||
return Internals->GetSpatialBounds();
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Range ConnectivityProxy::GetScalarRange()
|
||||
{
|
||||
return Internals->GetScalarRange();
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetCompositeBackground(bool on)
|
||||
{
|
||||
return Internals->SetCompositeBackground(on);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::SetScalarRange(const vtkm::Range& range)
|
||||
{
|
||||
Internals->SetScalarRange(range);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::Trace(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays)
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
logger->OpenLogEntry("connectivity_trace_64");
|
||||
if (Internals->GetRenderMode() == VOLUME_MODE)
|
||||
{
|
||||
logger->AddLogData("volume_mode", "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->AddLogData("volume_mode", "false");
|
||||
}
|
||||
|
||||
Internals->Trace(rays);
|
||||
logger->CloseLogEntry(-1.0);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::Trace(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays)
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
logger->OpenLogEntry("connectivity_trace_32");
|
||||
if (Internals->GetRenderMode() == VOLUME_MODE)
|
||||
{
|
||||
logger->AddLogData("volume_mode", "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->AddLogData("volume_mode", "false");
|
||||
}
|
||||
|
||||
Internals->Trace(rays);
|
||||
|
||||
logger->CloseLogEntry(-1.0);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void ConnectivityProxy::Trace(const vtkm::rendering::Camera& camera,
|
||||
vtkm::rendering::CanvasRayTracer* canvas)
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
logger->OpenLogEntry("connectivity_trace_32");
|
||||
logger->AddLogData("volume_mode", "true");
|
||||
|
||||
Internals->Trace(camera, canvas);
|
||||
|
||||
logger->CloseLogEntry(-1.0);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering
|
81
vtkm/rendering/ConnectivityProxy.h
Normal file
81
vtkm/rendering/ConnectivityProxy.h
Normal file
@ -0,0 +1,81 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_ConnectivityProxy_h
|
||||
#define vtk_m_rendering_ConnectivityProxy_h
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
class VTKM_RENDERING_EXPORT ConnectivityProxy
|
||||
{
|
||||
public:
|
||||
ConnectivityProxy(vtkm::cont::DataSet& dataset);
|
||||
ConnectivityProxy(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField);
|
||||
~ConnectivityProxy();
|
||||
enum RenderMode
|
||||
{
|
||||
VOLUME_MODE,
|
||||
ENERGY_MODE
|
||||
};
|
||||
|
||||
void SetRenderMode(RenderMode mode);
|
||||
void SetSampleDistance(const vtkm::Float32&);
|
||||
void SetCanvas(vtkm::rendering::Canvas* canvas);
|
||||
void SetScalarField(const std::string& fieldName);
|
||||
void SetEmissionField(const std::string& fieldName);
|
||||
void SetCamera(const vtkm::rendering::Camera& camera);
|
||||
void SetScalarRange(const vtkm::Range& range);
|
||||
void SetColorMap(vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colormap);
|
||||
void SetCompositeBackground(bool on);
|
||||
|
||||
vtkm::Bounds GetSpatialBounds();
|
||||
vtkm::Range GetScalarRange();
|
||||
|
||||
void Trace(const vtkm::rendering::Camera& camera, vtkm::rendering::CanvasRayTracer* canvas);
|
||||
void Trace(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays);
|
||||
void Trace(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays);
|
||||
|
||||
protected:
|
||||
struct InternalsType;
|
||||
struct BoundsFunctor;
|
||||
std::shared_ptr<InternalsType> Internals;
|
||||
|
||||
private:
|
||||
// Do not allow the default constructor
|
||||
ConnectivityProxy();
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
#endif //vtk_m_rendering_SceneRendererVolume_h
|
107
vtkm/rendering/MapperConnectivity.cxx
Normal file
107
vtkm/rendering/MapperConnectivity.cxx
Normal file
@ -0,0 +1,107 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/ConnectivityProxy.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
#include <vtkm/rendering/MapperConnectivity.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/ConnectivityTracerFactory.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
VTKM_CONT
|
||||
MapperConnectivity::MapperConnectivity()
|
||||
{
|
||||
CanvasRT = NULL;
|
||||
SampleDistance = -1;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
MapperConnectivity::~MapperConnectivity()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void MapperConnectivity::SetSampleDistance(const vtkm::Float32& distance)
|
||||
{
|
||||
SampleDistance = distance;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void MapperConnectivity::SetCanvas(Canvas* canvas)
|
||||
{
|
||||
if (canvas != NULL)
|
||||
{
|
||||
|
||||
CanvasRT = dynamic_cast<CanvasRayTracer*>(canvas);
|
||||
if (CanvasRT == NULL)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Volume Render: bad canvas type. Must be CanvasRayTracer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::rendering::Canvas* MapperConnectivity::GetCanvas() const
|
||||
{
|
||||
return CanvasRT;
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
void MapperConnectivity::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::rendering::ColorTable& vtkmNotUsed(colorTable),
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& vtkmNotUsed(scalarRange))
|
||||
{
|
||||
vtkm::rendering::ConnectivityProxy tracerProxy(cellset, coords, scalarField);
|
||||
if (SampleDistance != -1.f)
|
||||
{
|
||||
tracerProxy.SetSampleDistance(SampleDistance);
|
||||
}
|
||||
tracerProxy.SetColorMap(ColorMap);
|
||||
tracerProxy.Trace(camera, CanvasRT);
|
||||
}
|
||||
|
||||
void MapperConnectivity::StartScene()
|
||||
{
|
||||
// Nothing needs to be done.
|
||||
}
|
||||
|
||||
void MapperConnectivity::EndScene()
|
||||
{
|
||||
// Nothing needs to be done.
|
||||
}
|
||||
|
||||
vtkm::rendering::Mapper* MapperConnectivity::NewCopy() const
|
||||
{
|
||||
return new vtkm::rendering::MapperConnectivity(*this);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering
|
64
vtkm/rendering/MapperConnectivity.h
Normal file
64
vtkm/rendering/MapperConnectivity.h
Normal file
@ -0,0 +1,64 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_MapperConnectivity_h
|
||||
#define vtk_m_rendering_MapperConnectivity_h
|
||||
|
||||
#include <cstdlib>
|
||||
#include <typeinfo>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
#include <vtkm/rendering/View.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
class VTKM_RENDERING_EXPORT MapperConnectivity : public Mapper
|
||||
{
|
||||
public:
|
||||
MapperConnectivity();
|
||||
|
||||
~MapperConnectivity();
|
||||
void SetSampleDistance(const vtkm::Float32&);
|
||||
void SetCanvas(vtkm::rendering::Canvas* canvas) VTKM_OVERRIDE;
|
||||
virtual vtkm::rendering::Canvas* GetCanvas() const VTKM_OVERRIDE;
|
||||
|
||||
virtual void RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::rendering::ColorTable&, //colorTable
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange) VTKM_OVERRIDE;
|
||||
|
||||
virtual void StartScene() VTKM_OVERRIDE;
|
||||
virtual void EndScene() VTKM_OVERRIDE;
|
||||
|
||||
vtkm::rendering::Mapper* NewCopy() const VTKM_OVERRIDE;
|
||||
void CreateDefaultView();
|
||||
|
||||
protected:
|
||||
vtkm::Float32 SampleDistance;
|
||||
CanvasRayTracer* CanvasRT;
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
#endif //vtk_m_rendering_SceneRendererVolume_h
|
@ -26,6 +26,7 @@
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/internal/RunTriangulator.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracer.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -36,41 +37,15 @@ namespace rendering
|
||||
struct MapperRayTracer::InternalsType
|
||||
{
|
||||
vtkm::rendering::CanvasRayTracer* Canvas;
|
||||
std::shared_ptr<vtkm::cont::internal::SimplePolymorphicContainerBase> RayTracerContainer;
|
||||
vtkm::rendering::raytracing::RayTracer Tracer;
|
||||
vtkm::rendering::raytracing::Camera RayCamera;
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
|
||||
|
||||
VTKM_CONT
|
||||
InternalsType()
|
||||
: Canvas(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT vtkm::rendering::raytracing::RayTracer<Device>* GetRayTracer(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
typedef vtkm::rendering::raytracing::RayTracer<Device> RayTracerType;
|
||||
typedef vtkm::cont::internal::SimplePolymorphicContainer<RayTracerType> ContainerType;
|
||||
RayTracerType* tracer = nullptr;
|
||||
if (this->RayTracerContainer)
|
||||
{
|
||||
ContainerType* container = dynamic_cast<ContainerType*>(this->RayTracerContainer.get());
|
||||
if (container)
|
||||
{
|
||||
tracer = &container->Item;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracer == nullptr)
|
||||
{
|
||||
ContainerType* container =
|
||||
new vtkm::cont::internal::SimplePolymorphicContainer<RayTracerType>;
|
||||
tracer = &container->Item;
|
||||
this->RayTracerContainer.reset(container);
|
||||
}
|
||||
|
||||
return tracer;
|
||||
}
|
||||
};
|
||||
|
||||
MapperRayTracer::MapperRayTracer()
|
||||
@ -103,60 +78,6 @@ vtkm::rendering::Canvas* MapperRayTracer::GetCanvas() const
|
||||
return this->Internals->Canvas;
|
||||
}
|
||||
|
||||
struct MapperRayTracer::RenderFunctor
|
||||
{
|
||||
vtkm::rendering::MapperRayTracer* Self;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> TriangleIndices;
|
||||
vtkm::Id NumberOfTriangles;
|
||||
vtkm::cont::CoordinateSystem Coordinates;
|
||||
vtkm::cont::Field ScalarField;
|
||||
vtkm::rendering::Camera Camera;
|
||||
vtkm::Range ScalarRange;
|
||||
|
||||
VTKM_CONT
|
||||
RenderFunctor(vtkm::rendering::MapperRayTracer* self,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
|
||||
vtkm::Id numberOfTriangles,
|
||||
const vtkm::cont::CoordinateSystem& coordinates,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange)
|
||||
: Self(self)
|
||||
, TriangleIndices(indices)
|
||||
, NumberOfTriangles(numberOfTriangles)
|
||||
, Coordinates(coordinates)
|
||||
, ScalarField(scalarField)
|
||||
, Camera(camera)
|
||||
, ScalarRange(scalarRange)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
vtkm::rendering::raytracing::RayTracer<Device>* tracer =
|
||||
this->Self->Internals->GetRayTracer(Device());
|
||||
|
||||
tracer->GetCamera().SetParameters(this->Camera, *this->Self->Internals->Canvas);
|
||||
|
||||
vtkm::Bounds dataBounds = this->Coordinates.GetBounds();
|
||||
|
||||
tracer->SetData(this->Coordinates.GetData(),
|
||||
this->TriangleIndices,
|
||||
this->ScalarField,
|
||||
this->NumberOfTriangles,
|
||||
this->ScalarRange,
|
||||
dataBounds);
|
||||
tracer->SetColorMap(this->Self->ColorMap);
|
||||
tracer->SetBackgroundColor(this->Self->Internals->Canvas->GetBackgroundColor().Components);
|
||||
tracer->Render(this->Self->Internals->Canvas);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void MapperRayTracer::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
@ -164,12 +85,41 @@ void MapperRayTracer::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
logger->OpenLogEntry("mapper_ray_tracer");
|
||||
vtkm::cont::Timer<> tot_timer;
|
||||
vtkm::cont::Timer<> timer;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> indices;
|
||||
vtkm::Id numberOfTriangles;
|
||||
vtkm::rendering::internal::RunTriangulator(cellset, indices, numberOfTriangles);
|
||||
|
||||
RenderFunctor functor(this, indices, numberOfTriangles, coords, scalarField, camera, scalarRange);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
vtkm::rendering::internal::RunTriangulator(cellset, indices, numberOfTriangles);
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("triangulator", time);
|
||||
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);
|
||||
|
||||
vtkm::Bounds dataBounds = coords.GetBounds();
|
||||
|
||||
this->Internals->Tracer.SetData(
|
||||
coords.GetData(), indices, scalarField, numberOfTriangles, scalarRange, dataBounds);
|
||||
|
||||
this->Internals->Tracer.SetColorMap(this->ColorMap);
|
||||
this->Internals->Tracer.SetBackgroundColor(
|
||||
this->Internals->Canvas->GetBackgroundColor().Components);
|
||||
this->Internals->Tracer.Render(this->Internals->Rays);
|
||||
|
||||
timer.Reset();
|
||||
this->Internals->Canvas->WriteToCanvas(this->Internals->Rays.PixelIdx,
|
||||
this->Internals->Rays.Distance,
|
||||
this->Internals->Rays.Buffers.at(0).Buffer,
|
||||
camera);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("write_to_canvas", time);
|
||||
time = tot_timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
|
||||
void MapperRayTracer::StartScene()
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include <vtkm/rendering/MapperVolume.h>
|
||||
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/cont/internal/SimplePolymorphicContainer.h>
|
||||
|
||||
@ -29,8 +28,10 @@
|
||||
#include <vtkm/rendering/internal/RunTriangulator.h>
|
||||
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/VolumeRendererStructured.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <typeinfo>
|
||||
|
||||
#define DEFAULT_SAMPLE_DISTANCE -1.f
|
||||
@ -45,8 +46,6 @@ struct MapperVolume::InternalsType
|
||||
vtkm::rendering::CanvasRayTracer* Canvas;
|
||||
vtkm::Float32 SampleDistance;
|
||||
bool CompositeBackground;
|
||||
vtkm::cont::RuntimeDeviceTracker DeviceTracker;
|
||||
std::shared_ptr<vtkm::cont::internal::SimplePolymorphicContainerBase> RayTracerContainer;
|
||||
|
||||
VTKM_CONT
|
||||
InternalsType()
|
||||
@ -55,34 +54,6 @@ struct MapperVolume::InternalsType
|
||||
, CompositeBackground(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT vtkm::rendering::raytracing::VolumeRendererStructured<Device>* GetRayTracer(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
typedef vtkm::rendering::raytracing::VolumeRendererStructured<Device> RayTracerType;
|
||||
typedef vtkm::cont::internal::SimplePolymorphicContainer<RayTracerType> ContainerType;
|
||||
RayTracerType* tracer = nullptr;
|
||||
if (this->RayTracerContainer)
|
||||
{
|
||||
ContainerType* container = dynamic_cast<ContainerType*>(this->RayTracerContainer.get());
|
||||
if (container)
|
||||
{
|
||||
tracer = &container->Item;
|
||||
}
|
||||
}
|
||||
|
||||
if (tracer == nullptr)
|
||||
{
|
||||
ContainerType* container =
|
||||
new vtkm::cont::internal::SimplePolymorphicContainer<RayTracerType>;
|
||||
tracer = &container->Item;
|
||||
this->RayTracerContainer.reset(container);
|
||||
}
|
||||
|
||||
return tracer;
|
||||
}
|
||||
};
|
||||
|
||||
MapperVolume::MapperVolume()
|
||||
@ -99,6 +70,7 @@ void MapperVolume::SetCanvas(vtkm::rendering::Canvas* canvas)
|
||||
if (canvas != nullptr)
|
||||
{
|
||||
this->Internals->Canvas = dynamic_cast<CanvasRayTracer*>(canvas);
|
||||
|
||||
if (this->Internals->Canvas == nullptr)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Ray Tracer: bad canvas type. Must be CanvasRayTracer");
|
||||
@ -115,59 +87,6 @@ vtkm::rendering::Canvas* MapperVolume::GetCanvas() const
|
||||
return this->Internals->Canvas;
|
||||
}
|
||||
|
||||
struct MapperVolume::RenderFunctor
|
||||
{
|
||||
vtkm::rendering::MapperVolume* Self;
|
||||
vtkm::cont::CellSetStructured<3> CellSet;
|
||||
vtkm::cont::CoordinateSystem Coordinates;
|
||||
vtkm::cont::Field ScalarField;
|
||||
vtkm::rendering::Camera Camera;
|
||||
vtkm::Range ScalarRange;
|
||||
|
||||
VTKM_CONT
|
||||
RenderFunctor(vtkm::rendering::MapperVolume* self,
|
||||
const vtkm::cont::CellSetStructured<3> cellSet,
|
||||
const vtkm::cont::CoordinateSystem& coordinates,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange)
|
||||
: Self(self)
|
||||
, CellSet(cellSet)
|
||||
, Coordinates(coordinates)
|
||||
, ScalarField(scalarField)
|
||||
, Camera(camera)
|
||||
, ScalarRange(scalarRange)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
vtkm::rendering::raytracing::VolumeRendererStructured<Device>* tracer =
|
||||
this->Self->Internals->GetRayTracer(Device());
|
||||
|
||||
tracer->GetCamera().SetParameters(this->Camera, *this->Self->Internals->Canvas);
|
||||
// Check to see of the sample distance was set
|
||||
if (this->Self->Internals->SampleDistance != DEFAULT_SAMPLE_DISTANCE)
|
||||
{
|
||||
tracer->SetSampleDistance(this->Self->Internals->SampleDistance);
|
||||
}
|
||||
|
||||
tracer->SetCompositeBackground(this->Self->Internals->CompositeBackground);
|
||||
vtkm::Bounds dataBounds = this->Coordinates.GetBounds();
|
||||
|
||||
tracer->SetData(
|
||||
this->Coordinates, this->ScalarField, dataBounds, this->CellSet, this->ScalarRange);
|
||||
tracer->SetColorMap(this->Self->ColorMap);
|
||||
tracer->SetBackgroundColor(this->Self->Internals->Canvas->GetBackgroundColor().Components);
|
||||
tracer->Render(this->Self->Internals->Canvas);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void MapperVolume::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
@ -177,20 +96,49 @@ void MapperVolume::RenderCells(const vtkm::cont::DynamicCellSet& cellset,
|
||||
{
|
||||
if (!cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
|
||||
{
|
||||
std::cerr << "ERROR cell set type not currently supported\n";
|
||||
std::stringstream msg;
|
||||
std::string theType = typeid(cellset).name();
|
||||
std::cerr << "Type : " << theType << std::endl;
|
||||
msg << "Mapper volume: cell set type not currently supported\n";
|
||||
msg << "Type : " << theType << std::endl;
|
||||
throw vtkm::cont::ErrorBadValue(msg.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderFunctor functor(this,
|
||||
cellset.Cast<vtkm::cont::CellSetStructured<3>>(),
|
||||
coords,
|
||||
scalarField,
|
||||
camera,
|
||||
scalarRange);
|
||||
vtkm::cont::TryExecute(
|
||||
functor, this->Internals->DeviceTracker, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
logger->OpenLogEntry("mapper_volume");
|
||||
vtkm::cont::Timer<> tot_timer;
|
||||
vtkm::cont::Timer<> timer;
|
||||
|
||||
vtkm::rendering::raytracing::VolumeRendererStructured tracer;
|
||||
|
||||
vtkm::rendering::raytracing::Camera rayCamera;
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
|
||||
|
||||
rayCamera.SetParameters(camera, *this->Internals->Canvas);
|
||||
|
||||
rayCamera.CreateRays(rays, coords);
|
||||
|
||||
rays.Buffers.at(0).InitConst(0.f);
|
||||
|
||||
if (this->Internals->SampleDistance != DEFAULT_SAMPLE_DISTANCE)
|
||||
{
|
||||
tracer.SetSampleDistance(this->Internals->SampleDistance);
|
||||
}
|
||||
|
||||
tracer.SetData(
|
||||
coords, scalarField, cellset.Cast<vtkm::cont::CellSetStructured<3>>(), scalarRange);
|
||||
tracer.SetColorMap(this->ColorMap);
|
||||
tracer.SetBackgroundColor(this->Internals->Canvas->GetBackgroundColor().Components);
|
||||
tracer.Render(rays);
|
||||
|
||||
timer.Reset();
|
||||
this->Internals->Canvas->WriteToCanvas(
|
||||
rays.PixelIdx, rays.Distance, rays.Buffers.at(0).Buffer, camera);
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("write_to_canvas", time);
|
||||
time = tot_timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,6 @@ public:
|
||||
private:
|
||||
struct InternalsType;
|
||||
std::shared_ptr<InternalsType> Internals;
|
||||
|
||||
struct RenderFunctor;
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
|
900
vtkm/rendering/raytracing/BoundingVolumeHierarchy.cxx
Normal file
900
vtkm/rendering/raytracing/BoundingVolumeHierarchy.cxx
Normal file
@ -0,0 +1,900 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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 <math.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
|
||||
#include <vtkm/exec/AtomicArray.h>
|
||||
|
||||
#include <vtkm/rendering/raytracing/BoundingVolumeHierarchy.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/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class LinearBVHBuilder
|
||||
{
|
||||
public:
|
||||
class CountingIterator;
|
||||
class FindAABBs;
|
||||
|
||||
template <typename Device>
|
||||
class GatherFloat32;
|
||||
|
||||
template <typename Device>
|
||||
class GatherVecCast;
|
||||
|
||||
class BVHData;
|
||||
|
||||
template <typename Device>
|
||||
class PropagateAABBs;
|
||||
|
||||
template <typename Device>
|
||||
class TreeBuilder;
|
||||
|
||||
VTKM_CONT
|
||||
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));
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT void RunOnDevice(LinearBVH& linearBVH, Device device);
|
||||
}; // class LinearBVHBuilder
|
||||
|
||||
class LinearBVHBuilder::CountingIterator : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CountingIterator() {}
|
||||
typedef void ControlSignature(FieldOut<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
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() {}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<Vec3RenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8);
|
||||
template <typename PointPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Id, 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]);
|
||||
}
|
||||
}; //class FindAABBs
|
||||
|
||||
template <typename Device>
|
||||
class LinearBVHBuilder::GatherFloat32 : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Float32> FloatArrayHandle;
|
||||
typedef typename FloatArrayHandle::ExecutionTypes<Device>::PortalConst PortalConst;
|
||||
typedef typename FloatArrayHandle::ExecutionTypes<Device>::Portal Portal;
|
||||
PortalConst InputPortal;
|
||||
Portal OutputPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GatherFloat32(const FloatArrayHandle& inputPortal,
|
||||
FloatArrayHandle& outputPortal,
|
||||
const vtkm::Id& size)
|
||||
: InputPortal(inputPortal.PrepareForInput(Device()))
|
||||
{
|
||||
this->OutputPortal = outputPortal.PrepareForOutput(size, Device());
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& outIndex, const vtkm::Id& inIndex) const
|
||||
{
|
||||
OutputPortal.Set(outIndex, InputPortal.Get(inIndex));
|
||||
}
|
||||
}; //class GatherFloat
|
||||
|
||||
template <typename Device>
|
||||
class LinearBVHBuilder::GatherVecCast : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Vec4IdArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef typename Vec4IdArrayHandle::ExecutionTypes<Device>::PortalConst PortalConst;
|
||||
typedef typename Vec4IntArrayHandle::ExecutionTypes<Device>::Portal Portal;
|
||||
|
||||
private:
|
||||
PortalConst InputPortal;
|
||||
Portal OutputPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GatherVecCast(const Vec4IdArrayHandle& inputPortal,
|
||||
Vec4IntArrayHandle& outputPortal,
|
||||
const vtkm::Id& size)
|
||||
: InputPortal(inputPortal.PrepareForInput(Device()))
|
||||
{
|
||||
this->OutputPortal = outputPortal.PrepareForOutput(size, Device());
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& outIndex, const vtkm::Id& inIndex) const
|
||||
{
|
||||
OutputPortal.Set(outIndex, InputPortal.Get(inIndex));
|
||||
}
|
||||
}; //class GatherVec3Id
|
||||
|
||||
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;
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT BVHData(vtkm::Id numPrimitives, Device vtkmNotUsed(device))
|
||||
: 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());
|
||||
mortonCodes.PrepareForOutput(NumPrimitives, Device());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
~BVHData()
|
||||
{
|
||||
//
|
||||
delete xmins;
|
||||
delete ymins;
|
||||
delete zmins;
|
||||
delete xmaxs;
|
||||
delete ymaxs;
|
||||
delete zmaxs;
|
||||
}
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfPrimitives() const { return NumPrimitives; }
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfInnerNodes() const { return InnerNodeCount; }
|
||||
|
||||
private:
|
||||
vtkm::Id NumPrimitives;
|
||||
vtkm::Id InnerNodeCount;
|
||||
|
||||
}; // class BVH
|
||||
|
||||
template <typename Device>
|
||||
class LinearBVHBuilder::PropagateAABBs : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Int8> Int8Handle;
|
||||
typedef typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 2>> Float2ArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 2>> VecInt2Handle;
|
||||
typedef typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 4>> Float4ArrayHandle;
|
||||
|
||||
typedef typename IdArrayHandle::ExecutionTypes<Device>::PortalConst IdConstPortal;
|
||||
typedef typename Float2ArrayHandle::ExecutionTypes<Device>::Portal Float2ArrayPortal;
|
||||
typedef typename VecInt2Handle::ExecutionTypes<Device>::Portal Int2ArrayPortal;
|
||||
typedef typename Int8Handle::ExecutionTypes<Device>::Portal Int8ArrayPortal;
|
||||
typedef typename Float4ArrayHandle::ExecutionTypes<Device>::Portal Float4ArrayPortal;
|
||||
|
||||
Float4ArrayPortal FlatBVH;
|
||||
IdConstPortal Parents;
|
||||
IdConstPortal LeftChildren;
|
||||
IdConstPortal RightChildren;
|
||||
vtkm::Int32 LeafCount;
|
||||
//Int8Handle Counters;
|
||||
//Int8ArrayPortal CountersPortal;
|
||||
vtkm::exec::AtomicArray<vtkm::Int32, Device> Counters;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
PropagateAABBs(IdArrayHandle& parents,
|
||||
IdArrayHandle& leftChildren,
|
||||
IdArrayHandle& rightChildren,
|
||||
vtkm::Int32 leafCount,
|
||||
Float4ArrayHandle flatBVH,
|
||||
const vtkm::exec::AtomicArray<vtkm::Int32, Device>& counters)
|
||||
: Parents(parents.PrepareForInput(Device()))
|
||||
, LeftChildren(leftChildren.PrepareForInput(Device()))
|
||||
, RightChildren(rightChildren.PrepareForInput(Device()))
|
||||
, LeafCount(leafCount)
|
||||
, Counters(counters)
|
||||
|
||||
{
|
||||
this->FlatBVH = flatBVH.PrepareForOutput((LeafCount - 1) * 4, Device());
|
||||
}
|
||||
typedef void ControlSignature(ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject);
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2, _3, _4, _5, _6);
|
||||
template <typename StrorageType>
|
||||
VTKM_EXEC_CONT void operator()(
|
||||
const vtkm::Id workIndex,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& xmin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& ymin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& zmin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& xmax,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& ymax,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& zmax) const
|
||||
{
|
||||
//move up into the inner nodes
|
||||
vtkm::Id currentNode = LeafCount - 1 + workIndex;
|
||||
vtkm::Vec<vtkm::Id, 2> childVector;
|
||||
while (currentNode != 0)
|
||||
{
|
||||
currentNode = Parents.Get(currentNode);
|
||||
|
||||
vtkm::Int32 oldCount = Counters.Add(currentNode, 1);
|
||||
if (oldCount == 0)
|
||||
return;
|
||||
vtkm::Id currentNodeOffset = currentNode * 4;
|
||||
childVector[0] = LeftChildren.Get(currentNode);
|
||||
childVector[1] = RightChildren.Get(currentNode);
|
||||
if (childVector[0] > (LeafCount - 2))
|
||||
{
|
||||
childVector[0] = childVector[0] - LeafCount + 1;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4>
|
||||
first4Vec; // = FlatBVH.Get(currentNode); only this one needs effects this
|
||||
|
||||
first4Vec[0] = xmin.Get(childVector[0]);
|
||||
first4Vec[1] = ymin.Get(childVector[0]);
|
||||
first4Vec[2] = zmin.Get(childVector[0]);
|
||||
first4Vec[3] = xmax.Get(childVector[0]);
|
||||
FlatBVH.Set(currentNodeOffset, first4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[0] = ymax.Get(childVector[0]);
|
||||
second4Vec[1] = zmax.Get(childVector[0]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
childVector[0] = -(childVector[0] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::Id child = childVector[0] * 4;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
|
||||
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
|
||||
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
|
||||
|
||||
cFirst4Vec[0] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
|
||||
cFirst4Vec[1] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
|
||||
cFirst4Vec[2] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
|
||||
cFirst4Vec[3] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
|
||||
FlatBVH.Set(currentNodeOffset, cFirst4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[0] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
|
||||
second4Vec[1] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
|
||||
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
}
|
||||
|
||||
if (childVector[1] > (LeafCount - 2))
|
||||
{
|
||||
childVector[1] = childVector[1] - LeafCount + 1;
|
||||
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
|
||||
second4Vec[2] = xmin.Get(childVector[1]);
|
||||
second4Vec[3] = ymin.Get(childVector[1]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> third4Vec;
|
||||
third4Vec[0] = zmin.Get(childVector[1]);
|
||||
third4Vec[1] = xmax.Get(childVector[1]);
|
||||
third4Vec[2] = ymax.Get(childVector[1]);
|
||||
third4Vec[3] = zmax.Get(childVector[1]);
|
||||
FlatBVH.Set(currentNodeOffset + 2, third4Vec);
|
||||
childVector[1] = -(childVector[1] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
vtkm::Id child = childVector[1] * 4;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
|
||||
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
|
||||
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[2] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
|
||||
second4Vec[3] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
cThird4Vec[0] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
|
||||
cThird4Vec[1] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
|
||||
cThird4Vec[2] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
|
||||
cThird4Vec[3] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
|
||||
FlatBVH.Set(currentNodeOffset + 2, cThird4Vec);
|
||||
}
|
||||
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);
|
||||
vtkm::Int32 rightChild =
|
||||
static_cast<vtkm::Int32>((childVector[1] >= 0) ? childVector[1] * 4 : childVector[1]);
|
||||
memcpy(&fourth4Vec[1], &rightChild, 4);
|
||||
FlatBVH.Set(currentNodeOffset + 3, fourth4Vec);
|
||||
}
|
||||
}
|
||||
}; //class PropagateAABBs
|
||||
|
||||
|
||||
template <typename Device>
|
||||
class LinearBVHBuilder::TreeBuilder : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::UInt32> UIntArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
|
||||
typedef typename UIntArrayHandle::ExecutionTypes<Device>::PortalConst UIntPortalType;
|
||||
typedef typename IdArrayHandle::ExecutionTypes<Device>::Portal IdPortalType;
|
||||
|
||||
private:
|
||||
UIntPortalType MortonCodePortal;
|
||||
IdPortalType ParentPortal;
|
||||
vtkm::Id LeafCount;
|
||||
vtkm::Id InnerCount;
|
||||
//TODO: get instrinsic support
|
||||
VTKM_EXEC
|
||||
inline vtkm::Int32 CountLeadingZeros(vtkm::UInt32& x) const
|
||||
{
|
||||
vtkm::UInt32 y;
|
||||
vtkm::UInt32 n = 32;
|
||||
y = x >> 16;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 16;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 8;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 8;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 4;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 4;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 2;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 2;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 1;
|
||||
if (y != 0)
|
||||
return vtkm::Int32(n - 2);
|
||||
return vtkm::Int32(n - x);
|
||||
}
|
||||
|
||||
// returns the count of largest shared prefix between
|
||||
// two morton codes. Ties are broken by the indexes
|
||||
// a and b.
|
||||
//
|
||||
// returns count of the largest binary prefix
|
||||
|
||||
VTKM_EXEC
|
||||
inline vtkm::Int32 delta(const vtkm::Int32& a, const vtkm::Int32& b) const
|
||||
{
|
||||
bool tie = false;
|
||||
bool outOfRange = (b < 0 || b > LeafCount - 1);
|
||||
//still make the call but with a valid adderss
|
||||
vtkm::Int32 bb = (outOfRange) ? 0 : b;
|
||||
vtkm::UInt32 aCode = MortonCodePortal.Get(a);
|
||||
vtkm::UInt32 bCode = MortonCodePortal.Get(bb);
|
||||
//use xor to find where they differ
|
||||
vtkm::UInt32 exOr = aCode ^ bCode;
|
||||
tie = (exOr == 0);
|
||||
//break the tie, a and b must always differ
|
||||
exOr = tie ? vtkm::UInt32(a) ^ vtkm::UInt32(bb) : exOr;
|
||||
vtkm::Int32 count = CountLeadingZeros(exOr);
|
||||
if (tie)
|
||||
count += 32;
|
||||
count = (outOfRange) ? -1 : count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
TreeBuilder(const UIntArrayHandle& mortonCodesHandle,
|
||||
IdArrayHandle& parentHandle,
|
||||
const vtkm::Id& leafCount)
|
||||
: MortonCodePortal(mortonCodesHandle.PrepareForInput(Device()))
|
||||
, LeafCount(leafCount)
|
||||
{
|
||||
InnerCount = LeafCount - 1;
|
||||
this->ParentPortal = parentHandle.PrepareForOutput(InnerCount + LeafCount, Device());
|
||||
}
|
||||
typedef void ControlSignature(FieldOut<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& index, vtkm::Id& leftChild, vtkm::Id& rightChild) const
|
||||
{
|
||||
vtkm::Int32 idx = vtkm::Int32(index);
|
||||
//something = MortonCodePortal.Get(index) + 1;
|
||||
//determine range direction
|
||||
vtkm::Int32 d = 0 > (delta(idx, idx + 1) - delta(idx, idx - 1)) ? -1 : 1;
|
||||
|
||||
//find upper bound for the length of the range
|
||||
vtkm::Int32 minDelta = delta(idx, idx - d);
|
||||
vtkm::Int32 lMax = 2;
|
||||
while (delta(idx, idx + lMax * d) > minDelta)
|
||||
lMax *= 2;
|
||||
|
||||
//binary search to find the lower bound
|
||||
vtkm::Int32 l = 0;
|
||||
for (int t = lMax / 2; t >= 1; t /= 2)
|
||||
{
|
||||
if (delta(idx, idx + (l + t) * d) > minDelta)
|
||||
l += t;
|
||||
}
|
||||
|
||||
vtkm::Int32 j = idx + l * d;
|
||||
vtkm::Int32 deltaNode = delta(idx, j);
|
||||
vtkm::Int32 s = 0;
|
||||
vtkm::Float32 divFactor = 2.f;
|
||||
//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))
|
||||
{
|
||||
if (delta(idx, idx + (s + t) * d) > deltaNode)
|
||||
{
|
||||
s += t;
|
||||
}
|
||||
|
||||
if (t == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
vtkm::Int32 split = idx + s * d + vtkm::Min(d, 0);
|
||||
//assign parent/child pointers
|
||||
if (vtkm::Min(idx, j) == split)
|
||||
{
|
||||
//leaf
|
||||
ParentPortal.Set(split + InnerCount, idx);
|
||||
leftChild = split + InnerCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
//inner node
|
||||
ParentPortal.Set(split, idx);
|
||||
leftChild = split;
|
||||
}
|
||||
|
||||
|
||||
if (vtkm::Max(idx, j) == split + 1)
|
||||
{
|
||||
//leaf
|
||||
ParentPortal.Set(split + InnerCount + 1, idx);
|
||||
rightChild = split + InnerCount + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentPortal.Set(split + 1, idx);
|
||||
rightChild = split + 1;
|
||||
}
|
||||
}
|
||||
}; // 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))
|
||||
{
|
||||
//create array of indexes to be sorted with morton codes
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> iterator;
|
||||
iterator.PrepareForOutput(bvh.GetNumberOfPrimitives(), Device());
|
||||
vtkm::worklet::DispatcherMapField<CountingIterator, Device> iteratorDispatcher;
|
||||
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;
|
||||
|
||||
|
||||
tempStorage = new vtkm::cont::ArrayHandle<vtkm::Float32>();
|
||||
//xmins
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.xmins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.xmins;
|
||||
bvh.xmins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.ymins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.ymins;
|
||||
bvh.ymins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//zmins
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.zmins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.zmins;
|
||||
bvh.zmins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//xmaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.xmaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.xmaxs;
|
||||
bvh.xmaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//ymaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.ymaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.ymaxs;
|
||||
bvh.ymaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//zmaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32<Device>, Device>(
|
||||
GatherFloat32<Device>(*bvh.zmaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.zmaxs;
|
||||
bvh.zmaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<GatherVecCast<Device>, Device>(
|
||||
GatherVecCast<Device>(triangleIndices, outputTriangleIndices, arraySize))
|
||||
.Invoke(iterator);
|
||||
delete tempStorage;
|
||||
|
||||
} // method SortAABBs
|
||||
|
||||
// Adding this as a template parameter to allow restricted types and
|
||||
// storage for dynamic coordinate system to limit crazy code bloat and
|
||||
// compile times.
|
||||
//
|
||||
template <typename Device>
|
||||
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;
|
||||
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem coordsHandle = linearBVH.GetCoordsHandle();
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangleIndices = linearBVH.GetTriangles();
|
||||
vtkm::Id numberOfTriangles = linearBVH.GetNumberOfTriangles();
|
||||
|
||||
logger->AddLogData("bvh_num_triangles ", numberOfTriangles);
|
||||
|
||||
const vtkm::Id numBBoxes = numberOfTriangles;
|
||||
BVHData bvh(numBBoxes, device);
|
||||
|
||||
vtkm::cont::Timer<Device> timer;
|
||||
vtkm::worklet::DispatcherMapField<FindAABBs, Device>(FindAABBs())
|
||||
.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());
|
||||
maxExtent[1] =
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.ymaxs, maxExtent[1], MaxValue());
|
||||
maxExtent[2] =
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.zmaxs, maxExtent[2], MaxValue());
|
||||
minExtent[0] =
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.xmins, minExtent[0], MinValue());
|
||||
minExtent[1] =
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.ymins, minExtent[1], MinValue());
|
||||
minExtent[2] =
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(*bvh.zmins, minExtent[2], MinValue());
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("calc_extents", time);
|
||||
timer.Reset();
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> deltaExtent = maxExtent - minExtent;
|
||||
vtkm::Vec<vtkm::Float32, 3> inverseExtent;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
inverseExtent[i] = (deltaExtent[i] == 0.f) ? 0 : 1.f / deltaExtent[i];
|
||||
}
|
||||
|
||||
//Generate the morton codes
|
||||
vtkm::worklet::DispatcherMapField<MortonCodeAABB, Device>(
|
||||
MortonCodeAABB(inverseExtent, minExtent))
|
||||
.Invoke(
|
||||
*bvh.xmins, *bvh.ymins, *bvh.zmins, *bvh.xmaxs, *bvh.ymaxs, *bvh.zmaxs, bvh.mortonCodes);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("morton_codes", time);
|
||||
timer.Reset();
|
||||
|
||||
linearBVH.Allocate(bvh.GetNumberOfPrimitives(), Device());
|
||||
|
||||
SortAABBS(bvh, triangleIndices, linearBVH.LeafNodes, Device());
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("sort_aabbs", time);
|
||||
timer.Reset();
|
||||
|
||||
vtkm::worklet::DispatcherMapField<TreeBuilder<Device>, Device>(
|
||||
TreeBuilder<Device>(bvh.mortonCodes, bvh.parent, bvh.GetNumberOfPrimitives()))
|
||||
.Invoke(bvh.leftChild, bvh.rightChild);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("build_tree", time);
|
||||
timer.Reset();
|
||||
|
||||
const vtkm::Int32 primitiveCount = vtkm::Int32(bvh.GetNumberOfPrimitives());
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Int32> counters;
|
||||
counters.PrepareForOutput(bvh.GetNumberOfPrimitives() - 1, Device());
|
||||
vtkm::Int32 zero = 0;
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Int32>, Device>(MemSet<vtkm::Int32>(zero))
|
||||
.Invoke(counters);
|
||||
vtkm::exec::AtomicArray<vtkm::Int32, Device> atomicCounters(counters);
|
||||
|
||||
|
||||
vtkm::worklet::DispatcherMapField<PropagateAABBs<Device>, Device>(
|
||||
PropagateAABBs<Device>(
|
||||
bvh.parent, bvh.leftChild, bvh.rightChild, primitiveCount, linearBVH.FlatBVH, atomicCounters))
|
||||
.Invoke(vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.xmins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.ymins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.zmins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.xmaxs),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.ymaxs),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.zmaxs));
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("propagate_aabbs", time);
|
||||
|
||||
time = constructTimer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
} //namespace detail
|
||||
|
||||
struct LinearBVH::ConstructFunctor
|
||||
{
|
||||
LinearBVH* Self;
|
||||
VTKM_CONT
|
||||
ConstructFunctor(LinearBVH* self)
|
||||
: Self(self)
|
||||
{
|
||||
}
|
||||
template <typename Device>
|
||||
bool operator()(Device)
|
||||
{
|
||||
Self->ConstructOnDevice(Device());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
LinearBVH::LinearBVH()
|
||||
: IsConstructed(false)
|
||||
, CanConstruct(false){};
|
||||
|
||||
VTKM_CONT
|
||||
LinearBVH::LinearBVH(vtkm::cont::DynamicArrayHandleCoordinateSystem coordsHandle,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles)
|
||||
: CoordsHandle(coordsHandle)
|
||||
, Triangles(triangles)
|
||||
, IsConstructed(false)
|
||||
, CanConstruct(true)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
LinearBVH::LinearBVH(const LinearBVH& other)
|
||||
: FlatBVH(other.FlatBVH)
|
||||
, LeafNodes(other.LeafNodes)
|
||||
, ExtentMin(other.ExtentMin)
|
||||
, ExtentMax(other.ExtentMax)
|
||||
, LeafCount(other.LeafCount)
|
||||
, CoordsHandle(other.CoordsHandle)
|
||||
, Triangles(other.Triangles)
|
||||
, IsConstructed(other.IsConstructed)
|
||||
, CanConstruct(other.CanConstruct)
|
||||
{
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void LinearBVH::Construct()
|
||||
{
|
||||
if (IsConstructed)
|
||||
return;
|
||||
if (!CanConstruct)
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"Linear BVH: coordinates and triangles must be set before calling construct!");
|
||||
ConstructFunctor functor(this);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
IsConstructed = true;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void LinearBVH::SetData(vtkm::cont::DynamicArrayHandleCoordinateSystem coordsHandle,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles)
|
||||
{
|
||||
CoordsHandle = coordsHandle;
|
||||
Triangles = triangles;
|
||||
IsConstructed = false;
|
||||
CanConstruct = true;
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
void LinearBVH::ConstructOnDevice(Device device)
|
||||
{
|
||||
Logger* logger = Logger::GetInstance();
|
||||
vtkm::cont::Timer<Device> timer;
|
||||
logger->OpenLogEntry("bvh");
|
||||
if (!CanConstruct)
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"Linear BVH: coordinates and triangles must be set before calling construct!");
|
||||
if (!IsConstructed)
|
||||
{
|
||||
detail::LinearBVHBuilder builder;
|
||||
builder.RunOnDevice(*this, device);
|
||||
IsConstructed = true;
|
||||
}
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
bool LinearBVH::GetIsConstructed() const
|
||||
{
|
||||
return IsConstructed;
|
||||
}
|
||||
VTKM_CONT
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem LinearBVH::GetCoordsHandle() const
|
||||
{
|
||||
return CoordsHandle;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> LinearBVH::GetTriangles() const
|
||||
{
|
||||
return Triangles;
|
||||
}
|
||||
|
||||
vtkm::Id LinearBVH::GetNumberOfTriangles() const
|
||||
{
|
||||
return Triangles.GetPortalConstControl().GetNumberOfValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
@ -19,25 +19,10 @@
|
||||
//============================================================================
|
||||
#ifndef vtk_m_worklet_BoundingVolumeHierachy_h
|
||||
#define vtk_m_worklet_BoundingVolumeHierachy_h
|
||||
#include <math.h>
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/exec/AtomicArray.h>
|
||||
#include <vtkm/exec/ExecutionWholeArray.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/rendering/raytracing/Worklets.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -45,787 +30,62 @@ namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
//
|
||||
// This is the data structure that is passed to the ray tracer.
|
||||
//
|
||||
//template<typename DeviceAdapter>
|
||||
class LinearBVH
|
||||
class VTKM_RENDERING_EXPORT LinearBVH
|
||||
{
|
||||
|
||||
public:
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> FlatBVH;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> LeafNodes;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> InnerNodesHandle;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> LeafNodesHandle;
|
||||
InnerNodesHandle FlatBVH;
|
||||
LeafNodesHandle LeafNodes;
|
||||
vtkm::Vec<Float32, 3> ExtentMin;
|
||||
vtkm::Vec<Float32, 3> ExtentMax;
|
||||
struct ConstructFunctor;
|
||||
vtkm::Id LeafCount;
|
||||
|
||||
protected:
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem CoordsHandle;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Triangles;
|
||||
bool IsConstructed;
|
||||
bool CanConstruct;
|
||||
|
||||
public:
|
||||
LinearBVH();
|
||||
|
||||
VTKM_CONT
|
||||
LinearBVH() {}
|
||||
LinearBVH(vtkm::cont::DynamicArrayHandleCoordinateSystem coordsHandle,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles);
|
||||
|
||||
VTKM_CONT
|
||||
LinearBVH(const LinearBVH& other);
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void Allocate(const vtkm::Id& leafCount, DeviceAdapter deviceAdapter)
|
||||
{
|
||||
LeafCount = leafCount;
|
||||
LeafNodes.PrepareForOutput(leafCount, deviceAdapter);
|
||||
FlatBVH.PrepareForOutput((leafCount - 1) * 4, deviceAdapter);
|
||||
}
|
||||
VTKM_CONT void Allocate(const vtkm::Id& leafCount, DeviceAdapter deviceAdapter);
|
||||
|
||||
VTKM_CONT
|
||||
void Construct();
|
||||
|
||||
VTKM_CONT
|
||||
void SetData(vtkm::cont::DynamicArrayHandleCoordinateSystem coordsHandle,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> triangles);
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT void ConstructOnDevice(Device device);
|
||||
|
||||
VTKM_CONT
|
||||
bool GetIsConstructed() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem GetCoordsHandle() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> GetTriangles() const;
|
||||
|
||||
vtkm::Id GetNumberOfTriangles() const;
|
||||
}; // class LinearBVH
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
class LinearBVHBuilder
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float64, 3>> Vec3DoubleArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> Vec3FloatArrayHandle;
|
||||
typedef
|
||||
typename Vec3DoubleArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst Point64PortalConst;
|
||||
typedef
|
||||
typename Vec3FloatArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst Point32PortalConst;
|
||||
|
||||
public:
|
||||
class CountingIterator : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CountingIterator() {}
|
||||
typedef void ControlSignature(FieldOut<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& index, vtkm::Id& outId) const { outId = index; }
|
||||
}; //class countingIterator
|
||||
|
||||
class FindAABBs : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
FindAABBs() {}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<Vec3RenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8);
|
||||
template <typename PointPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Id, 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]);
|
||||
}
|
||||
}; //class FindAABBs
|
||||
|
||||
class GatherFloat32 : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Float32> FloatArrayHandle;
|
||||
typedef typename FloatArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst PortalConst;
|
||||
typedef typename FloatArrayHandle::ExecutionTypes<DeviceAdapter>::Portal Portal;
|
||||
|
||||
private:
|
||||
PortalConst InputPortal;
|
||||
Portal OutputPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GatherFloat32(const FloatArrayHandle& inputPortal,
|
||||
FloatArrayHandle& outputPortal,
|
||||
const vtkm::Id& size)
|
||||
: InputPortal(inputPortal.PrepareForInput(DeviceAdapter()))
|
||||
{
|
||||
this->OutputPortal = outputPortal.PrepareForOutput(size, DeviceAdapter());
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& outIndex, const vtkm::Id& inIndex) const
|
||||
{
|
||||
OutputPortal.Set(outIndex, InputPortal.Get(inIndex));
|
||||
}
|
||||
}; //class GatherFloat
|
||||
|
||||
class GatherVecCast : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Vec4IdArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef typename Vec4IdArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst PortalConst;
|
||||
typedef typename Vec4IntArrayHandle::ExecutionTypes<DeviceAdapter>::Portal Portal;
|
||||
|
||||
private:
|
||||
PortalConst InputPortal;
|
||||
Portal OutputPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GatherVecCast(const Vec4IdArrayHandle& inputPortal,
|
||||
Vec4IntArrayHandle& outputPortal,
|
||||
const vtkm::Id& size)
|
||||
: InputPortal(inputPortal.PrepareForInput(DeviceAdapter()))
|
||||
{
|
||||
this->OutputPortal = outputPortal.PrepareForOutput(size, DeviceAdapter());
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& outIndex, const vtkm::Id& inIndex) const
|
||||
{
|
||||
OutputPortal.Set(outIndex, InputPortal.Get(inIndex));
|
||||
}
|
||||
}; //class GatherVec3Id
|
||||
|
||||
class 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
|
||||
BVHData(vtkm::Id numPrimitives)
|
||||
: 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, DeviceAdapter());
|
||||
leftChild.PrepareForOutput(InnerNodeCount, DeviceAdapter());
|
||||
rightChild.PrepareForOutput(InnerNodeCount, DeviceAdapter());
|
||||
mortonCodes.PrepareForOutput(NumPrimitives, DeviceAdapter());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
~BVHData()
|
||||
{
|
||||
//
|
||||
delete xmins;
|
||||
delete ymins;
|
||||
delete zmins;
|
||||
delete xmaxs;
|
||||
delete ymaxs;
|
||||
delete zmaxs;
|
||||
}
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfPrimitives() const { return NumPrimitives; }
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfInnerNodes() const { return InnerNodeCount; }
|
||||
private:
|
||||
vtkm::Id NumPrimitives;
|
||||
vtkm::Id InnerNodeCount;
|
||||
|
||||
}; // class BVH
|
||||
|
||||
class PropagateAABBs : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Int8> Int8Handle;
|
||||
typedef typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 2>> Float2ArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 2>> VecInt2Handle;
|
||||
typedef typename vtkm::cont::ArrayHandle<Vec<vtkm::Float32, 4>> Float4ArrayHandle;
|
||||
|
||||
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IdConstPortal;
|
||||
typedef typename Float2ArrayHandle::ExecutionTypes<DeviceAdapter>::Portal Float2ArrayPortal;
|
||||
typedef typename VecInt2Handle::ExecutionTypes<DeviceAdapter>::Portal Int2ArrayPortal;
|
||||
typedef typename Int8Handle::ExecutionTypes<DeviceAdapter>::Portal Int8ArrayPortal;
|
||||
typedef typename Float4ArrayHandle::ExecutionTypes<DeviceAdapter>::Portal Float4ArrayPortal;
|
||||
|
||||
Float4ArrayPortal FlatBVH;
|
||||
IdConstPortal Parents;
|
||||
IdConstPortal LeftChildren;
|
||||
IdConstPortal RightChildren;
|
||||
vtkm::Int32 LeafCount;
|
||||
//Int8Handle Counters;
|
||||
//Int8ArrayPortal CountersPortal;
|
||||
vtkm::exec::AtomicArray<vtkm::Int32, DeviceAdapter> Counters;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
PropagateAABBs(IdArrayHandle& parents,
|
||||
IdArrayHandle& leftChildren,
|
||||
IdArrayHandle& rightChildren,
|
||||
vtkm::Int32 leafCount,
|
||||
Float4ArrayHandle flatBVH,
|
||||
const vtkm::exec::AtomicArray<vtkm::Int32, DeviceAdapter>& counters)
|
||||
: Parents(parents.PrepareForInput(DeviceAdapter()))
|
||||
, LeftChildren(leftChildren.PrepareForInput(DeviceAdapter()))
|
||||
, RightChildren(rightChildren.PrepareForInput(DeviceAdapter()))
|
||||
, LeafCount(leafCount)
|
||||
, Counters(counters)
|
||||
|
||||
{
|
||||
this->FlatBVH = flatBVH.PrepareForOutput((LeafCount - 1) * 4, DeviceAdapter());
|
||||
}
|
||||
typedef void ControlSignature(ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject,
|
||||
ExecObject);
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2, _3, _4, _5, _6);
|
||||
template <typename StrorageType>
|
||||
VTKM_EXEC_CONT void operator()(
|
||||
const vtkm::Id workIndex,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& xmin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& ymin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& zmin,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& xmax,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& ymax,
|
||||
const vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32, StrorageType>& zmax) const
|
||||
{
|
||||
//move up into the inner nodes
|
||||
vtkm::Id currentNode = LeafCount - 1 + workIndex;
|
||||
vtkm::Vec<vtkm::Id, 2> childVector;
|
||||
while (currentNode != 0)
|
||||
{
|
||||
currentNode = Parents.Get(currentNode);
|
||||
|
||||
vtkm::Int32 oldCount = Counters.Add(currentNode, 1);
|
||||
if (oldCount == 0)
|
||||
return;
|
||||
vtkm::Id currentNodeOffset = currentNode * 4;
|
||||
childVector[0] = LeftChildren.Get(currentNode);
|
||||
childVector[1] = RightChildren.Get(currentNode);
|
||||
if (childVector[0] > (LeafCount - 2))
|
||||
{
|
||||
childVector[0] = childVector[0] - LeafCount + 1;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4>
|
||||
first4Vec; // = FlatBVH.Get(currentNode); only this one needs effects this
|
||||
|
||||
first4Vec[0] = xmin.Get(childVector[0]);
|
||||
first4Vec[1] = ymin.Get(childVector[0]);
|
||||
first4Vec[2] = zmin.Get(childVector[0]);
|
||||
first4Vec[3] = xmax.Get(childVector[0]);
|
||||
FlatBVH.Set(currentNodeOffset, first4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[0] = ymax.Get(childVector[0]);
|
||||
second4Vec[1] = zmax.Get(childVector[0]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
childVector[0] = -(childVector[0] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::Id child = childVector[0] * 4;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
|
||||
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
|
||||
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
|
||||
|
||||
cFirst4Vec[0] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
|
||||
cFirst4Vec[1] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
|
||||
cFirst4Vec[2] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
|
||||
cFirst4Vec[3] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
|
||||
FlatBVH.Set(currentNodeOffset, cFirst4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[0] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
|
||||
second4Vec[1] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
|
||||
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
}
|
||||
|
||||
if (childVector[1] > (LeafCount - 2))
|
||||
{
|
||||
childVector[1] = childVector[1] - LeafCount + 1;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
|
||||
second4Vec[2] = xmin.Get(childVector[1]);
|
||||
second4Vec[3] = ymin.Get(childVector[1]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> third4Vec;
|
||||
third4Vec[0] = zmin.Get(childVector[1]);
|
||||
third4Vec[1] = xmax.Get(childVector[1]);
|
||||
third4Vec[2] = ymax.Get(childVector[1]);
|
||||
third4Vec[3] = zmax.Get(childVector[1]);
|
||||
FlatBVH.Set(currentNodeOffset + 2, third4Vec);
|
||||
childVector[1] = -(childVector[1] + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
vtkm::Id child = childVector[1] * 4;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> cFirst4Vec = FlatBVH.Get(child);
|
||||
vtkm::Vec<vtkm::Float32, 4> cSecond4Vec = FlatBVH.Get(child + 1);
|
||||
vtkm::Vec<vtkm::Float32, 4> cThird4Vec = FlatBVH.Get(child + 2);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> second4Vec = FlatBVH.Get(currentNodeOffset + 1);
|
||||
second4Vec[2] = vtkm::Min(cFirst4Vec[0], cSecond4Vec[2]);
|
||||
second4Vec[3] = vtkm::Min(cFirst4Vec[1], cSecond4Vec[3]);
|
||||
FlatBVH.Set(currentNodeOffset + 1, second4Vec);
|
||||
|
||||
cThird4Vec[0] = vtkm::Min(cFirst4Vec[2], cThird4Vec[0]);
|
||||
cThird4Vec[1] = vtkm::Max(cFirst4Vec[3], cThird4Vec[1]);
|
||||
cThird4Vec[2] = vtkm::Max(cSecond4Vec[0], cThird4Vec[2]);
|
||||
cThird4Vec[3] = vtkm::Max(cSecond4Vec[1], cThird4Vec[3]);
|
||||
FlatBVH.Set(currentNodeOffset + 2, cThird4Vec);
|
||||
}
|
||||
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);
|
||||
vtkm::Int32 rightChild =
|
||||
static_cast<vtkm::Int32>((childVector[1] >= 0) ? childVector[1] * 4 : childVector[1]);
|
||||
memcpy(&fourth4Vec[1], &rightChild, 4);
|
||||
FlatBVH.Set(currentNodeOffset + 3, fourth4Vec);
|
||||
}
|
||||
}
|
||||
}; //class PropagateAABBs
|
||||
|
||||
class MortonCodeAABB : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
// (1.f / dx),(1.f / dy), (1.f, / dz)
|
||||
vtkm::Vec<vtkm::Float32, 3> InverseExtent;
|
||||
vtkm::Vec<vtkm::Float32, 3> MinCoordinate;
|
||||
|
||||
//expands 10-bit unsigned int into 30 bits
|
||||
VTKM_EXEC
|
||||
vtkm::UInt32 ExpandBits(vtkm::UInt32 x) const
|
||||
{
|
||||
x = (x * 0x00010001u) & 0xFF0000FFu;
|
||||
x = (x * 0x00000101u) & 0x0F00F00Fu;
|
||||
x = (x * 0x00000011u) & 0xC30C30C3u;
|
||||
x = (x * 0x00000005u) & 0x49249249u;
|
||||
return x;
|
||||
}
|
||||
//Returns 30 bit morton code for coordinates for
|
||||
//coordinates in the unit cude
|
||||
VTKM_EXEC
|
||||
vtkm::UInt32 Morton3D(vtkm::Float32& x, vtkm::Float32& y, vtkm::Float32& z) const
|
||||
{
|
||||
//take the first 10 bits
|
||||
x = fminf(fmaxf(x * 1024.0f, 0.0f), 1023.0f);
|
||||
y = fminf(fmaxf(y * 1024.0f, 0.0f), 1023.0f);
|
||||
z = fminf(fmaxf(z * 1024.0f, 0.0f), 1023.0f);
|
||||
//expand the 10 bits to 30
|
||||
vtkm::UInt32 xx = ExpandBits((vtkm::UInt32)x);
|
||||
vtkm::UInt32 yy = ExpandBits((vtkm::UInt32)y);
|
||||
vtkm::UInt32 zz = ExpandBits((vtkm::UInt32)z);
|
||||
//interleave coordinates
|
||||
return xx * 4 + yy * 2 + zz;
|
||||
}
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
MortonCodeAABB(const vtkm::Vec<vtkm::Float32, 3>& inverseExtent,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& minCoordinate)
|
||||
: InverseExtent(inverseExtent)
|
||||
, MinCoordinate(minCoordinate)
|
||||
{
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
|
||||
typedef _7 InputDomain;
|
||||
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Float32& xmin,
|
||||
const vtkm::Float32& ymin,
|
||||
const vtkm::Float32& zmin,
|
||||
const vtkm::Float32& xmax,
|
||||
const vtkm::Float32& ymax,
|
||||
const vtkm::Float32& zmax,
|
||||
vtkm::UInt32& mortonCode) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> direction(xmax - xmin, ymax - ymin, zmax - zmin);
|
||||
vtkm::Float32 halfDistance = sqrtf(vtkm::dot(direction, direction)) * 0.5f;
|
||||
vtkm::Normalize(direction);
|
||||
vtkm::Float32 centroidx = xmin + halfDistance * direction[0] - MinCoordinate[0];
|
||||
vtkm::Float32 centroidy = ymin + halfDistance * direction[1] - MinCoordinate[1];
|
||||
vtkm::Float32 centroidz = zmin + halfDistance * direction[2] - MinCoordinate[2];
|
||||
//normalize the centroid tp 10 bits
|
||||
centroidx *= InverseExtent[0];
|
||||
centroidy *= InverseExtent[1];
|
||||
centroidz *= InverseExtent[2];
|
||||
mortonCode = Morton3D(centroidx, centroidy, centroidz);
|
||||
}
|
||||
}; // class MortonCodeAABB
|
||||
|
||||
class TreeBuilder : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::UInt32> UIntArrayHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
|
||||
typedef typename UIntArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst UIntPortalType;
|
||||
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::Portal IdPortalType;
|
||||
|
||||
private:
|
||||
UIntPortalType MortonCodePortal;
|
||||
IdPortalType ParentPortal;
|
||||
vtkm::Id LeafCount;
|
||||
vtkm::Id InnerCount;
|
||||
//TODO: get instrinsic support
|
||||
VTKM_EXEC
|
||||
vtkm::Int32 CountLeadingZeros(vtkm::UInt32& x) const
|
||||
{
|
||||
vtkm::UInt32 y;
|
||||
vtkm::UInt32 n = 32;
|
||||
y = x >> 16;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 16;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 8;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 8;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 4;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 4;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 2;
|
||||
if (y != 0)
|
||||
{
|
||||
n = n - 2;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 1;
|
||||
if (y != 0)
|
||||
return vtkm::Int32(n - 2);
|
||||
return vtkm::Int32(n - x);
|
||||
}
|
||||
|
||||
// returns the count of largest shared prefix between
|
||||
// two morton codes. Ties are broken by the indexes
|
||||
// a and b.
|
||||
//
|
||||
// returns count of the largest binary prefix
|
||||
|
||||
VTKM_EXEC
|
||||
vtkm::Int32 delta(const vtkm::Int32& a, const vtkm::Int32& b) const
|
||||
{
|
||||
bool tie = false;
|
||||
bool outOfRange = (b < 0 || b > LeafCount - 1);
|
||||
//still make the call but with a valid adderss
|
||||
vtkm::Int32 bb = (outOfRange) ? 0 : b;
|
||||
vtkm::UInt32 aCode = MortonCodePortal.Get(a);
|
||||
vtkm::UInt32 bCode = MortonCodePortal.Get(bb);
|
||||
//use xor to find where they differ
|
||||
vtkm::UInt32 exOr = aCode ^ bCode;
|
||||
tie = (exOr == 0);
|
||||
//break the tie, a and b must always differ
|
||||
exOr = tie ? vtkm::UInt32(a) ^ vtkm::UInt32(bb) : exOr;
|
||||
vtkm::Int32 count = CountLeadingZeros(exOr);
|
||||
if (tie)
|
||||
count += 32;
|
||||
count = (outOfRange) ? -1 : count;
|
||||
return count;
|
||||
}
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
TreeBuilder(const UIntArrayHandle& mortonCodesHandle,
|
||||
IdArrayHandle& parentHandle,
|
||||
const vtkm::Id& leafCount)
|
||||
: MortonCodePortal(mortonCodesHandle.PrepareForInput(DeviceAdapter()))
|
||||
, LeafCount(leafCount)
|
||||
{
|
||||
InnerCount = LeafCount - 1;
|
||||
this->ParentPortal = parentHandle.PrepareForOutput(InnerCount + LeafCount, DeviceAdapter());
|
||||
}
|
||||
typedef void ControlSignature(FieldOut<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& index, vtkm::Id& leftChild, vtkm::Id& rightChild) const
|
||||
{
|
||||
vtkm::Int32 idx = vtkm::Int32(index);
|
||||
//something = MortonCodePortal.Get(index) + 1;
|
||||
//determine range direction
|
||||
vtkm::Int32 d = 0 > (delta(idx, idx + 1) - delta(idx, idx - 1)) ? -1 : 1;
|
||||
|
||||
//find upper bound for the length of the range
|
||||
vtkm::Int32 minDelta = delta(idx, idx - d);
|
||||
vtkm::Int32 lMax = 2;
|
||||
while (delta(idx, idx + lMax * d) > minDelta)
|
||||
lMax *= 2;
|
||||
|
||||
//binary search to find the lower bound
|
||||
vtkm::Int32 l = 0;
|
||||
for (int t = lMax / 2; t >= 1; t /= 2)
|
||||
{
|
||||
if (delta(idx, idx + (l + t) * d) > minDelta)
|
||||
l += t;
|
||||
}
|
||||
|
||||
vtkm::Int32 j = idx + l * d;
|
||||
vtkm::Int32 deltaNode = delta(idx, j);
|
||||
vtkm::Int32 s = 0;
|
||||
vtkm::Float32 divFactor = 2.f;
|
||||
//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))
|
||||
{
|
||||
if (delta(idx, idx + (s + t) * d) > deltaNode)
|
||||
{
|
||||
s += t;
|
||||
}
|
||||
|
||||
if (t == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
vtkm::Int32 split = idx + s * d + vtkm::Min(d, 0);
|
||||
//assign parent/child pointers
|
||||
if (vtkm::Min(idx, j) == split)
|
||||
{
|
||||
//leaf
|
||||
ParentPortal.Set(split + InnerCount, idx);
|
||||
leftChild = split + InnerCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
//inner node
|
||||
ParentPortal.Set(split, idx);
|
||||
leftChild = split;
|
||||
}
|
||||
|
||||
if (vtkm::Max(idx, j) == split + 1)
|
||||
{
|
||||
//leaf
|
||||
ParentPortal.Set(split + InnerCount + 1, idx);
|
||||
rightChild = split + InnerCount + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentPortal.Set(split + 1, idx);
|
||||
rightChild = split + 1;
|
||||
}
|
||||
}
|
||||
}; // class TreeBuilder
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
LinearBVHBuilder() {}
|
||||
|
||||
VTKM_CONT
|
||||
void SortAABBS(BVHData& bvh,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& triangleIndices,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>>& outputTriangleIndices)
|
||||
{
|
||||
//create array of indexes to be sorted with morton codes
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> iterator;
|
||||
iterator.PrepareForOutput(bvh.GetNumberOfPrimitives(), DeviceAdapter());
|
||||
vtkm::worklet::DispatcherMapField<CountingIterator> iteratorDispatcher;
|
||||
iteratorDispatcher.Invoke(iterator);
|
||||
|
||||
/*
|
||||
for(int i = 0; i < bvh.GetNumberOfPrimitives(); i++)
|
||||
{
|
||||
//std::cout<<iterator.GetPortalControl().Get(i)
|
||||
<<" "<<bvh.mortonCodes.GetPortalControl().Get(i)
|
||||
<<" "<<bvh.xmins->GetPortalControl().Get(i)
|
||||
<<" "<<bvh.ymins->GetPortalControl().Get(i)
|
||||
<<" "<<bvh.zmins->GetPortalControl().Get(i)
|
||||
<<" "<<bvh.xmaxs->GetPortalControl().Get(i)
|
||||
<<" "<<bvh.ymaxs->GetPortalControl().Get(i)
|
||||
<<" "<<bvh.zmaxs->GetPortalControl().Get(i)
|
||||
<<" "<<triangleIndices->GetPortalControl().Get(i)
|
||||
<<" \n";
|
||||
}
|
||||
*/
|
||||
//std::cout<<"\n\n\n";
|
||||
//sort the morton codes
|
||||
|
||||
vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::SortByKey(bvh.mortonCodes, iterator);
|
||||
|
||||
vtkm::Id arraySize = bvh.GetNumberOfPrimitives();
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>* tempStorage;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>* tempPtr;
|
||||
|
||||
//outputTriangleIndices.Allocate( bvh.GetNumberOfPrimitives() );
|
||||
|
||||
tempStorage = new vtkm::cont::ArrayHandle<vtkm::Float32>();
|
||||
//tempStorage->Allocate( arraySize );
|
||||
// for (int i = 0; i < 12; ++i)
|
||||
// {
|
||||
// //std::cout<<bvh.xmins->GetPortalControl().Get(i)<<" ";
|
||||
// }//std::cout<<"\n";
|
||||
//xmins
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.xmins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.xmins;
|
||||
bvh.xmins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.ymins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.ymins;
|
||||
bvh.ymins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//zmins
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.zmins, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.zmins;
|
||||
bvh.zmins = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//xmaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.xmaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.xmaxs;
|
||||
bvh.xmaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//ymaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.ymaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
tempPtr = bvh.ymaxs;
|
||||
bvh.ymaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
//zmaxs
|
||||
vtkm::worklet::DispatcherMapField<GatherFloat32>(
|
||||
GatherFloat32(*bvh.zmaxs, *tempStorage, arraySize))
|
||||
.Invoke(iterator);
|
||||
|
||||
tempPtr = bvh.zmaxs;
|
||||
bvh.zmaxs = tempStorage;
|
||||
tempStorage = tempPtr;
|
||||
vtkm::worklet::DispatcherMapField<GatherVecCast>(
|
||||
GatherVecCast(triangleIndices, outputTriangleIndices, arraySize))
|
||||
.Invoke(iterator);
|
||||
delete tempStorage;
|
||||
|
||||
} // method SortAABBs
|
||||
|
||||
VTKM_CONT
|
||||
void run(vtkm::cont::DynamicArrayHandleCoordinateSystem& coordsHandle,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& triangleIndices,
|
||||
const vtkm::Id& numberOfTriangles,
|
||||
LinearBVH& linearBVH)
|
||||
{
|
||||
const vtkm::Id numBBoxes = numberOfTriangles;
|
||||
BVHData bvh(numBBoxes);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<FindAABBs>(FindAABBs())
|
||||
.Invoke(triangleIndices,
|
||||
*bvh.xmins,
|
||||
*bvh.ymins,
|
||||
*bvh.zmins,
|
||||
*bvh.xmaxs,
|
||||
*bvh.ymaxs,
|
||||
*bvh.zmaxs,
|
||||
coordsHandle);
|
||||
// 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<DeviceAdapter>::Reduce(
|
||||
*bvh.xmaxs, maxExtent[0], MaxValue());
|
||||
maxExtent[1] = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
|
||||
*bvh.ymaxs, maxExtent[1], MaxValue());
|
||||
maxExtent[2] = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
|
||||
*bvh.zmaxs, maxExtent[2], MaxValue());
|
||||
minExtent[0] = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
|
||||
*bvh.xmins, minExtent[0], MinValue());
|
||||
minExtent[1] = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
|
||||
*bvh.ymins, minExtent[1], MinValue());
|
||||
minExtent[2] = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>::Reduce(
|
||||
*bvh.zmins, minExtent[2], MinValue());
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> deltaExtent = maxExtent - minExtent;
|
||||
vtkm::Vec<vtkm::Float32, 3> inverseExtent;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
inverseExtent[i] = (deltaExtent[i] == 0.f) ? 0 : 1.f / deltaExtent[i];
|
||||
}
|
||||
|
||||
//Generate the morton codes
|
||||
vtkm::worklet::DispatcherMapField<MortonCodeAABB>(MortonCodeAABB(inverseExtent, minExtent))
|
||||
.Invoke(
|
||||
*bvh.xmins, *bvh.ymins, *bvh.zmins, *bvh.xmaxs, *bvh.ymaxs, *bvh.zmaxs, bvh.mortonCodes);
|
||||
linearBVH.Allocate(bvh.GetNumberOfPrimitives(), DeviceAdapter());
|
||||
SortAABBS(bvh, triangleIndices, linearBVH.LeafNodes);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<TreeBuilder>(
|
||||
TreeBuilder(bvh.mortonCodes, bvh.parent, bvh.GetNumberOfPrimitives()))
|
||||
.Invoke(bvh.leftChild, bvh.rightChild);
|
||||
|
||||
const vtkm::Int32 primitiveCount = vtkm::Int32(bvh.GetNumberOfPrimitives());
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Int32> counters;
|
||||
counters.PrepareForOutput(bvh.GetNumberOfPrimitives() - 1, DeviceAdapter());
|
||||
vtkm::Int32 zero = 0;
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Int32>>(MemSet<vtkm::Int32>(zero))
|
||||
.Invoke(counters);
|
||||
vtkm::exec::AtomicArray<vtkm::Int32, DeviceAdapter> atomicCounters(counters);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<PropagateAABBs>(PropagateAABBs(bvh.parent,
|
||||
bvh.leftChild,
|
||||
bvh.rightChild,
|
||||
primitiveCount,
|
||||
linearBVH.FlatBVH,
|
||||
atomicCounters))
|
||||
.Invoke(vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.xmins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.ymins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.zmins),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.xmaxs),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.ymaxs),
|
||||
vtkm::exec::ExecutionWholeArrayConst<vtkm::Float32>(*bvh.zmaxs));
|
||||
}
|
||||
}; // class LinearBVHBuilder
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
|
@ -21,12 +21,28 @@
|
||||
set(headers
|
||||
BoundingVolumeHierarchy.h
|
||||
Camera.h
|
||||
ChannelBuffer.h
|
||||
ChannelBufferOperations.h
|
||||
ConnectivityBase.h
|
||||
ConnectivityTracer.h
|
||||
ConnectivityTracerFactory.h
|
||||
CellIntersector.h
|
||||
CellSampler.h
|
||||
CellTables.h
|
||||
Logger.h
|
||||
MeshConnectivityBuilder.h
|
||||
MeshConnectivityStructures.h
|
||||
MortonCodes.h
|
||||
Ray.h
|
||||
RayOperations.h
|
||||
RayTracer.h
|
||||
RayTracingTypeDefs.h
|
||||
Ray.h
|
||||
TriangleIntersector.h
|
||||
Worklets.h
|
||||
VolumeRendererStructured.h
|
||||
)
|
||||
|
||||
set_source_files_properties(CellTables.h
|
||||
PROPERTIES VTKm_CANT_BE_HEADER_TESTED TRUE)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
929
vtkm/rendering/raytracing/Camera.cxx
Normal file
929
vtkm/rendering/raytracing/Camera.cxx
Normal file
@ -0,0 +1,929 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/cont/Timer.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/RayOperations.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class PixelData : 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> delta_x;
|
||||
vtkm::Vec<vtkm::Float32, 3> delta_y;
|
||||
vtkm::Vec<vtkm::Float32, 3> Origin;
|
||||
vtkm::Bounds BoundingBox;
|
||||
VTKM_CONT
|
||||
PixelData(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 subsetWidth,
|
||||
vtkm::Int32 minx,
|
||||
vtkm::Int32 miny,
|
||||
vtkm::Vec<vtkm::Float32, 3> origin,
|
||||
vtkm::Bounds boundingBox)
|
||||
: w(width)
|
||||
, h(height)
|
||||
, Minx(minx)
|
||||
, Miny(miny)
|
||||
, SubsetWidth(subsetWidth)
|
||||
, Origin(origin)
|
||||
, BoundingBox(boundingBox)
|
||||
{
|
||||
vtkm::Float32 thx = tanf((fovX * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Float32 thy = tanf((fovY * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Vec<vtkm::Float32, 3> ru = vtkm::Cross(look, up);
|
||||
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);
|
||||
}
|
||||
|
||||
VTKM_EXEC inline vtkm::Float32 rcp(vtkm::Float32 f) const { return 1.0f / f; }
|
||||
|
||||
VTKM_EXEC inline vtkm::Float32 rcp_safe(vtkm::Float32 f) const
|
||||
{
|
||||
return rcp((fabs(f) < 1e-8f) ? 1e-8f : f);
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldOut<>, FieldOut<>);
|
||||
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id idx, vtkm::Int32& hit, vtkm::Float32& distance) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> ray_dir;
|
||||
int i = vtkm::Int32(idx) % SubsetWidth;
|
||||
int j = vtkm::Int32(idx) / SubsetWidth;
|
||||
i += Minx;
|
||||
j += Miny;
|
||||
// Write out the global pixelId
|
||||
ray_dir = nlook + delta_x * ((2.f * vtkm::Float32(i) - vtkm::Float32(w)) / 2.0f) +
|
||||
delta_y * ((2.f * vtkm::Float32(j) - vtkm::Float32(h)) / 2.0f);
|
||||
|
||||
vtkm::Float32 dot = vtkm::dot(ray_dir, ray_dir);
|
||||
vtkm::Float32 sq_mag = vtkm::Sqrt(dot);
|
||||
|
||||
ray_dir[0] = ray_dir[0] / sq_mag;
|
||||
ray_dir[1] = ray_dir[1] / sq_mag;
|
||||
ray_dir[2] = ray_dir[2] / sq_mag;
|
||||
|
||||
vtkm::Float32 invDirx = rcp_safe(ray_dir[0]);
|
||||
vtkm::Float32 invDiry = rcp_safe(ray_dir[1]);
|
||||
vtkm::Float32 invDirz = rcp_safe(ray_dir[2]);
|
||||
|
||||
vtkm::Float32 odirx = Origin[0] * invDirx;
|
||||
vtkm::Float32 odiry = Origin[1] * invDiry;
|
||||
vtkm::Float32 odirz = Origin[2] * invDirz;
|
||||
|
||||
vtkm::Float32 xmin = vtkm::Float32(BoundingBox.X.Min) * invDirx - odirx;
|
||||
vtkm::Float32 ymin = vtkm::Float32(BoundingBox.Y.Min) * invDiry - odiry;
|
||||
vtkm::Float32 zmin = vtkm::Float32(BoundingBox.Z.Min) * invDirz - odirz;
|
||||
vtkm::Float32 xmax = vtkm::Float32(BoundingBox.X.Max) * invDirx - odirx;
|
||||
vtkm::Float32 ymax = vtkm::Float32(BoundingBox.Y.Max) * invDiry - odiry;
|
||||
vtkm::Float32 zmax = vtkm::Float32(BoundingBox.Z.Max) * invDirz - odirz;
|
||||
vtkm::Float32 mind = vtkm::Max(
|
||||
vtkm::Max(vtkm::Max(vtkm::Min(ymin, ymax), vtkm::Min(xmin, xmax)), vtkm::Min(zmin, zmax)),
|
||||
0.f);
|
||||
vtkm::Float32 maxd =
|
||||
vtkm::Min(vtkm::Min(vtkm::Max(ymin, ymax), vtkm::Max(xmin, xmax)), vtkm::Max(zmin, zmax));
|
||||
if (maxd < mind)
|
||||
{
|
||||
hit = 0;
|
||||
distance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = maxd - mind;
|
||||
hit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}; // class pixelData
|
||||
|
||||
class Camera::PerspectiveRayGen : 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> delta_x;
|
||||
vtkm::Vec<vtkm::Float32, 3> delta_y;
|
||||
VTKM_CONT
|
||||
PerspectiveRayGen(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 subsetWidth,
|
||||
vtkm::Int32 minx,
|
||||
vtkm::Int32 miny)
|
||||
: w(width)
|
||||
, h(height)
|
||||
, Minx(minx)
|
||||
, Miny(miny)
|
||||
, SubsetWidth(subsetWidth)
|
||||
{
|
||||
vtkm::Float32 thx = tanf((fovX * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Float32 thy = tanf((fovY * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Vec<vtkm::Float32, 3> ru = vtkm::Cross(look, up);
|
||||
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);
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldOut<>, FieldOut<>, FieldOut<>, FieldOut<>);
|
||||
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2, _3, _4);
|
||||
template <typename Precision>
|
||||
VTKM_EXEC void operator()(vtkm::Id idx,
|
||||
Precision& rayDirX,
|
||||
Precision& rayDirY,
|
||||
Precision& rayDirZ,
|
||||
vtkm::Id& pixelIndex) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> ray_dir(rayDirX, rayDirY, rayDirZ);
|
||||
int i = vtkm::Int32(idx) % SubsetWidth;
|
||||
int j = vtkm::Int32(idx) / SubsetWidth;
|
||||
i += Minx;
|
||||
j += Miny;
|
||||
// Write out the global pixelId
|
||||
pixelIndex = static_cast<vtkm::Id>(j * w + i);
|
||||
ray_dir = nlook + delta_x * ((2.f * Precision(i) - Precision(w)) / 2.0f) +
|
||||
delta_y * ((2.f * Precision(j) - Precision(h)) / 2.0f);
|
||||
|
||||
Precision dot = vtkm::dot(ray_dir, ray_dir);
|
||||
Precision sq_mag = vtkm::Sqrt(dot);
|
||||
|
||||
rayDirX = ray_dir[0] / sq_mag;
|
||||
rayDirY = ray_dir[1] / sq_mag;
|
||||
rayDirZ = ray_dir[2] / sq_mag;
|
||||
}
|
||||
|
||||
}; // class perspective ray gen
|
||||
|
||||
bool Camera::operator==(const Camera& other) const
|
||||
{
|
||||
|
||||
if (this->Height != other.Height)
|
||||
return false;
|
||||
if (this->Width != other.Width)
|
||||
return false;
|
||||
if (this->SubsetWidth != other.SubsetWidth)
|
||||
return false;
|
||||
if (this->SubsetHeight != other.SubsetHeight)
|
||||
return false;
|
||||
if (this->SubsetMinX != other.SubsetMinX)
|
||||
return false;
|
||||
if (this->SubsetMinY != other.SubsetMinY)
|
||||
return false;
|
||||
if (this->FovY != other.FovY)
|
||||
return false;
|
||||
if (this->FovX != other.FovX)
|
||||
return false;
|
||||
if (this->Zoom != other.Zoom)
|
||||
return false;
|
||||
if (this->Look[0] != other.Look[0])
|
||||
return false;
|
||||
if (this->Look[1] != other.Look[1])
|
||||
return false;
|
||||
if (this->Look[2] != other.Look[2])
|
||||
return false;
|
||||
if (this->LookAt[0] != other.LookAt[0])
|
||||
return false;
|
||||
if (this->LookAt[1] != other.LookAt[1])
|
||||
return false;
|
||||
if (this->LookAt[2] != other.LookAt[2])
|
||||
return false;
|
||||
if (this->Up[0] != other.Up[0])
|
||||
return false;
|
||||
if (this->Up[1] != other.Up[1])
|
||||
return false;
|
||||
if (this->Up[2] != other.Up[2])
|
||||
return false;
|
||||
if (this->Position[0] != other.Position[0])
|
||||
return false;
|
||||
if (this->Position[1] != other.Position[1])
|
||||
return false;
|
||||
if (this->Position[2] != other.Position[2])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
Camera::Camera()
|
||||
{
|
||||
this->Height = 500;
|
||||
this->Width = 500;
|
||||
this->SubsetWidth = 500;
|
||||
this->SubsetHeight = 500;
|
||||
this->SubsetMinX = 0;
|
||||
this->SubsetMinY = 0;
|
||||
this->FovY = 30.f;
|
||||
this->FovX = 30.f;
|
||||
this->Zoom = 1.f;
|
||||
this->Look[0] = 0.f;
|
||||
this->Look[1] = 0.f;
|
||||
this->Look[2] = -1.f;
|
||||
this->LookAt[0] = 0.f;
|
||||
this->LookAt[1] = 0.f;
|
||||
this->LookAt[2] = -1.f;
|
||||
this->Up[0] = 0.f;
|
||||
this->Up[1] = 1.f;
|
||||
this->Up[2] = 0.f;
|
||||
this->Position[0] = 0.f;
|
||||
this->Position[1] = 0.f;
|
||||
this->Position[2] = 0.f;
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
Camera::~Camera()
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetParameters(const vtkm::rendering::Camera& camera,
|
||||
vtkm::rendering::CanvasRayTracer& canvas)
|
||||
{
|
||||
this->SetUp(camera.GetViewUp());
|
||||
this->SetLookAt(camera.GetLookAt());
|
||||
this->SetPosition(camera.GetPosition());
|
||||
this->SetFieldOfView(camera.GetFieldOfView());
|
||||
this->SetHeight(static_cast<vtkm::Int32>(canvas.GetHeight()));
|
||||
this->SetWidth(static_cast<vtkm::Int32>(canvas.GetWidth()));
|
||||
this->CameraView = camera;
|
||||
Canvas = canvas;
|
||||
}
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetHeight(const vtkm::Int32& height)
|
||||
{
|
||||
if (height <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera height must be greater than zero.");
|
||||
}
|
||||
if (Height != height)
|
||||
{
|
||||
this->Height = height;
|
||||
this->SetFieldOfView(this->FovX);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 Camera::GetHeight() const
|
||||
{
|
||||
return this->Height;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetWidth(const vtkm::Int32& width)
|
||||
{
|
||||
if (width <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera width must be greater than zero.");
|
||||
}
|
||||
if (this->Width != width)
|
||||
{
|
||||
this->Width = width;
|
||||
this->SetFieldOfView(this->FovX);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 Camera::GetWidth() const
|
||||
{
|
||||
return this->Width;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 Camera::GetSubsetWidth() const
|
||||
{
|
||||
return this->SubsetWidth;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 Camera::GetSubsetHeight() const
|
||||
{
|
||||
return this->SubsetHeight;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetZoom(const vtkm::Float32& zoom)
|
||||
{
|
||||
if (zoom <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera zoom must be greater than zero.");
|
||||
}
|
||||
if (this->Zoom != zoom)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
this->Zoom = zoom;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float32 Camera::GetZoom() const
|
||||
{
|
||||
return this->Zoom;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetFieldOfView(const vtkm::Float32& degrees)
|
||||
{
|
||||
if (degrees <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera feild of view must be greater than zero.");
|
||||
}
|
||||
if (degrees > 180)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera feild of view must be less than 180.");
|
||||
}
|
||||
|
||||
vtkm::Float32 newFOVY = (vtkm::Float32(this->Height) / vtkm::Float32(this->Width)) * degrees;
|
||||
vtkm::Float32 newFOVX = degrees;
|
||||
if (newFOVX != this->FovX)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
if (newFOVY != this->FovY)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
this->FovX = newFOVX;
|
||||
this->FovY = newFOVY;
|
||||
this->CameraView.SetFieldOfView(this->FovX);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float32 Camera::GetFieldOfView() const
|
||||
{
|
||||
return this->FovX;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetUp(const vtkm::Vec<vtkm::Float32, 3>& up)
|
||||
{
|
||||
if (this->Up != up)
|
||||
{
|
||||
this->Up = up;
|
||||
vtkm::Normalize(this->Up);
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> Camera::GetUp() const
|
||||
{
|
||||
return this->Up;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetLookAt(const vtkm::Vec<vtkm::Float32, 3>& lookAt)
|
||||
{
|
||||
if (this->LookAt != lookAt)
|
||||
{
|
||||
this->LookAt = lookAt;
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> Camera::GetLookAt() const
|
||||
{
|
||||
return this->LookAt;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::SetPosition(const vtkm::Vec<vtkm::Float32, 3>& position)
|
||||
{
|
||||
if (this->Position != position)
|
||||
{
|
||||
this->Position = position;
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> Camera::GetPosition() const
|
||||
{
|
||||
return this->Position;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::ResetIsViewDirty()
|
||||
{
|
||||
this->IsViewDirty = false;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
struct Camera::PixelDataFunctor
|
||||
{
|
||||
vtkm::rendering::raytracing::Camera* Self;
|
||||
const vtkm::cont::CoordinateSystem& Coords;
|
||||
vtkm::Int32& ActivePixels;
|
||||
vtkm::Float32& AveDistPerRay;
|
||||
|
||||
VTKM_CONT
|
||||
PixelDataFunctor(vtkm::rendering::raytracing::Camera* self,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::Int32& activePixels,
|
||||
vtkm::Float32& aveDistPerRay)
|
||||
: Self(self)
|
||||
, Coords(coords)
|
||||
, ActivePixels(activePixels)
|
||||
, AveDistPerRay(aveDistPerRay)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT bool operator()(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
vtkm::Bounds boundingBox = Coords.GetBounds();
|
||||
Self->FindSubset(boundingBox);
|
||||
//Reset the camera look vector
|
||||
Self->Look = Self->LookAt - Self->Position;
|
||||
vtkm::Normalize(Self->Look);
|
||||
const int size = Self->SubsetWidth * Self->SubsetHeight;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> dists;
|
||||
vtkm::cont::ArrayHandle<vtkm::Int32> hits;
|
||||
dists.PrepareForOutput(size, Device());
|
||||
hits.PrepareForOutput(size, Device());
|
||||
|
||||
//Create the ray direction
|
||||
vtkm::worklet::DispatcherMapField<PixelData, Device>(PixelData(Self->Width,
|
||||
Self->Height,
|
||||
Self->FovX,
|
||||
Self->FovY,
|
||||
Self->Look,
|
||||
Self->Up,
|
||||
Self->Zoom,
|
||||
Self->SubsetWidth,
|
||||
Self->SubsetMinX,
|
||||
Self->SubsetMinY,
|
||||
Self->Position,
|
||||
boundingBox))
|
||||
.Invoke(hits, dists); //X Y Z
|
||||
ActivePixels = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(hits, vtkm::Int32(0));
|
||||
AveDistPerRay = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(dists, vtkm::Float32(0)) /
|
||||
vtkm::Float32(ActivePixels);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void Camera::GetPixelData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::Int32& activePixels,
|
||||
vtkm::Float32& aveRayDistance)
|
||||
{
|
||||
|
||||
PixelDataFunctor functor(this, coords, activePixels, aveRayDistance);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::CreateRays(Ray<vtkm::Float32>& rays, const vtkm::cont::CoordinateSystem& coords)
|
||||
{
|
||||
CreateRaysFunctor<Float32> functor(this, coords, rays);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::CreateRays(Ray<vtkm::Float64>& rays, const vtkm::cont::CoordinateSystem& coords)
|
||||
{
|
||||
CreateRaysFunctor<Float64> functor(this, coords, rays);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
template <typename Precision, typename Device>
|
||||
VTKM_CONT void Camera::CreateRaysOnDevice(Ray<Precision>& rays,
|
||||
Device,
|
||||
const vtkm::Bounds boundingBox)
|
||||
{
|
||||
Logger* logger = Logger::GetInstance();
|
||||
vtkm::cont::Timer<Device> createTimer;
|
||||
logger->OpenLogEntry("ray_camera");
|
||||
logger->AddLogData("device", GetDeviceString(Device()));
|
||||
this->UpdateDimensions(rays, Device(), boundingBox);
|
||||
|
||||
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);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(infinity))
|
||||
.Invoke(rays.MaxDistance);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(0.f))
|
||||
.Invoke(rays.MinDistance);
|
||||
|
||||
//Reset the Rays Hit Index to -2
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Id>, Device>(MemSet<vtkm::Id>(-2))
|
||||
.Invoke(rays.HitIdx);
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("camera_memset", time);
|
||||
timer.Reset();
|
||||
|
||||
//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
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("ray_gen", time);
|
||||
time = createTimer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
} //create rays
|
||||
|
||||
VTKM_CONT
|
||||
void Camera::FindSubset(const vtkm::Bounds& bounds)
|
||||
{
|
||||
this->ViewProjectionMat =
|
||||
vtkm::MatrixMultiply(this->CameraView.CreateProjectionMatrix(this->Width, this->Height),
|
||||
this->CameraView.CreateViewMatrix());
|
||||
vtkm::Float32 x[2], y[2], z[2];
|
||||
x[0] = static_cast<vtkm::Float32>(bounds.X.Min);
|
||||
x[1] = static_cast<vtkm::Float32>(bounds.X.Max);
|
||||
y[0] = static_cast<vtkm::Float32>(bounds.Y.Min);
|
||||
y[1] = static_cast<vtkm::Float32>(bounds.Y.Max);
|
||||
z[0] = static_cast<vtkm::Float32>(bounds.Z.Min);
|
||||
z[1] = static_cast<vtkm::Float32>(bounds.Z.Max);
|
||||
//Inise the data bounds
|
||||
if (this->Position[0] >= x[0] && this->Position[0] <= x[1] && this->Position[1] >= y[0] &&
|
||||
this->Position[1] <= y[1] && this->Position[2] >= z[0] && this->Position[2] <= z[1])
|
||||
{
|
||||
this->SubsetWidth = this->Width;
|
||||
this->SubsetHeight = this->Height;
|
||||
this->SubsetMinY = 0;
|
||||
this->SubsetMinX = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//std::cout<<"Bounds ("<<x[0]<<","<<y[0]<<","<<z[0]<<")-("<<x[1]<<","<<y[1]<<","<<z[1]<<std::endl;
|
||||
vtkm::Float32 xmin, ymin, xmax, ymax, zmin, zmax;
|
||||
xmin = vtkm::Infinity32();
|
||||
ymin = vtkm::Infinity32();
|
||||
zmin = vtkm::Infinity32();
|
||||
xmax = vtkm::NegativeInfinity32();
|
||||
ymax = vtkm::NegativeInfinity32();
|
||||
zmax = vtkm::NegativeInfinity32();
|
||||
vtkm::Vec<vtkm::Float32, 4> extentPoint;
|
||||
for (vtkm::Int32 i = 0; i < 2; ++i)
|
||||
for (vtkm::Int32 j = 0; j < 2; ++j)
|
||||
for (vtkm::Int32 k = 0; k < 2; ++k)
|
||||
{
|
||||
extentPoint[0] = x[i];
|
||||
extentPoint[1] = y[j];
|
||||
extentPoint[2] = z[k];
|
||||
extentPoint[3] = 1.f;
|
||||
vtkm::Vec<vtkm::Float32, 4> transformed =
|
||||
vtkm::MatrixMultiply(this->ViewProjectionMat, extentPoint);
|
||||
// perform the perspective divide
|
||||
for (vtkm::Int32 a = 0; a < 3; ++a)
|
||||
{
|
||||
transformed[a] = transformed[a] / transformed[3];
|
||||
}
|
||||
|
||||
transformed[0] = (transformed[0] * 0.5f + 0.5f) * static_cast<vtkm::Float32>(Width);
|
||||
transformed[1] = (transformed[1] * 0.5f + 0.5f) * static_cast<vtkm::Float32>(Height);
|
||||
transformed[2] = (transformed[2] * 0.5f + 0.5f);
|
||||
zmin = vtkm::Min(zmin, transformed[2]);
|
||||
zmax = vtkm::Max(zmax, transformed[2]);
|
||||
if (transformed[2] < 0 || transformed[2] > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
xmin = vtkm::Min(xmin, transformed[0]);
|
||||
ymin = vtkm::Min(ymin, transformed[1]);
|
||||
xmax = vtkm::Max(xmax, transformed[0]);
|
||||
ymax = vtkm::Max(ymax, transformed[1]);
|
||||
}
|
||||
|
||||
xmin -= .001f;
|
||||
xmax += .001f;
|
||||
ymin -= .001f;
|
||||
ymax += .001f;
|
||||
xmin = vtkm::Floor(vtkm::Min(vtkm::Max(0.f, xmin), vtkm::Float32(Width)));
|
||||
xmax = vtkm::Ceil(vtkm::Min(vtkm::Max(0.f, xmax), vtkm::Float32(Width)));
|
||||
ymin = vtkm::Floor(vtkm::Min(vtkm::Max(0.f, ymin), vtkm::Float32(Height)));
|
||||
ymax = vtkm::Ceil(vtkm::Min(vtkm::Max(0.f, ymax), vtkm::Float32(Height)));
|
||||
|
||||
//printf("Pixel range = (%f,%f,%f), (%f,%f,%f)\n", xmin, ymin,zmin, xmax,ymax,zmax);
|
||||
vtkm::Int32 dx = vtkm::Int32(xmax) - vtkm::Int32(xmin);
|
||||
vtkm::Int32 dy = vtkm::Int32(ymax) - vtkm::Int32(ymin);
|
||||
|
||||
//
|
||||
// scene is behind the camera
|
||||
//
|
||||
if (zmax < 0 || xmin >= xmax || ymin >= ymax)
|
||||
{
|
||||
this->SubsetWidth = 1;
|
||||
this->SubsetHeight = 1;
|
||||
this->SubsetMinX = 0;
|
||||
this->SubsetMinY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SubsetWidth = dx;
|
||||
this->SubsetHeight = dy;
|
||||
this->SubsetMinX = vtkm::Int32(xmin);
|
||||
this->SubsetMinY = vtkm::Int32(ymin);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Device, typename Precision>
|
||||
VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
|
||||
Device,
|
||||
const vtkm::Bounds& boundingBox)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
this->FindSubset(boundingBox);
|
||||
}
|
||||
|
||||
//Update the image dimensions
|
||||
this->SubsetWidth = this->Width;
|
||||
this->SubsetHeight = this->Height;
|
||||
this->SubsetMinY = 0;
|
||||
this->SubsetMinX = 0;
|
||||
// resize rays and buffers
|
||||
|
||||
|
||||
if (rays.NumRays != SubsetWidth * SubsetHeight)
|
||||
{
|
||||
RayOperations::Resize(rays, this->SubsetHeight * this->SubsetWidth, Device());
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::CreateDebugRay(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<vtkm::Float64>& rays)
|
||||
{
|
||||
CreateDebugRayImp(pixel, rays);
|
||||
}
|
||||
|
||||
void Camera::CreateDebugRay(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<vtkm::Float32>& rays)
|
||||
{
|
||||
CreateDebugRayImp(pixel, rays);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void Camera::CreateDebugRayImp(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<Precision>& rays)
|
||||
{
|
||||
RayOperations::Resize(rays, 1, vtkm::cont::DeviceAdapterTagSerial());
|
||||
vtkm::Int32 pixelIndex = this->Width * (this->Height - pixel[1]) + pixel[0];
|
||||
rays.PixelIdx.GetPortalControl().Set(0, pixelIndex);
|
||||
|
||||
rays.OriginX.GetPortalControl().Set(0, this->Position[0]);
|
||||
rays.OriginY.GetPortalControl().Set(0, this->Position[1]);
|
||||
rays.OriginZ.GetPortalControl().Set(0, this->Position[2]);
|
||||
|
||||
|
||||
vtkm::Float32 infinity;
|
||||
GetInfinity(infinity);
|
||||
|
||||
rays.MaxDistance.GetPortalControl().Set(0, infinity);
|
||||
rays.MinDistance.GetPortalControl().Set(0, 0.f);
|
||||
rays.HitIdx.GetPortalControl().Set(0, -2);
|
||||
|
||||
vtkm::Float32 thx = tanf((this->FovX * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Float32 thy = tanf((this->FovY * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Vec<vtkm::Float32, 3> ru = vtkm::Cross(this->Look, this->Up);
|
||||
vtkm::Normalize(ru);
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> rv = vtkm::Cross(ru, this->Look);
|
||||
vtkm::Vec<vtkm::Float32, 3> delta_x, delta_y;
|
||||
vtkm::Normalize(rv);
|
||||
delta_x = ru * (2 * thx / (float)this->Width);
|
||||
delta_y = rv * (2 * thy / (float)this->Height);
|
||||
|
||||
if (this->Zoom > 0)
|
||||
{
|
||||
vtkm::Float32 _zoom = this->Zoom;
|
||||
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;
|
||||
}
|
||||
vtkm::Vec<vtkm::Float32, 3> nlook = this->Look;
|
||||
vtkm::Normalize(nlook);
|
||||
|
||||
vtkm::Vec<Precision, 3> ray_dir;
|
||||
int i = vtkm::Int32(pixelIndex) % this->Width;
|
||||
int j = vtkm::Int32(pixelIndex) / this->Height;
|
||||
|
||||
ray_dir = nlook + delta_x * ((2.f * Precision(i) - Precision(this->Width)) / 2.0f) +
|
||||
delta_y * ((2.f * Precision(j) - Precision(this->Height)) / 2.0f);
|
||||
|
||||
Precision dot = vtkm::dot(ray_dir, ray_dir);
|
||||
Precision sq_mag = vtkm::Sqrt(dot);
|
||||
|
||||
ray_dir[0] = ray_dir[0] / sq_mag;
|
||||
ray_dir[1] = ray_dir[1] / sq_mag;
|
||||
ray_dir[2] = ray_dir[2] / sq_mag;
|
||||
rays.DirX.GetPortalControl().Set(0, ray_dir[0]);
|
||||
rays.DirY.GetPortalControl().Set(0, ray_dir[1]);
|
||||
rays.DirZ.GetPortalControl().Set(0, ray_dir[2]);
|
||||
}
|
||||
|
||||
void Camera::WriteSettingsToLog()
|
||||
{
|
||||
Logger* logger = Logger::GetInstance();
|
||||
logger->AddLogData("position_x", Position[0]);
|
||||
logger->AddLogData("position_y", Position[1]);
|
||||
logger->AddLogData("position_z", Position[2]);
|
||||
|
||||
logger->AddLogData("lookat_x", LookAt[0]);
|
||||
logger->AddLogData("lookat_y", LookAt[1]);
|
||||
logger->AddLogData("lookat_z", LookAt[2]);
|
||||
|
||||
logger->AddLogData("up_x", Up[0]);
|
||||
logger->AddLogData("up_y", Up[1]);
|
||||
logger->AddLogData("up_z", Up[2]);
|
||||
|
||||
logger->AddLogData("fov_x", FovX);
|
||||
logger->AddLogData("fov_y", FovY);
|
||||
logger->AddLogData("width", Width);
|
||||
logger->AddLogData("height", Height);
|
||||
logger->AddLogData("subset_height", SubsetHeight);
|
||||
logger->AddLogData("subset_width", SubsetWidth);
|
||||
logger->AddLogData("num_rays", SubsetWidth * SubsetHeight);
|
||||
}
|
||||
|
||||
std::string Camera::ToString()
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << "------------------------------------------------------------\n";
|
||||
sstream << "Position : [" << this->Position[0] << ",";
|
||||
sstream << this->Position[1] << ",";
|
||||
sstream << this->Position[2] << "]\n";
|
||||
sstream << "LookAt : [" << this->LookAt[0] << ",";
|
||||
sstream << this->LookAt[1] << ",";
|
||||
sstream << this->LookAt[2] << "]\n";
|
||||
sstream << "FOV_X : " << this->FovX << "\n";
|
||||
sstream << "Up : [" << this->Up[0] << ",";
|
||||
sstream << this->Up[1] << ",";
|
||||
sstream << this->Up[2] << "]\n";
|
||||
sstream << "Width : " << this->Width << "\n";
|
||||
sstream << "Height : " << this->Height << "\n";
|
||||
sstream << "------------------------------------------------------------\n";
|
||||
return sstream.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
@ -21,9 +21,11 @@
|
||||
#define vtk_m_rendering_raytracing_Camera_h
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/CoordinateSystem.h>
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
#include <vtkm/rendering/Camera.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/rendering/raytracing/Worklets.h>
|
||||
@ -38,138 +40,15 @@ namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
class Camera
|
||||
|
||||
class VTKM_RENDERING_EXPORT Camera
|
||||
{
|
||||
public:
|
||||
class SurfaceConverter : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::Float32 Proj22;
|
||||
vtkm::Float32 Proj23;
|
||||
vtkm::Float32 Proj32;
|
||||
vtkm::Int32 Width;
|
||||
vtkm::Int32 SubsetWidth;
|
||||
vtkm::Int32 Xmin;
|
||||
vtkm::Int32 Ymin;
|
||||
vtkm::Int32 NumPixels;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
SurfaceConverter(const vtkm::Int32& width,
|
||||
const vtkm::Int32& subsetWidth,
|
||||
const vtkm::Int32& xmin,
|
||||
const vtkm::Int32& ymin,
|
||||
const vtkm::Matrix<vtkm::Float32, 4, 4> projMat,
|
||||
const vtkm::Int32& numPixels)
|
||||
{
|
||||
Width = width;
|
||||
SubsetWidth = subsetWidth;
|
||||
Xmin = xmin;
|
||||
Ymin = ymin;
|
||||
Proj22 = projMat[2][2];
|
||||
Proj23 = projMat[2][3];
|
||||
Proj32 = projMat[3][2];
|
||||
NumPixels = numPixels;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldIn<>, ExecObject, ExecObject);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, WorkIndex);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Vec<vtkm::Float32, 4>& inColor,
|
||||
const vtkm::Float32& inDepth,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>& depthBuffer,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Float32, 4>>& colorBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
if (index >= NumPixels)
|
||||
return;
|
||||
vtkm::Float32 depth = (Proj22 + Proj23 / (-inDepth)) / Proj32;
|
||||
depth = 0.5f * depth + 0.5f;
|
||||
vtkm::Int32 x = static_cast<vtkm::Int32>(index) % SubsetWidth;
|
||||
vtkm::Int32 y = static_cast<vtkm::Int32>(index) / SubsetWidth;
|
||||
x += Xmin;
|
||||
y += Ymin;
|
||||
vtkm::Id outIdx = static_cast<vtkm::Id>(y * Width + x);
|
||||
//std::cout<<" "<<depth;
|
||||
depthBuffer.Set(outIdx, depth);
|
||||
colorBuffer.Set(outIdx, inColor);
|
||||
}
|
||||
}; //class SurfaceConverter
|
||||
|
||||
class PerspectiveRayGen : 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> delta_x;
|
||||
vtkm::Vec<vtkm::Float32, 3> delta_y;
|
||||
VTKM_CONT
|
||||
PerspectiveRayGen(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 subsetWidth,
|
||||
vtkm::Int32 minx,
|
||||
vtkm::Int32 miny)
|
||||
: w(width)
|
||||
, h(height)
|
||||
, Minx(minx)
|
||||
, Miny(miny)
|
||||
, SubsetWidth(subsetWidth)
|
||||
{
|
||||
vtkm::Float32 thx = tanf((fovX * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Float32 thy = tanf((fovY * vtkm::Float32(vtkm::Pi()) / 180.f) * .5f);
|
||||
vtkm::Vec<vtkm::Float32, 3> ru = vtkm::Cross(look, up);
|
||||
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);
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldOut<>, FieldOut<>, FieldOut<>);
|
||||
|
||||
typedef void ExecutionSignature(WorkIndex, _1, _2, _3);
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Id idx,
|
||||
vtkm::Float32& rayDirX,
|
||||
vtkm::Float32& rayDirY,
|
||||
vtkm::Float32& rayDirZ) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> ray_dir(rayDirX, rayDirY, rayDirZ);
|
||||
int i = vtkm::Int32(idx) % SubsetWidth;
|
||||
int j = vtkm::Int32(idx) / SubsetWidth;
|
||||
i += Minx;
|
||||
j += Miny;
|
||||
ray_dir = nlook + delta_x * ((2.f * vtkm::Float32(i) - vtkm::Float32(w)) / 2.0f) +
|
||||
delta_y * ((2.f * vtkm::Float32(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
|
||||
private:
|
||||
struct PixelDataFunctor;
|
||||
template <typename Precision>
|
||||
struct CreateRaysFunctor;
|
||||
vtkm::rendering::CanvasRayTracer Canvas;
|
||||
vtkm::Int32 Height;
|
||||
vtkm::Int32 Width;
|
||||
vtkm::Int32 SubsetWidth;
|
||||
@ -178,13 +57,8 @@ private:
|
||||
vtkm::Int32 SubsetMinY;
|
||||
vtkm::Float32 FovX;
|
||||
vtkm::Float32 FovY;
|
||||
vtkm::Float32 FOV;
|
||||
vtkm::Float32 Zoom;
|
||||
bool IsViewDirty;
|
||||
bool IsResDirty;
|
||||
bool MortonSort;
|
||||
bool LookAtSet;
|
||||
//bool ImageSubsetModeOn;
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 3> Look;
|
||||
vtkm::Vec<vtkm::Float32, 3> Up;
|
||||
@ -194,426 +68,110 @@ private:
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> ViewProjectionMat;
|
||||
|
||||
public:
|
||||
ColorBuffer4f FrameBuffer;
|
||||
VTKM_CONT
|
||||
Camera();
|
||||
|
||||
VTKM_CONT
|
||||
Camera()
|
||||
{
|
||||
this->Height = 500;
|
||||
this->Width = 500;
|
||||
this->SubsetWidth = 500;
|
||||
this->SubsetHeight = 500;
|
||||
this->SubsetMinX = 0;
|
||||
this->SubsetMinY = 0;
|
||||
this->FovY = 30.f;
|
||||
this->FovX = 30.f;
|
||||
this->Zoom = 1.f;
|
||||
this->Look[0] = 0.f;
|
||||
this->Look[1] = 0.f;
|
||||
this->Look[2] = -1.f;
|
||||
this->LookAt[0] = 0.f;
|
||||
this->LookAt[1] = 0.f;
|
||||
this->LookAt[2] = -1.f;
|
||||
this->Up[0] = 0.f;
|
||||
this->Up[1] = 1.f;
|
||||
this->Up[2] = 0.f;
|
||||
this->Position[0] = 0.f;
|
||||
this->Position[1] = 0.f;
|
||||
this->Position[2] = 0.f;
|
||||
this->IsViewDirty = true;
|
||||
this->IsResDirty = true;
|
||||
this->MortonSort = false;
|
||||
this->FrameBuffer.Allocate(Height * Width);
|
||||
//this->ImageSubsetModeOn = true;
|
||||
}
|
||||
~Camera();
|
||||
|
||||
// cuda does not compile if this is private
|
||||
class PerspectiveRayGen;
|
||||
|
||||
std::string ToString();
|
||||
|
||||
VTKM_CONT
|
||||
void SetParameters(const vtkm::rendering::Camera& camera,
|
||||
const vtkm::rendering::CanvasRayTracer& canvas)
|
||||
{
|
||||
this->SetUp(camera.GetViewUp());
|
||||
this->SetLookAt(camera.GetLookAt());
|
||||
this->SetPosition(camera.GetPosition());
|
||||
this->SetFieldOfView(camera.GetFieldOfView());
|
||||
this->SetHeight(static_cast<vtkm::Int32>(canvas.GetHeight()));
|
||||
this->SetWidth(static_cast<vtkm::Int32>(canvas.GetWidth()));
|
||||
this->CameraView = camera;
|
||||
}
|
||||
vtkm::rendering::CanvasRayTracer& canvas);
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
void SetHeight(const vtkm::Int32& height)
|
||||
{
|
||||
if (height <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera height must be greater than zero.");
|
||||
}
|
||||
if (Height != height)
|
||||
{
|
||||
this->IsResDirty = true;
|
||||
this->Height = height;
|
||||
this->SetFieldOfView(this->FovX);
|
||||
}
|
||||
}
|
||||
void SetHeight(const vtkm::Int32& height);
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 GetHeight() const { return this->Height; }
|
||||
void WriteSettingsToLog();
|
||||
|
||||
VTKM_CONT
|
||||
void SetWidth(const vtkm::Int32& width)
|
||||
{
|
||||
if (width <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera width must be greater than zero.");
|
||||
}
|
||||
if (this->Width != width)
|
||||
{
|
||||
this->IsResDirty = true;
|
||||
this->Width = width;
|
||||
this->SetFieldOfView(this->FovX);
|
||||
}
|
||||
}
|
||||
vtkm::Int32 GetHeight() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Int32 GetWidth() const { return this->Width; }
|
||||
void SetWidth(const vtkm::Int32& width);
|
||||
|
||||
VTKM_CONT
|
||||
void SetZoom(const vtkm::Float32& zoom)
|
||||
{
|
||||
if (zoom <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera zoom must be greater than zero.");
|
||||
}
|
||||
if (this->Zoom != zoom)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
this->Zoom = zoom;
|
||||
}
|
||||
}
|
||||
vtkm::Int32 GetWidth() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float32 GetZoom() const { return this->Zoom; }
|
||||
vtkm::Int32 GetSubsetWidth() const;
|
||||
|
||||
VTKM_CONT
|
||||
void SetFieldOfView(const vtkm::Float32& degrees)
|
||||
{
|
||||
if (degrees <= 0)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera feild of view must be greater than zero.");
|
||||
}
|
||||
if (degrees > 180)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera feild of view must be less than 180.");
|
||||
}
|
||||
// fov is stored as a half angle
|
||||
// float fovx= 2.f*atan(tan(view.view3d.fov/2.f)*view.w/view.h);
|
||||
// fovx*=180.f/M_PI;
|
||||
// camera->setFOVY((view.view3d.fov*(180.f/M_PI))/2.f);
|
||||
// camera->setFOVX( fovx/2.f );
|
||||
|
||||
vtkm::Float32 newFOVY = (vtkm::Float32(this->Height) / vtkm::Float32(this->Width)) * degrees;
|
||||
vtkm::Float32 newFOVX = degrees;
|
||||
if (newFOVX != this->FovX)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
if (newFOVY != this->FovY)
|
||||
{
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
this->FovX = newFOVX;
|
||||
this->FovY = newFOVY;
|
||||
this->CameraView.SetFieldOfView(this->FovX);
|
||||
}
|
||||
vtkm::Int32 GetSubsetHeight() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Float32 GetFieldOfView() const { return this->FovX; }
|
||||
void SetZoom(const vtkm::Float32& zoom);
|
||||
|
||||
VTKM_CONT
|
||||
void SetUp(const vtkm::Vec<vtkm::Float32, 3>& up)
|
||||
{
|
||||
if (this->Up != up)
|
||||
{
|
||||
this->Up = up;
|
||||
vtkm::Normalize(this->Up);
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
vtkm::Float32 GetZoom() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> GetUp() const { return this->Up; }
|
||||
void SetFieldOfView(const vtkm::Float32& degrees);
|
||||
|
||||
VTKM_CONT
|
||||
void SetLookAt(const vtkm::Vec<vtkm::Float32, 3>& lookAt)
|
||||
{
|
||||
if (this->LookAt != lookAt)
|
||||
{
|
||||
this->LookAt = lookAt;
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
vtkm::Float32 GetFieldOfView() const;
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> GetLookAt() const { return this->LookAt; }
|
||||
void SetUp(const vtkm::Vec<vtkm::Float32, 3>& up);
|
||||
|
||||
VTKM_CONT
|
||||
void SetPosition(const vtkm::Vec<vtkm::Float32, 3>& position)
|
||||
{
|
||||
if (this->Position != position)
|
||||
{
|
||||
this->Position = position;
|
||||
this->IsViewDirty = true;
|
||||
}
|
||||
}
|
||||
void SetPosition(const vtkm::Vec<vtkm::Float32, 3>& position);
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::Vec<vtkm::Float32, 3> GetPosition() const { return this->Position; }
|
||||
vtkm::Vec<vtkm::Float32, 3> GetPosition() const;
|
||||
|
||||
VTKM_CONT
|
||||
void ResetIsViewDirty() { this->IsViewDirty = false; }
|
||||
vtkm::Vec<vtkm::Float32, 3> GetUp() const;
|
||||
|
||||
VTKM_CONT
|
||||
bool GetIsViewDirty() const { return this->IsViewDirty; }
|
||||
void SetLookAt(const vtkm::Vec<vtkm::Float32, 3>& lookAt);
|
||||
|
||||
VTKM_CONT
|
||||
void WriteToSurface(CanvasRayTracer* canvas,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Float32>& distances)
|
||||
{
|
||||
if (canvas == nullptr)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera can not write to nullptr canvas");
|
||||
}
|
||||
if (this->Height != vtkm::Int32(canvas->GetHeight()) ||
|
||||
this->Width != vtkm::Int32(canvas->GetWidth()))
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Camera: suface-view mismatched dims");
|
||||
}
|
||||
vtkm::worklet::DispatcherMapField<SurfaceConverter>(
|
||||
SurfaceConverter(
|
||||
this->Width,
|
||||
this->SubsetWidth,
|
||||
this->SubsetMinX,
|
||||
this->SubsetMinY,
|
||||
this->CameraView.CreateProjectionMatrix(canvas->GetWidth(), canvas->GetHeight()),
|
||||
this->SubsetWidth * this->SubsetHeight))
|
||||
.Invoke(
|
||||
this->FrameBuffer,
|
||||
distances,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Float32>(canvas->GetDepthBuffer()),
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Float32, 4>>(canvas->GetColorBuffer()));
|
||||
|
||||
//Force the transfer so the vectors contain data from device
|
||||
canvas->GetColorBuffer().GetPortalControl().Get(0);
|
||||
canvas->GetDepthBuffer().GetPortalControl().Get(0);
|
||||
}
|
||||
vtkm::Vec<vtkm::Float32, 3> GetLookAt() const;
|
||||
|
||||
VTKM_CONT
|
||||
void CreateRays(Ray<DeviceAdapter>& rays, const vtkm::Bounds boundingBox = vtkm::Bounds())
|
||||
{
|
||||
this->UpdateDimensions(&rays, boundingBox);
|
||||
//Set the origin of the ray back to the camera position
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Float32>>(
|
||||
MemSet<vtkm::Float32>(this->Position[0]))
|
||||
.Invoke(rays.OriginX);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Float32>>(
|
||||
MemSet<vtkm::Float32>(this->Position[1]))
|
||||
.Invoke(rays.OriginY);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Float32>>(
|
||||
MemSet<vtkm::Float32>(this->Position[2]))
|
||||
.Invoke(rays.OriginZ);
|
||||
|
||||
//Reset the camera look vector
|
||||
this->Look = this->LookAt - this->Position;
|
||||
vtkm::Normalize(this->Look);
|
||||
//Create the ray direction
|
||||
vtkm::worklet::DispatcherMapField<PerspectiveRayGen>(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); //X Y Z
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Float32>>(MemSet<vtkm::Float32>(1e12f))
|
||||
.Invoke(rays.Distance);
|
||||
|
||||
//Reset the Rays Hit Index to -2
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::Id>>(MemSet<vtkm::Id>(-2)).Invoke(rays.HitIdx);
|
||||
|
||||
} //create rays
|
||||
void ResetIsViewDirty();
|
||||
|
||||
VTKM_CONT
|
||||
void CreateRays(VolumeRay<DeviceAdapter>& rays, const vtkm::Bounds& boundingBox = vtkm::Bounds())
|
||||
{
|
||||
bool GetIsViewDirty() const;
|
||||
|
||||
this->UpdateDimensions(&rays, boundingBox);
|
||||
VTKM_CONT
|
||||
void CreateRays(Ray<vtkm::Float32>& rays, const vtkm::cont::CoordinateSystem& coords);
|
||||
VTKM_CONT
|
||||
void CreateRays(Ray<vtkm::Float64>& rays, const vtkm::cont::CoordinateSystem& coords);
|
||||
|
||||
//Reset the camera look vector
|
||||
this->Look = this->LookAt - this->Position;
|
||||
vtkm::Normalize(this->Look);
|
||||
//Create the ray direction
|
||||
vtkm::worklet::DispatcherMapField<PerspectiveRayGen>(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); //X Y Z
|
||||
VTKM_CONT
|
||||
void GetPixelData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::Int32& activePixels,
|
||||
vtkm::Float32& aveRayDistance);
|
||||
|
||||
} //create rays
|
||||
template <typename Precision, typename DeviceAdapter>
|
||||
VTKM_CONT void CreateRaysOnDevice(Ray<Precision>& rays,
|
||||
DeviceAdapter,
|
||||
const vtkm::Bounds boundingBox);
|
||||
|
||||
void CreateDebugRay(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<vtkm::Float32>& rays);
|
||||
|
||||
void CreateDebugRay(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<vtkm::Float64>& rays);
|
||||
|
||||
bool operator==(const Camera& other) const;
|
||||
|
||||
private:
|
||||
template <typename Precision>
|
||||
void CreateDebugRayImp(vtkm::Vec<vtkm::Int32, 2> pixel, Ray<Precision>& rays);
|
||||
VTKM_CONT
|
||||
void FindSubset(const vtkm::Bounds& bounds)
|
||||
{
|
||||
vtkm::Float32 x[2], y[2], z[2];
|
||||
x[0] = static_cast<vtkm::Float32>(bounds.X.Min);
|
||||
x[1] = static_cast<vtkm::Float32>(bounds.X.Max);
|
||||
y[0] = static_cast<vtkm::Float32>(bounds.Y.Min);
|
||||
y[1] = static_cast<vtkm::Float32>(bounds.Y.Max);
|
||||
z[0] = static_cast<vtkm::Float32>(bounds.Z.Min);
|
||||
z[1] = static_cast<vtkm::Float32>(bounds.Z.Max);
|
||||
//Inise the data bounds
|
||||
if (this->Position[0] >= x[0] && this->Position[0] <= x[1] && this->Position[1] >= y[0] &&
|
||||
this->Position[1] <= y[1] && this->Position[2] >= z[0] && this->Position[2] <= z[1])
|
||||
{
|
||||
this->SubsetWidth = this->Width;
|
||||
this->SubsetHeight = this->Height;
|
||||
this->SubsetMinY = 0;
|
||||
this->SubsetMinX = 0;
|
||||
return;
|
||||
}
|
||||
void FindSubset(const vtkm::Bounds& bounds);
|
||||
|
||||
//std::cout<<"Bounds ("<<x[0]<<","<<y[0]<<","<<z[0]<<")-("<<x[1]<<","<<y[1]<<","<<z[1]<<std::endl;
|
||||
vtkm::Float32 xmin, ymin, xmax, ymax, zmin, zmax;
|
||||
xmin = vtkm::Infinity32();
|
||||
ymin = vtkm::Infinity32();
|
||||
zmin = vtkm::Infinity32();
|
||||
xmax = vtkm::NegativeInfinity32();
|
||||
ymax = vtkm::NegativeInfinity32();
|
||||
zmax = vtkm::NegativeInfinity32();
|
||||
vtkm::Vec<vtkm::Float32, 4> extentPoint;
|
||||
for (vtkm::Int32 i = 0; i < 2; ++i)
|
||||
for (vtkm::Int32 j = 0; j < 2; ++j)
|
||||
for (vtkm::Int32 k = 0; k < 2; ++k)
|
||||
{
|
||||
extentPoint[0] = x[i];
|
||||
extentPoint[1] = y[j];
|
||||
extentPoint[2] = z[k];
|
||||
extentPoint[3] = 1.f;
|
||||
vtkm::Vec<vtkm::Float32, 4> transformed =
|
||||
vtkm::MatrixMultiply(this->ViewProjectionMat, extentPoint);
|
||||
// perform the perspective divide
|
||||
for (vtkm::Int32 a = 0; a < 3; ++a)
|
||||
{
|
||||
transformed[a] = transformed[a] / transformed[3];
|
||||
}
|
||||
|
||||
transformed[0] = (transformed[0] * 0.5f + 0.5f) * static_cast<vtkm::Float32>(Width);
|
||||
transformed[1] = (transformed[1] * 0.5f + 0.5f) * static_cast<vtkm::Float32>(Height);
|
||||
transformed[2] = (transformed[2] * 0.5f + 0.5f);
|
||||
zmin = vtkm::Min(zmin, transformed[2]);
|
||||
zmax = vtkm::Max(zmax, transformed[2]);
|
||||
if (transformed[2] < 0 || transformed[2] > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
xmin = vtkm::Min(xmin, transformed[0]);
|
||||
ymin = vtkm::Min(ymin, transformed[1]);
|
||||
xmax = vtkm::Max(xmax, transformed[0]);
|
||||
ymax = vtkm::Max(ymax, transformed[1]);
|
||||
}
|
||||
|
||||
xmin -= .001f;
|
||||
xmax += .001f;
|
||||
ymin -= .001f;
|
||||
ymax += .001f;
|
||||
xmin = vtkm::Floor(vtkm::Min(vtkm::Max(0.f, xmin), vtkm::Float32(Width)));
|
||||
xmax = vtkm::Ceil(vtkm::Min(vtkm::Max(0.f, xmax), vtkm::Float32(Width)));
|
||||
ymin = vtkm::Floor(vtkm::Min(vtkm::Max(0.f, ymin), vtkm::Float32(Height)));
|
||||
ymax = vtkm::Ceil(vtkm::Min(vtkm::Max(0.f, ymax), vtkm::Float32(Height)));
|
||||
|
||||
//printf("Pixel range = (%f,%f,%f), (%f,%f,%f)\n", xmin, ymin,zmin, xmax,ymax,zmax);
|
||||
vtkm::Int32 dx = vtkm::Int32(xmax) - vtkm::Int32(xmin);
|
||||
vtkm::Int32 dy = vtkm::Int32(ymax) - vtkm::Int32(ymin);
|
||||
|
||||
//
|
||||
// scene is behind the camera
|
||||
//
|
||||
if (zmax < 0 || zmin > 1 || xmin >= xmax || ymin >= ymax)
|
||||
{
|
||||
this->SubsetWidth = 1;
|
||||
this->SubsetHeight = 1;
|
||||
this->SubsetMinX = 0;
|
||||
this->SubsetMinY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SubsetWidth = dx;
|
||||
this->SubsetHeight = dy;
|
||||
this->SubsetMinX = vtkm::Int32(xmin);
|
||||
this->SubsetMinY = vtkm::Int32(ymin);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void UpdateDimensions(RayBase* rays, const vtkm::Bounds& boundingBox = vtkm::Bounds())
|
||||
{
|
||||
// If bounds have been provided, only cast rays that could hit the data
|
||||
bool imageSubsetModeOn = boundingBox.IsNonEmpty();
|
||||
|
||||
//Update our ViewProjection matrix
|
||||
this->ViewProjectionMat =
|
||||
vtkm::MatrixMultiply(this->CameraView.CreateProjectionMatrix(this->Width, this->Height),
|
||||
this->CameraView.CreateViewMatrix());
|
||||
|
||||
//Find the pixel footprint
|
||||
if (imageSubsetModeOn)
|
||||
{
|
||||
this->FindSubset(boundingBox);
|
||||
}
|
||||
|
||||
//Update the image dimensions
|
||||
if (!imageSubsetModeOn)
|
||||
{
|
||||
this->SubsetWidth = this->Width;
|
||||
this->SubsetHeight = this->Height;
|
||||
this->SubsetMinY = 0;
|
||||
this->SubsetMinX = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->SubsetWidth != this->Width)
|
||||
{
|
||||
this->IsResDirty = true;
|
||||
}
|
||||
if (this->SubsetHeight != this->Height)
|
||||
{
|
||||
this->IsResDirty = true;
|
||||
}
|
||||
}
|
||||
// resize rays and buffers
|
||||
if (this->IsResDirty)
|
||||
{
|
||||
rays->resize(this->SubsetHeight * this->SubsetWidth);
|
||||
this->FrameBuffer.PrepareForOutput(this->SubsetHeight * this->SubsetWidth, DeviceAdapter());
|
||||
}
|
||||
|
||||
this->IsResDirty = false;
|
||||
}
|
||||
template <typename DeviceAdapter, typename Precision>
|
||||
VTKM_CONT void UpdateDimensions(Ray<Precision>& rays,
|
||||
DeviceAdapter,
|
||||
const vtkm::Bounds& boundingBox);
|
||||
|
||||
}; // class camera
|
||||
}
|
||||
|
468
vtkm/rendering/raytracing/CellIntersector.h
Normal file
468
vtkm/rendering/raytracing/CellIntersector.h
Normal file
@ -0,0 +1,468 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Cell_Intersector_h
|
||||
#define vtk_m_rendering_raytracing_Cell_Intersector_h
|
||||
|
||||
#include <vtkm/rendering/raytracing/CellTables.h>
|
||||
#include <vtkm/rendering/raytracing/TriangleIntersector.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
//
|
||||
// Any supported element. If the cell shape is not
|
||||
// supported it does nothing, e.g. a 2D cellkk.
|
||||
//
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectZoo(T xpoints[8],
|
||||
T ypoints[8],
|
||||
T zpoints[8],
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T distances[6],
|
||||
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);
|
||||
const vtkm::Int32 tableOffset = ZooLookUp[CellTypeLookUp[shapeType]][0];
|
||||
const vtkm::Int32 numTriangles = ZooLookUp[CellTypeLookUp[shapeType]][1];
|
||||
// Decompose each face into two triangles
|
||||
for (int i = 0; i < 6; ++i)
|
||||
distances[i] = -1.;
|
||||
for (int i = 0; i < numTriangles; ++i)
|
||||
{
|
||||
const vtkm::Int32 offset = tableOffset + i;
|
||||
vtkm::Vec<T, 3> a, c, b;
|
||||
a[0] = xpoints[ZooTable[offset][1]];
|
||||
a[1] = ypoints[ZooTable[offset][1]];
|
||||
a[2] = zpoints[ZooTable[offset][1]];
|
||||
b[0] = xpoints[ZooTable[offset][2]];
|
||||
b[1] = ypoints[ZooTable[offset][2]];
|
||||
b[2] = zpoints[ZooTable[offset][2]];
|
||||
c[0] = xpoints[ZooTable[offset][3]];
|
||||
c[1] = ypoints[ZooTable[offset][3]];
|
||||
c[2] = zpoints[ZooTable[offset][3]];
|
||||
const vtkm::Int32 faceId = ZooTable[offset][0];
|
||||
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]);
|
||||
|
||||
if (distance != -1.f)
|
||||
{
|
||||
if (distances[faceId] != -1.f)
|
||||
distances[faceId] = vtkm::Min(distance, distances[faceId]);
|
||||
else
|
||||
distances[faceId] = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectHex(T xpoints[8],
|
||||
T ypoints[8],
|
||||
T zpoints[8],
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
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);
|
||||
// Decompose each face into two triangles
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
vtkm::Vec<T, 3> a, c, b, d;
|
||||
a[0] = xpoints[ShapesFaceList[i][1]];
|
||||
a[1] = ypoints[ShapesFaceList[i][1]];
|
||||
a[2] = zpoints[ShapesFaceList[i][1]];
|
||||
b[0] = xpoints[ShapesFaceList[i][2]];
|
||||
b[1] = ypoints[ShapesFaceList[i][2]];
|
||||
b[2] = zpoints[ShapesFaceList[i][2]];
|
||||
c[0] = xpoints[ShapesFaceList[i][3]];
|
||||
c[1] = ypoints[ShapesFaceList[i][3]];
|
||||
c[2] = zpoints[ShapesFaceList[i][3]];
|
||||
d[0] = xpoints[ShapesFaceList[i][4]];
|
||||
d[1] = ypoints[ShapesFaceList[i][4]];
|
||||
d[2] = zpoints[ShapesFaceList[i][4]];
|
||||
T distance = -1.f;
|
||||
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]);
|
||||
|
||||
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]);
|
||||
|
||||
|
||||
|
||||
if (distance != -1.f)
|
||||
{
|
||||
if (distances[i] != -1.f)
|
||||
distances[i] = vtkm::Min(distance, distances[i]);
|
||||
else
|
||||
distances[i] = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectTet(T xpoints[8],
|
||||
T ypoints[8],
|
||||
T zpoints[8],
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
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);
|
||||
|
||||
const vtkm::Int32 tableOffset = FaceLookUp[CellTypeLookUp[CELL_SHAPE_TETRA]][0];
|
||||
for (vtkm::Int32 i = 0; i < 4; ++i)
|
||||
{
|
||||
vtkm::Vec<T, 3> a, c, b;
|
||||
a[0] = xpoints[ShapesFaceList[i + tableOffset][1]];
|
||||
a[1] = ypoints[ShapesFaceList[i + tableOffset][1]];
|
||||
a[2] = zpoints[ShapesFaceList[i + tableOffset][1]];
|
||||
b[0] = xpoints[ShapesFaceList[i + tableOffset][2]];
|
||||
b[1] = ypoints[ShapesFaceList[i + tableOffset][2]];
|
||||
b[2] = zpoints[ShapesFaceList[i + tableOffset][2]];
|
||||
c[0] = xpoints[ShapesFaceList[i + tableOffset][3]];
|
||||
c[1] = ypoints[ShapesFaceList[i + tableOffset][3]];
|
||||
c[2] = zpoints[ShapesFaceList[i + tableOffset][3]];
|
||||
T distance = -1.f;
|
||||
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]);
|
||||
|
||||
if (distance != -1.f)
|
||||
distances[i] = distance;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Wedge
|
||||
//
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectWedge(T xpoints[8],
|
||||
T ypoints[8],
|
||||
T zpoints[8],
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
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);
|
||||
// TODO: try two sepate loops to see performance impact
|
||||
const vtkm::Int32 tableOffset = FaceLookUp[CellTypeLookUp[CELL_SHAPE_WEDGE]][0];
|
||||
// Decompose each face into two triangles
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
vtkm::Vec<T, 3> a, c, b, d;
|
||||
a[0] = xpoints[ShapesFaceList[i + tableOffset][1]];
|
||||
a[1] = ypoints[ShapesFaceList[i + tableOffset][1]];
|
||||
a[2] = zpoints[ShapesFaceList[i + tableOffset][1]];
|
||||
b[0] = xpoints[ShapesFaceList[i + tableOffset][2]];
|
||||
b[1] = ypoints[ShapesFaceList[i + tableOffset][2]];
|
||||
b[2] = zpoints[ShapesFaceList[i + tableOffset][2]];
|
||||
c[0] = xpoints[ShapesFaceList[i + tableOffset][3]];
|
||||
c[1] = ypoints[ShapesFaceList[i + tableOffset][3]];
|
||||
c[2] = zpoints[ShapesFaceList[i + tableOffset][3]];
|
||||
d[0] = xpoints[ShapesFaceList[i + tableOffset][4]];
|
||||
d[1] = ypoints[ShapesFaceList[i + tableOffset][4]];
|
||||
d[2] = zpoints[ShapesFaceList[i + tableOffset][4]];
|
||||
T distance = -1.f;
|
||||
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]);
|
||||
|
||||
if (distance != -1.f)
|
||||
distances[i] = distance;
|
||||
//
|
||||
//First two faces are triangles
|
||||
//
|
||||
if (i < 2)
|
||||
continue;
|
||||
distance = -1.f;
|
||||
|
||||
intersector.IntersectTriSn(a,
|
||||
c,
|
||||
d,
|
||||
sx,
|
||||
sy,
|
||||
sz,
|
||||
kx,
|
||||
ky,
|
||||
kz,
|
||||
distance,
|
||||
uNotUsed,
|
||||
vNotUsed,
|
||||
origin[0],
|
||||
origin[1],
|
||||
origin[2]);
|
||||
|
||||
if (distance != -1.f)
|
||||
{
|
||||
if (distances[i] != -1.f)
|
||||
distances[i] = vtkm::Min(distance, distances[i]);
|
||||
else
|
||||
distances[i] = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// General Template should never be instantiated
|
||||
//
|
||||
|
||||
template <int CellType>
|
||||
class CellIntersector
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* vtkmNotUsed(xpoints),
|
||||
T* vtkmNotUsed(ypoints),
|
||||
T* vtkmNotUsed(zpoints),
|
||||
const vtkm::Vec<T, 3>& vtkmNotUsed(dir),
|
||||
const vtkm::Vec<T, 3>& vtkmNotUsed(origin),
|
||||
T* vtkmNotUsed(distances),
|
||||
const vtkm::UInt8 vtkmNotUsed(cellShape = 12));
|
||||
};
|
||||
|
||||
//
|
||||
// Hex Specialization
|
||||
//
|
||||
template <>
|
||||
class CellIntersector<CELL_SHAPE_HEXAHEDRON>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
|
||||
T* ypoints,
|
||||
T* zpoints,
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T* distances,
|
||||
const vtkm::UInt8 cellShape = 12) const
|
||||
{
|
||||
if (cellShape == 12)
|
||||
{
|
||||
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("CellIntersector Hex Error: unsupported cell type. Doing nothing\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
//
|
||||
//
|
||||
// Hex Specialization Structured
|
||||
//
|
||||
template <>
|
||||
class CellIntersector<254>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
|
||||
T* ypoints,
|
||||
T* zpoints,
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T* distances,
|
||||
const vtkm::UInt8 cellShape = 12) const
|
||||
{
|
||||
if (cellShape == 12)
|
||||
{
|
||||
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("CellIntersector Hex Error: unsupported cell type. Doing nothing\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Tet Specialization
|
||||
//
|
||||
template <>
|
||||
class CellIntersector<CELL_SHAPE_TETRA>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
|
||||
T* ypoints,
|
||||
T* zpoints,
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T distances[6],
|
||||
const vtkm::UInt8 cellShape = 12) const
|
||||
{
|
||||
if (cellShape == CELL_SHAPE_TETRA)
|
||||
{
|
||||
IntersectTet(xpoints, ypoints, zpoints, dir, origin, distances);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("CellIntersector Tet Error: unsupported cell type. Doing nothing\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Wedge Specialization
|
||||
//
|
||||
template <>
|
||||
class CellIntersector<CELL_SHAPE_WEDGE>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
|
||||
T* ypoints,
|
||||
T* zpoints,
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T distances[6],
|
||||
const vtkm::UInt8 cellShape = 12) const
|
||||
{
|
||||
if (cellShape == CELL_SHAPE_WEDGE)
|
||||
{
|
||||
IntersectWedge(xpoints, ypoints, zpoints, dir, origin, distances);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("CellIntersector Wedge Error: unsupported cell type. Doing nothing\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
//
|
||||
// Zoo elements
|
||||
//
|
||||
template <>
|
||||
class CellIntersector<255>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void IntersectCell(T* xpoints,
|
||||
T* ypoints,
|
||||
T* zpoints,
|
||||
const vtkm::Vec<T, 3>& dir,
|
||||
const vtkm::Vec<T, 3>& origin,
|
||||
T distances[6],
|
||||
const vtkm::UInt8 cellShape = 0) const
|
||||
{
|
||||
IntersectZoo(xpoints, ypoints, zpoints, dir, origin, distances, cellShape);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
317
vtkm/rendering/raytracing/CellSampler.h
Normal file
317
vtkm/rendering/raytracing/CellSampler.h
Normal file
@ -0,0 +1,317 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_CellSampler_h
|
||||
#define vtk_m_rendering_raytracing_CellSampler_h
|
||||
|
||||
#include <vtkm/VecVariable.h>
|
||||
#include <vtkm/exec/CellInterpolate.h>
|
||||
#include <vtkm/exec/ParametricCoordinates.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
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename CellTag>
|
||||
VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints(CellTag tag);
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints<vtkm::CellShapeTagHexahedron>(
|
||||
vtkm::CellShapeTagHexahedron vtkmNotUsed(tag))
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints<vtkm::CellShapeTagTetra>(
|
||||
vtkm::CellShapeTagTetra vtkmNotUsed(tag))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints<vtkm::CellShapeTagWedge>(
|
||||
vtkm::CellShapeTagWedge vtkmNotUsed(tag))
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline vtkm::Int32 GetNumberOfPoints<vtkm::CellShapeTagPyramid>(
|
||||
vtkm::CellShapeTagPyramid vtkmNotUsed(tag))
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
template <typename P, typename S, typename WorkletType, typename CellShapeTagType>
|
||||
VTKM_EXEC_CONT inline bool Sample(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const CellShapeTagType& shapeTag)
|
||||
{
|
||||
|
||||
bool validSample = true;
|
||||
vtkm::VecVariable<vtkm::Vec<P, 3>, 8> pointsVec;
|
||||
vtkm::VecVariable<S, 8> scalarVec;
|
||||
for (vtkm::Int32 i = 0; i < GetNumberOfPoints(shapeTag); ++i)
|
||||
{
|
||||
pointsVec.Append(points[i]);
|
||||
scalarVec.Append(scalars[i]);
|
||||
}
|
||||
vtkm::Vec<P, 3> pcoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
|
||||
pointsVec, sampleLocation, shapeTag, callingWorklet);
|
||||
P pmin, pmax;
|
||||
pmin = vtkm::Min(vtkm::Min(pcoords[0], pcoords[1]), pcoords[2]);
|
||||
pmax = vtkm::Max(vtkm::Max(pcoords[0], pcoords[1]), pcoords[2]);
|
||||
if (pmin < 0.f || pmax > 1.f)
|
||||
{
|
||||
validSample = false;
|
||||
}
|
||||
lerpedScalar = vtkm::exec::CellInterpolate(scalarVec, pcoords, shapeTag, callingWorklet);
|
||||
return validSample;
|
||||
}
|
||||
|
||||
template <typename S, typename P, typename WorkletType, typename CellShapeTagType>
|
||||
VTKM_EXEC_CONT inline bool Sample(const vtkm::VecRectilinearPointCoordinates<3>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const CellShapeTagType& vtkmNotUsed(shapeTag))
|
||||
{
|
||||
|
||||
bool validSample = true;
|
||||
vtkm::Vec<P, 3> pcoords = vtkm::exec::WorldCoordinatesToParametricCoordinates(
|
||||
points, sampleLocation, vtkm::CellShapeTagHexahedron(), callingWorklet);
|
||||
P pmin, pmax;
|
||||
pmin = vtkm::Min(vtkm::Min(pcoords[0], pcoords[1]), pcoords[2]);
|
||||
pmax = vtkm::Max(vtkm::Max(pcoords[0], pcoords[1]), pcoords[2]);
|
||||
if (pmin < 0.f || pmax > 1.f)
|
||||
{
|
||||
validSample = false;
|
||||
}
|
||||
lerpedScalar =
|
||||
vtkm::exec::CellInterpolate(scalars, pcoords, vtkm::CellShapeTagHexahedron(), callingWorklet);
|
||||
return validSample;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// General Template: returns false if sample location is outside the cell
|
||||
//
|
||||
template <int CellType>
|
||||
class CellSampler
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& vtkmNotUsed(points),
|
||||
const vtkm::Vec<S, 8>& vtkmNotUsed(scalars),
|
||||
const vtkm::Vec<P, 3>& vtkmNotUsed(sampleLocation),
|
||||
S& vtkmNotUsed(lerpedScalar),
|
||||
const WorkletType& vtkmNotUsed(callingWorklet),
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CellType)) const
|
||||
{
|
||||
static_assert(CellType != CELL_SHAPE_ZOO && CellType != CELL_SHAPE_STRUCTURED &&
|
||||
CellType != CELL_SHAPE_HEXAHEDRON && CellType != CELL_SHAPE_TETRA &&
|
||||
CellType != CELL_SHAPE_WEDGE && CellType != CELL_SHAPE_PYRAMID,
|
||||
"Cell Sampler: Default template. This should not happen.\n");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Zoo Sampler
|
||||
//
|
||||
template <>
|
||||
class CellSampler<255>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& cellShape) const
|
||||
{
|
||||
bool valid = false;
|
||||
if (cellShape == CELL_SHAPE_HEXAHEDRON)
|
||||
{
|
||||
valid = detail::Sample(points,
|
||||
scalars,
|
||||
sampleLocation,
|
||||
lerpedScalar,
|
||||
callingWorklet,
|
||||
vtkm::CellShapeTagHexahedron());
|
||||
}
|
||||
|
||||
if (cellShape == CELL_SHAPE_TETRA)
|
||||
{
|
||||
valid = detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagTetra());
|
||||
}
|
||||
|
||||
if (cellShape == CELL_SHAPE_WEDGE)
|
||||
{
|
||||
valid = detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagWedge());
|
||||
}
|
||||
if (cellShape == CELL_SHAPE_PYRAMID)
|
||||
{
|
||||
valid = detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagPyramid());
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Single type hex
|
||||
//
|
||||
template <>
|
||||
class CellSampler<CELL_SHAPE_HEXAHEDRON>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(
|
||||
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_HEXAHEDRON)) const
|
||||
{
|
||||
return detail::Sample(points,
|
||||
scalars,
|
||||
sampleLocation,
|
||||
lerpedScalar,
|
||||
callingWorklet,
|
||||
vtkm::CellShapeTagHexahedron());
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Single type hex uniform and rectilinear
|
||||
// calls fast path for sampling
|
||||
//
|
||||
template <>
|
||||
class CellSampler<CELL_SHAPE_STRUCTURED>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(
|
||||
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_HEXAHEDRON)) const
|
||||
{
|
||||
vtkm::VecRectilinearPointCoordinates<3> rPoints(points[0], points[6] - points[0]);
|
||||
return detail::Sample(rPoints,
|
||||
scalars,
|
||||
sampleLocation,
|
||||
lerpedScalar,
|
||||
callingWorklet,
|
||||
vtkm::CellShapeTagHexahedron());
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Single type pyramid
|
||||
//
|
||||
template <>
|
||||
class CellSampler<CELL_SHAPE_PYRAMID>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(
|
||||
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_PYRAMID)) const
|
||||
{
|
||||
return detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagPyramid());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Single type Tet
|
||||
//
|
||||
template <>
|
||||
class CellSampler<CELL_SHAPE_TETRA>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(
|
||||
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_TETRA)) const
|
||||
{
|
||||
return detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagTetra());
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Single type Wedge
|
||||
//
|
||||
template <>
|
||||
class CellSampler<CELL_SHAPE_WEDGE>
|
||||
{
|
||||
public:
|
||||
template <typename P, typename S, typename WorkletType>
|
||||
VTKM_EXEC_CONT inline bool SampleCell(
|
||||
const vtkm::Vec<vtkm::Vec<P, 3>, 8>& points,
|
||||
const vtkm::Vec<S, 8>& scalars,
|
||||
const vtkm::Vec<P, 3>& sampleLocation,
|
||||
S& lerpedScalar,
|
||||
const WorkletType& callingWorklet,
|
||||
const vtkm::Int32& vtkmNotUsed(cellShape = CELL_SHAPE_WEDGE)) const
|
||||
{
|
||||
return detail::Sample(
|
||||
points, scalars, sampleLocation, lerpedScalar, callingWorklet, vtkm::CellShapeTagWedge());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
132
vtkm/rendering/raytracing/CellTables.h
Normal file
132
vtkm/rendering/raytracing/CellTables.h
Normal file
@ -0,0 +1,132 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_CellTables_h
|
||||
#define vtk_m_rendering_raytracing_CellTables_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/internal/ExportMacros.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
//LookUp of Shapes to FaceLookUp
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 CellTypeLookUp[15] = {
|
||||
4, // 0 Nothing
|
||||
4, // 1 Vertex
|
||||
4, // 2 (Not Used) Poly Vertex
|
||||
4, // 3 Line
|
||||
4, // 4 (Not Used) Poly Line
|
||||
4, // 5 Triangle
|
||||
4, // 6 (not used) triangle strip
|
||||
4, // 7 Polygon
|
||||
4, // 8 (Not used)Pixel
|
||||
4, // 9 Quad
|
||||
1, // 10 Tetra
|
||||
4, // 11 (Not used) Voxel
|
||||
0, // 12 Hex
|
||||
2, // 13 Wedge
|
||||
3 // 14 Pyramid
|
||||
};
|
||||
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 FaceLookUp[5][3] = {
|
||||
{ 0, 6, 8 }, //hex offset into shapes face list, num faces and number of Indices
|
||||
{ 6, 4, 4 }, //tet
|
||||
{ 10, 5, 6 }, //wedge
|
||||
{ 15, 5, 5 }, //pyramid
|
||||
{ -1, 0, 0 } //unsupported shape
|
||||
};
|
||||
|
||||
// The convention for the faces is that looking from the outside of
|
||||
// the shape at a face, triangles should wind CCW.
|
||||
// Quads are broken up by {4=quad,a,b,c,d}:
|
||||
// t1 = abc and t2 = acd. Indices of the face are ordered CW, and the mapping
|
||||
// of t1 and t2 become CCW.
|
||||
// Since we know the triangle winding, we could tell
|
||||
// if we hit an inside face or outside face.
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 ShapesFaceList[20][5] = {
|
||||
//hex
|
||||
{ 4, 0, 1, 5, 4 }, //face 0
|
||||
{ 4, 1, 2, 6, 5 },
|
||||
{ 4, 3, 7, 6, 2 },
|
||||
{ 4, 0, 4, 7, 3 },
|
||||
{ 4, 0, 3, 2, 1 },
|
||||
{ 4, 4, 5, 6, 7 }, //face 5
|
||||
|
||||
//tet
|
||||
{ 3, 0, 3, 1, -1 },
|
||||
{ 3, 1, 2, 3, -1 },
|
||||
{ 3, 0, 2, 3, -1 },
|
||||
{ 3, 0, 2, 1, -1 },
|
||||
|
||||
//wedge
|
||||
{ 3, 0, 1, 2, -1 },
|
||||
{ 3, 3, 5, 4, -1 },
|
||||
{ 4, 3, 0, 2, 5 },
|
||||
{ 4, 1, 4, 5, 2 },
|
||||
{ 4, 0, 3, 4, 1 },
|
||||
|
||||
//pyramid
|
||||
{ 3, 0, 4, 1, -1 },
|
||||
{ 3, 1, 2, 4, -1 },
|
||||
{ 3, 2, 3, 4, -1 },
|
||||
{ 3, 0, 4, 3, -1 },
|
||||
{ 4, 3, 2, 1, 0 }
|
||||
|
||||
};
|
||||
|
||||
// Test of zoo table.
|
||||
// Format (faceNumber, triangle)
|
||||
//
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 ZooTable[30][4] = {
|
||||
{ 0, 0, 1, 5 }, // hex
|
||||
{ 0, 0, 5, 4 }, { 1, 1, 2, 6 }, { 1, 1, 6, 5 }, { 2, 3, 7, 6 }, { 2, 3, 6, 2 },
|
||||
{ 3, 0, 4, 7 }, { 3, 0, 7, 3 }, { 4, 0, 3, 2 }, { 4, 0, 2, 1 }, { 5, 4, 5, 6 },
|
||||
{ 5, 4, 6, 7 }, { 0, 0, 3, 1 }, // Tet
|
||||
{ 1, 1, 2, 3 }, { 2, 0, 2, 3 }, { 3, 0, 2, 1 }, { 0, 0, 1, 2 }, // Wedge
|
||||
{ 1, 3, 5, 4 }, { 2, 3, 0, 2 }, { 2, 3, 2, 5 }, { 3, 1, 4, 5 }, { 3, 1, 5, 2 },
|
||||
{ 4, 0, 3, 4 }, { 4, 0, 4, 1 }, { 0, 0, 4, 1 }, // Pyramid
|
||||
{ 1, 1, 2, 4 }, { 2, 2, 3, 4 }, { 3, 0, 4, 3 }, { 4, 3, 2, 1 }, { 4, 3, 1, 0 }
|
||||
};
|
||||
|
||||
//
|
||||
// Offset into zoo table and the
|
||||
// number of triangles for the shape
|
||||
//
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 ZooLookUp[5][2] = {
|
||||
{ 0, 12 }, //hex offset into shapes face list, num faces and number of Indices
|
||||
{ 12, 4 }, //tet
|
||||
{ 16, 8 }, //wedge
|
||||
{ 24, 6 }, //pyramid
|
||||
{ -1, 0 } //unsupported shape
|
||||
};
|
||||
|
||||
} // namespace raytracing
|
||||
} // namespace rendering
|
||||
} // namespace vtkm
|
||||
#endif
|
466
vtkm/rendering/raytracing/ChannelBuffer.cxx
Normal file
466
vtkm/rendering/raytracing/ChannelBuffer.cxx
Normal file
@ -0,0 +1,466 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/raytracing/ChannelBuffer.h>
|
||||
#include <vtkm/rendering/raytracing/ChannelBufferOperations.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
template <typename Precision>
|
||||
ChannelBuffer<Precision>::ChannelBuffer()
|
||||
{
|
||||
this->NumChannels = 4;
|
||||
this->Size = 0;
|
||||
this->Name = "default";
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
ChannelBuffer<Precision>::ChannelBuffer(const vtkm::Int32 numChannels, const vtkm::Id size)
|
||||
{
|
||||
if (size < 1)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that 0");
|
||||
if (numChannels < 1)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that 0");
|
||||
|
||||
this->NumChannels = numChannels;
|
||||
this->Size = size;
|
||||
|
||||
Buffer.Allocate(this->Size * this->NumChannels);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
vtkm::Int32 ChannelBuffer<Precision>::GetNumChannels() const
|
||||
{
|
||||
return this->NumChannels;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
vtkm::Id ChannelBuffer<Precision>::GetSize() const
|
||||
{
|
||||
return this->Size;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
vtkm::Id ChannelBuffer<Precision>::GetBufferLength() const
|
||||
{
|
||||
return this->Size * static_cast<vtkm::Id>(this->NumChannels);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void ChannelBuffer<Precision>::SetName(const std::string name)
|
||||
{
|
||||
this->Name = name;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
std::string ChannelBuffer<Precision>::GetName() const
|
||||
{
|
||||
return this->Name;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void ChannelBuffer<Precision>::Resize(const vtkm::Id newSize)
|
||||
{
|
||||
if (newSize < 0)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer resize: Size must be greater than -1");
|
||||
this->Size = newSize;
|
||||
this->Buffer.Allocate(this->Size * static_cast<vtkm::Id>(NumChannels));
|
||||
}
|
||||
|
||||
class ExtractChannel : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
vtkm::Id NumChannels; // the nnumber of channels in the buffer
|
||||
vtkm::Id ChannelNum; // the channel to extract
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
ExtractChannel(const vtkm::Int32 numChannels, const vtkm::Int32 channel)
|
||||
: NumChannels(numChannels)
|
||||
, ChannelNum(channel)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldOut<>, WholeArrayIn<>);
|
||||
typedef void ExecutionSignature(_1, _2, WorkIndex);
|
||||
template <typename T, typename BufferPortalType>
|
||||
VTKM_EXEC void operator()(T& outValue,
|
||||
const BufferPortalType& inBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
vtkm::Id valueIndex = index * NumChannels + ChannelNum;
|
||||
BOUNDS_CHECK(inBuffer, valueIndex);
|
||||
outValue = inBuffer.Get(valueIndex);
|
||||
}
|
||||
}; //class Extract Channel
|
||||
|
||||
template <typename Precision>
|
||||
struct ExtractChannelFunctor
|
||||
{
|
||||
ChannelBuffer<Precision>* Self;
|
||||
vtkm::cont::ArrayHandle<Precision> Output;
|
||||
vtkm::Int32 Channel;
|
||||
|
||||
ExtractChannelFunctor(ChannelBuffer<Precision>* self,
|
||||
vtkm::cont::ArrayHandle<Precision> output,
|
||||
const vtkm::Int32 channel)
|
||||
: Self(self)
|
||||
, Output(output)
|
||||
, Channel(channel)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device device)
|
||||
{
|
||||
Output.PrepareForOutput(Self->GetSize(), device);
|
||||
vtkm::worklet::DispatcherMapField<ExtractChannel, Device>(
|
||||
ExtractChannel(Self->GetNumChannels(), Channel))
|
||||
.Invoke(Output, Self->Buffer);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
ChannelBuffer<Precision> ChannelBuffer<Precision>::GetChannel(const vtkm::Int32 channel)
|
||||
{
|
||||
if (channel < 0 || channel >= this->NumChannels)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer: invalid channel to extract");
|
||||
ChannelBuffer<Precision> output(1, this->Size);
|
||||
output.SetName(this->Name);
|
||||
|
||||
ExtractChannelFunctor<Precision> functor(this, output.Buffer, channel);
|
||||
|
||||
vtkm::cont::TryExecute(functor);
|
||||
return output;
|
||||
}
|
||||
|
||||
//static
|
||||
class Expand : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
vtkm::Int32 NumChannels;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Expand(const vtkm::Int32 numChannels)
|
||||
: NumChannels(numChannels)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, WholeArrayOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, WorkIndex);
|
||||
template <typename T, typename IndexPortalType, typename BufferPortalType>
|
||||
VTKM_EXEC void operator()(const T& inValue,
|
||||
const IndexPortalType& sparseIndexes,
|
||||
BufferPortalType& outBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
vtkm::Id sparse = index / NumChannels;
|
||||
BOUNDS_CHECK(sparseIndexes, sparse);
|
||||
vtkm::Id sparseIndex = sparseIndexes.Get(sparse) * NumChannels;
|
||||
vtkm::Id outIndex = sparseIndex + index % NumChannels;
|
||||
BOUNDS_CHECK(outBuffer, outIndex);
|
||||
outBuffer.Set(outIndex, inValue);
|
||||
}
|
||||
}; //class Expand
|
||||
|
||||
template <typename Precision>
|
||||
struct ExpandFunctorSignature
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Precision> Input;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> SparseIndexes;
|
||||
ChannelBuffer<Precision>* Output;
|
||||
vtkm::cont::ArrayHandle<Precision> Signature;
|
||||
vtkm::Id OutputLength;
|
||||
vtkm::Int32 NumChannels;
|
||||
|
||||
|
||||
ExpandFunctorSignature(vtkm::cont::ArrayHandle<Precision> input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
ChannelBuffer<Precision>* outChannelBuffer,
|
||||
vtkm::Id outputLength,
|
||||
vtkm::Int32 numChannels,
|
||||
vtkm::cont::ArrayHandle<Precision> signature)
|
||||
: Input(input)
|
||||
, SparseIndexes(sparseIndexes)
|
||||
, Output(outChannelBuffer)
|
||||
, Signature(signature)
|
||||
, OutputLength(outputLength)
|
||||
, NumChannels(numChannels)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device device)
|
||||
{
|
||||
vtkm::Id totalSize = OutputLength * static_cast<vtkm::Id>(NumChannels);
|
||||
Output->Buffer.PrepareForOutput(totalSize, device);
|
||||
ChannelBufferOperations::InitChannels(*Output, Signature, device);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<Expand, Device>(Expand(NumChannels))
|
||||
.Invoke(Input, SparseIndexes, Output->Buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
struct ExpandFunctor
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Precision> Input;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> SparseIndexes;
|
||||
ChannelBuffer<Precision>* Output;
|
||||
vtkm::Id OutputLength;
|
||||
vtkm::Int32 NumChannels;
|
||||
Precision InitVal;
|
||||
|
||||
|
||||
ExpandFunctor(vtkm::cont::ArrayHandle<Precision> input,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
ChannelBuffer<Precision>* outChannelBuffer,
|
||||
vtkm::Id outputLength,
|
||||
vtkm::Int32 numChannels,
|
||||
Precision initVal)
|
||||
: Input(input)
|
||||
, SparseIndexes(sparseIndexes)
|
||||
, Output(outChannelBuffer)
|
||||
, OutputLength(outputLength)
|
||||
, NumChannels(numChannels)
|
||||
, InitVal(initVal)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device device)
|
||||
{
|
||||
vtkm::Id totalSize = OutputLength * static_cast<vtkm::Id>(NumChannels);
|
||||
Output->Buffer.PrepareForOutput(totalSize, device);
|
||||
ChannelBufferOperations::InitConst(*Output, InitVal, device);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<Expand, Device>(Expand(NumChannels))
|
||||
.Invoke(Input, SparseIndexes, Output->Buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
class NormalizeBuffer : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
Precision MinScalar;
|
||||
Precision InvDeltaScalar;
|
||||
bool Invert;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
NormalizeBuffer(const Precision minScalar, const Precision maxScalar, bool invert)
|
||||
: MinScalar(minScalar)
|
||||
, Invert(invert)
|
||||
{
|
||||
if (maxScalar - minScalar == 0.)
|
||||
{
|
||||
InvDeltaScalar = MinScalar;
|
||||
}
|
||||
else
|
||||
{
|
||||
InvDeltaScalar = 1.f / (maxScalar - minScalar);
|
||||
}
|
||||
//std::cout<<"Min scalar "<<minScalar<<" max "<<maxScalar<<std::endl;
|
||||
}
|
||||
typedef void ControlSignature(FieldInOut<>);
|
||||
typedef void ExecutionSignature(_1);
|
||||
|
||||
VTKM_EXEC
|
||||
void operator()(Precision& value) const
|
||||
{
|
||||
value = (value - MinScalar) * InvDeltaScalar;
|
||||
if (Invert)
|
||||
value = 1.f - value;
|
||||
}
|
||||
}; //class normalize buffer
|
||||
|
||||
|
||||
template <typename Precision>
|
||||
struct NormalizeFunctor
|
||||
{
|
||||
vtkm::cont::ArrayHandle<Precision> Input;
|
||||
bool Invert;
|
||||
|
||||
NormalizeFunctor(vtkm::cont::ArrayHandle<Precision> input, bool invert)
|
||||
: Input(input)
|
||||
, Invert(invert)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device vtkmNotUsed(device))
|
||||
{
|
||||
vtkm::cont::Field asField("name meaningless", vtkm::cont::Field::ASSOC_POINTS, Input);
|
||||
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>, Device>(
|
||||
NormalizeBuffer<Precision>(minScalar, maxScalar, Invert))
|
||||
.Invoke(Input);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Precision>
|
||||
ChannelBuffer<Precision> ChannelBuffer<Precision>::ExpandBuffer(
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
const vtkm::Id outputSize,
|
||||
vtkm::cont::ArrayHandle<Precision> signature)
|
||||
{
|
||||
VTKM_ASSERT(this->NumChannels == signature.GetPortalConstControl().GetNumberOfValues());
|
||||
ChannelBuffer<Precision> output(this->NumChannels, outputSize);
|
||||
|
||||
output.SetName(this->Name);
|
||||
|
||||
ExpandFunctorSignature<Precision> functor(
|
||||
this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, signature);
|
||||
|
||||
vtkm::cont::TryExecute(functor);
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
ChannelBuffer<Precision> ChannelBuffer<Precision>::ExpandBuffer(
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
const vtkm::Id outputSize,
|
||||
Precision initValue)
|
||||
{
|
||||
ChannelBuffer<Precision> output(this->NumChannels, outputSize);
|
||||
|
||||
output.SetName(this->Name);
|
||||
|
||||
ExpandFunctor<Precision> functor(
|
||||
this->Buffer, sparseIndexes, &output, outputSize, this->NumChannels, initValue);
|
||||
|
||||
vtkm::cont::TryExecute(functor);
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void ChannelBuffer<Precision>::Normalize(bool invert)
|
||||
{
|
||||
|
||||
NormalizeFunctor<Precision> functor(this->Buffer, invert);
|
||||
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
struct ResizeChannelFunctor
|
||||
{
|
||||
ChannelBuffer<Precision>* Self;
|
||||
vtkm::Int32 NumChannels;
|
||||
|
||||
ResizeChannelFunctor(ChannelBuffer<Precision>* self, vtkm::Int32 numChannels)
|
||||
: Self(self)
|
||||
, NumChannels(numChannels)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device device)
|
||||
{
|
||||
Self->SetNumChannels(NumChannels, device);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
struct InitChannelFunctor
|
||||
{
|
||||
ChannelBuffer<Precision>* Self;
|
||||
const vtkm::cont::ArrayHandle<Precision>& Signature;
|
||||
InitChannelFunctor(ChannelBuffer<Precision>* self,
|
||||
const vtkm::cont::ArrayHandle<Precision>& signature)
|
||||
: Self(self)
|
||||
, Signature(signature)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
bool operator()(Device device)
|
||||
{
|
||||
ChannelBufferOperations::InitChannels(*Self, Signature, device);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
void ChannelBuffer<Precision>::InitChannels(const vtkm::cont::ArrayHandle<Precision>& signature)
|
||||
{
|
||||
InitChannelFunctor<Precision> functor(this, signature);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void ChannelBuffer<Precision>::SetNumChannels(const vtkm::Int32 numChannels)
|
||||
{
|
||||
ResizeChannelFunctor<Precision> functor(this, numChannels);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
// Instantiate supported types
|
||||
template class ChannelBuffer<vtkm::Float32>;
|
||||
template class ChannelBuffer<vtkm::Float64>;
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
148
vtkm/rendering/raytracing/ChannelBuffer.h
Normal file
148
vtkm/rendering/raytracing/ChannelBuffer.h
Normal file
@ -0,0 +1,148 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtkm_rendering_raytracing_ChannelBuffer_h
|
||||
#define vtkm_rendering_raytracing_ChannelBuffer_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/rendering/raytracing/Worklets.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
///
|
||||
/// \brief Mananges a buffer that contains many channels per value (e.g., RGBA values).
|
||||
///
|
||||
/// \c The ChannelBuffer class is meant to handle a buffer of values with potentially many
|
||||
/// channels. While RGBA values could be placed in a Vec<T,4>, data with a large number of
|
||||
/// channels (e.g., 100+ energy bins) are better handled by a raw array. Rays can have color,
|
||||
/// absorption, absorption + emmision, or even track additional scalar values to support
|
||||
/// standards such as Cinema. This class allows us to treat all of these differnt use cases
|
||||
/// with the same type.
|
||||
///
|
||||
/// This class has methods that can be utilized by other VTK-m classes that already have a
|
||||
/// a device dapter specified, and can be used by external callers where the call executes
|
||||
/// on a device through the try execute mechanism.
|
||||
///
|
||||
/// \c Currently, the supported types are floating point to match the precision of the rays.
|
||||
///
|
||||
|
||||
template <typename Precision>
|
||||
class VTKM_RENDERING_EXPORT ChannelBuffer
|
||||
{
|
||||
protected:
|
||||
vtkm::Int32 NumChannels;
|
||||
vtkm::Id Size;
|
||||
std::string Name;
|
||||
friend class ChannelBufferOperations;
|
||||
|
||||
public:
|
||||
vtkm::cont::ArrayHandle<Precision> Buffer;
|
||||
|
||||
/// Functions we want accessble outside of vtkm some of which execute
|
||||
/// on a device
|
||||
///
|
||||
VTKM_CONT
|
||||
ChannelBuffer();
|
||||
|
||||
VTKM_CONT
|
||||
ChannelBuffer(const vtkm::Int32 numChannels, const vtkm::Id size);
|
||||
|
||||
VTKM_CONT
|
||||
ChannelBuffer<Precision> GetChannel(const vtkm::Int32 channel);
|
||||
|
||||
ChannelBuffer<Precision> ExpandBuffer(vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
const vtkm::Id outputSize,
|
||||
vtkm::cont::ArrayHandle<Precision> signature);
|
||||
|
||||
ChannelBuffer<Precision> ExpandBuffer(vtkm::cont::ArrayHandle<vtkm::Id> sparseIndexes,
|
||||
const vtkm::Id outputSize,
|
||||
Precision initValue = 1.f);
|
||||
|
||||
void InitConst(const Precision value);
|
||||
void InitChannels(const vtkm::cont::ArrayHandle<Precision>& signature);
|
||||
void Normalize(bool invert);
|
||||
void SetName(const std::string name);
|
||||
void Resize(const vtkm::Id newSize);
|
||||
void SetNumChannels(const vtkm::Int32 numChannels);
|
||||
vtkm::Int32 GetNumChannels() const;
|
||||
vtkm::Id GetSize() const;
|
||||
vtkm::Id GetBufferLength() const;
|
||||
std::string GetName() const;
|
||||
|
||||
/// Functions that are calleble within vtkm where the device is already known
|
||||
///
|
||||
template <typename Device>
|
||||
VTKM_CONT ChannelBuffer(const vtkm::Int32 size, const vtkm::Int32 numChannels, Device)
|
||||
{
|
||||
if (size < 1)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer: Size must be greater that 0");
|
||||
if (numChannels < 1)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer: NumChannels must be greater that 0");
|
||||
|
||||
this->NumChannels = numChannels;
|
||||
this->Size = size;
|
||||
|
||||
this->Buffer.PrepareForOutput(this->Size * this->NumChannels, Device());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT void SetNumChannels(const vtkm::Int32 numChannels, Device)
|
||||
{
|
||||
if (numChannels < 1)
|
||||
{
|
||||
std::string msg = "ChannelBuffer SetNumChannels: numBins must be greater that 0";
|
||||
throw vtkm::cont::ErrorBadValue(msg);
|
||||
}
|
||||
if (this->NumChannels == numChannels)
|
||||
return;
|
||||
|
||||
this->NumChannels = numChannels;
|
||||
this->Buffer.PrepareForOutput(this->Size * this->NumChannels, Device());
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT void Resize(const vtkm::Id newSize, Device device)
|
||||
{
|
||||
if (newSize < 0)
|
||||
throw vtkm::cont::ErrorBadValue("ChannelBuffer resize: Size must be greater than -1 ");
|
||||
this->Size = newSize;
|
||||
this->Buffer.PrepareForOutput(this->Size * static_cast<vtkm::Id>(NumChannels), device);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
|
||||
#endif
|
145
vtkm/rendering/raytracing/ChannelBufferOperations.h
Normal file
145
vtkm/rendering/raytracing/ChannelBufferOperations.h
Normal file
@ -0,0 +1,145 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtkm_rendering_raytracing_ChannelBuffer_Operations_h
|
||||
#define vtkm_rendering_raytracing_ChannelBuffer_Operations_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/rendering/raytracing/ChannelBuffer.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class CompactBuffer : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
const vtkm::Id NumChannels; // the number of channels in the buffer
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CompactBuffer(const vtkm::Int32 numChannels)
|
||||
: NumChannels(numChannels)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, FieldIn<>, WholeArrayOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, WorkIndex);
|
||||
template <typename InBufferPortalType, typename OutBufferPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::UInt8& mask,
|
||||
const InBufferPortalType& inBuffer,
|
||||
const vtkm::Id& offset,
|
||||
OutBufferPortalType& outBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
if (mask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
vtkm::Id inIndex = index * NumChannels;
|
||||
vtkm::Id outIndex = offset * NumChannels;
|
||||
for (vtkm::Int32 i = 0; i < NumChannels; ++i)
|
||||
{
|
||||
BOUNDS_CHECK(inBuffer, inIndex + i);
|
||||
BOUNDS_CHECK(outBuffer, outIndex + i);
|
||||
outBuffer.Set(outIndex + i, inBuffer.Get(inIndex + i));
|
||||
}
|
||||
}
|
||||
}; //class Compact
|
||||
|
||||
class InitBuffer : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
vtkm::Int32 NumChannels;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
InitBuffer(const vtkm::Int32 numChannels)
|
||||
: NumChannels(numChannels)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldOut<>, WholeArrayIn<>);
|
||||
typedef void ExecutionSignature(_1, _2, WorkIndex);
|
||||
template <typename ValueType, typename PortalType>
|
||||
VTKM_EXEC void operator()(ValueType& outValue,
|
||||
const PortalType& source,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
outValue = source.Get(index % NumChannels);
|
||||
}
|
||||
}; //class InitBuffer
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class ChannelBufferOperations
|
||||
{
|
||||
public:
|
||||
template <typename Device, typename Precision>
|
||||
static void Compact(ChannelBuffer<Precision>& buffer,
|
||||
vtkm::cont::ArrayHandle<UInt8>& masks,
|
||||
const vtkm::Id& newSize,
|
||||
Device)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> offsets;
|
||||
offsets.PrepareForOutput(buffer.Size, Device());
|
||||
vtkm::cont::ArrayHandleCast<vtkm::Id, vtkm::cont::ArrayHandle<vtkm::UInt8>> castedMasks(masks);
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExclusive(castedMasks, offsets);
|
||||
|
||||
vtkm::cont::ArrayHandle<Precision> compactedBuffer;
|
||||
compactedBuffer.PrepareForOutput(newSize * buffer.NumChannels, Device());
|
||||
|
||||
vtkm::worklet::DispatcherMapField<detail::CompactBuffer, Device>(
|
||||
detail::CompactBuffer(buffer.NumChannels))
|
||||
.Invoke(masks, buffer.Buffer, offsets, compactedBuffer);
|
||||
buffer.Buffer = compactedBuffer;
|
||||
buffer.Size = newSize;
|
||||
}
|
||||
|
||||
template <typename Device, typename Precision>
|
||||
static void InitChannels(ChannelBuffer<Precision>& buffer,
|
||||
vtkm::cont::ArrayHandle<Precision> sourceSignature,
|
||||
Device)
|
||||
{
|
||||
if (sourceSignature.GetNumberOfValues() != buffer.NumChannels)
|
||||
{
|
||||
std::string msg = "ChannelBuffer: number of bins in sourse signature must match NumChannels";
|
||||
throw vtkm::cont::ErrorBadValue(msg);
|
||||
}
|
||||
vtkm::worklet::DispatcherMapField<detail::InitBuffer, Device>(
|
||||
detail::InitBuffer(buffer.NumChannels))
|
||||
.Invoke(buffer.Buffer, sourceSignature);
|
||||
}
|
||||
|
||||
template <typename Device, typename Precision>
|
||||
static void InitConst(ChannelBuffer<Precision>& buffer, const Precision value, Device)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<MemSet<Precision>, Device>(MemSet<Precision>(value))
|
||||
.Invoke(buffer.Buffer);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
68
vtkm/rendering/raytracing/ConnectivityBase.h
Normal file
68
vtkm/rendering/raytracing/ConnectivityBase.h
Normal file
@ -0,0 +1,68 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//
|
||||
// Copyright 2015 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Connectivity_Base_h
|
||||
#define vtk_m_rendering_raytracing_Connectivity_Base_h
|
||||
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class 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& absorbtion,
|
||||
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 SetCompositeBackground(bool on) = 0;
|
||||
|
||||
virtual void SetSampleDistance(const vtkm::Float32& distance) = 0;
|
||||
|
||||
virtual void SetColorMap(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap) = 0;
|
||||
}; // class ConnectivityBase
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
1410
vtkm/rendering/raytracing/ConnectivityTracer.h
Normal file
1410
vtkm/rendering/raytracing/ConnectivityTracer.h
Normal file
File diff suppressed because it is too large
Load Diff
124
vtkm/rendering/raytracing/ConnectivityTracerFactory.h
Normal file
124
vtkm/rendering/raytracing/ConnectivityTracerFactory.h
Normal file
@ -0,0 +1,124 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_ConnectivityTracerFactory_h
|
||||
#define vtk_m_rendering_raytracing_ConnectivityTracerFactory_h
|
||||
|
||||
#include <vtkm/rendering/raytracing/ConnectivityTracer.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static ConnectivityBase* CreateTracer(const vtkm::cont::DynamicCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Connectivity tracer: cell set type unsupported");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
77
vtkm/rendering/raytracing/Logger.cxx
Normal file
77
vtkm/rendering/raytracing/Logger.cxx
Normal file
@ -0,0 +1,77 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/raytracing/Logger.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
Logger* Logger::Instance = NULL;
|
||||
|
||||
Logger::Logger()
|
||||
{
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
Stream.str("");
|
||||
}
|
||||
|
||||
Logger* Logger::GetInstance()
|
||||
{
|
||||
if (Instance == NULL)
|
||||
{
|
||||
Instance = new Logger();
|
||||
}
|
||||
return Instance;
|
||||
}
|
||||
|
||||
std::stringstream& Logger::GetStream()
|
||||
{
|
||||
return Stream;
|
||||
}
|
||||
|
||||
void Logger::Clear()
|
||||
{
|
||||
Stream.str("");
|
||||
while (!Entries.empty())
|
||||
{
|
||||
Entries.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::OpenLogEntry(const std::string& entryName)
|
||||
{
|
||||
Stream << entryName << " "
|
||||
<< "<\n";
|
||||
Entries.push(entryName);
|
||||
}
|
||||
void Logger::CloseLogEntry(const vtkm::Float64& entryTime)
|
||||
{
|
||||
this->Stream << "total_time " << entryTime << "\n";
|
||||
this->Stream << this->Entries.top() << " >\n";
|
||||
Entries.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::renderng::raytracing
|
@ -17,8 +17,14 @@
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Loggable_h
|
||||
#define vtk_m_rendering_raytracing_Loggable_h
|
||||
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/rendering/vtkm_rendering_export.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -27,9 +33,30 @@ namespace rendering
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
RayBase::~RayBase()
|
||||
class VTKM_RENDERING_EXPORT Logger
|
||||
{
|
||||
}
|
||||
public:
|
||||
~Logger();
|
||||
static Logger* GetInstance();
|
||||
void OpenLogEntry(const std::string& entryName);
|
||||
void CloseLogEntry(const vtkm::Float64& entryTime);
|
||||
void Clear();
|
||||
template <typename T>
|
||||
void AddLogData(const std::string key, const T& value)
|
||||
{
|
||||
this->Stream << key << " " << value << "\n";
|
||||
}
|
||||
|
||||
std::stringstream& GetStream();
|
||||
|
||||
protected:
|
||||
Logger();
|
||||
Logger(Logger const&);
|
||||
std::stringstream Stream;
|
||||
static class Logger* Instance;
|
||||
std::stack<std::string> Entries;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
||||
#endif
|
822
vtkm/rendering/raytracing/MeshConnectivityBuilder.h
Normal file
822
vtkm/rendering/raytracing/MeshConnectivityBuilder.h
Normal file
@ -0,0 +1,822 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#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/ColorTable.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>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
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() {}
|
||||
typedef void ControlSignature(WholeArrayIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_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() {}
|
||||
typedef void ControlSignature(WholeArrayIn<>,
|
||||
ExecObject,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, WorkIndex, _3, _4, _5, _6);
|
||||
|
||||
VTKM_EXEC
|
||||
inline vtkm::Int32 GetShapeOffset(const vtkm::UInt8& shapeType) const
|
||||
{
|
||||
|
||||
//TODO: This might be better as if if if
|
||||
vtkm::Int32 tableOffset = 0;
|
||||
if (shapeType == vtkm::CELL_SHAPE_TETRA)
|
||||
{
|
||||
tableOffset = FaceLookUp[1][0];
|
||||
}
|
||||
else if (shapeType == vtkm::CELL_SHAPE_HEXAHEDRON)
|
||||
{
|
||||
tableOffset = FaceLookUp[0][0];
|
||||
}
|
||||
else if (shapeType == vtkm::CELL_SHAPE_WEDGE)
|
||||
{
|
||||
tableOffset = FaceLookUp[2][0];
|
||||
}
|
||||
else if (shapeType == vtkm::CELL_SHAPE_PYRAMID)
|
||||
{
|
||||
tableOffset = 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 ConnPortalType,
|
||||
typename ShapePortalType,
|
||||
typename OffsetPortalType,
|
||||
typename ExternalFaceFlagType>
|
||||
VTKM_EXEC inline void operator()(
|
||||
const MortonPortalType& mortonCodes,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Id, 3>>& 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;
|
||||
|
||||
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::Id shape1Offset = GetShapeOffset(shapes.Get(cellId1)) + faceIdPairs.Get(index)[1];
|
||||
vtkm::Id shape2Offset =
|
||||
GetShapeOffset(shapes.Get(cellId2)) + faceIdPairs.Get(currentIndex)[1];
|
||||
|
||||
vtkm::Int32 icount1 = ShapesFaceList[shape1Offset][0];
|
||||
vtkm::Int32 icount2 = 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;
|
||||
|
||||
for (vtkm::Int32 i = 1; i <= ShapesFaceList[shape1Offset][0]; ++i)
|
||||
{
|
||||
BOUNDS_CHECK(offsets, cellId1);
|
||||
BOUNDS_CHECK(offsets, cellId2);
|
||||
BOUNDS_CHECK(connectivity, (offsets.Get(cellId1) + ShapesFaceList[shape1Offset][i]));
|
||||
BOUNDS_CHECK(connectivity, (offsets.Get(cellId2) + ShapesFaceList[shape2Offset][i]));
|
||||
indices1[i - 1] =
|
||||
connectivity.Get(offsets.Get(cellId1) + ShapesFaceList[shape1Offset][i]);
|
||||
indices2[i - 1] =
|
||||
connectivity.Get(offsets.Get(cellId2) + ShapesFaceList[shape2Offset][i]);
|
||||
}
|
||||
|
||||
bool isEqual = true;
|
||||
for (vtkm::Int32 i = 0; i < ShapesFaceList[shape1Offset][0]; ++i)
|
||||
{
|
||||
if (!IsIn(indices1[i], indices2, ShapesFaceList[shape1Offset][0]))
|
||||
isEqual = false;
|
||||
}
|
||||
|
||||
if (isEqual)
|
||||
{
|
||||
isInternal = true;
|
||||
|
||||
connectedCell = cellId2;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentIndex--;
|
||||
}
|
||||
|
||||
//this means that this cell is resposible for both itself and the other cell
|
||||
//set the connecttion 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() {}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayIn<>,
|
||||
WholeArrayOut<>,
|
||||
FieldIn<>);
|
||||
typedef void ExecutionSignature(_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
|
||||
{
|
||||
|
||||
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 = FaceLookUp[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 = ShapesFaceList[tableIndex][0];
|
||||
|
||||
for (vtkm::Int32 i = 1; i <= numIndices; ++i)
|
||||
{
|
||||
BOUNDS_CHECK(indices, offset + ShapesFaceList[tableIndex][i]);
|
||||
faceIndices[i - 1] = indices.Get(offset + 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:
|
||||
VTKM_CONT
|
||||
WriteFaceConn() {}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, ExecObject);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
template <typename FaceOffsetsPortalType>
|
||||
VTKM_EXEC inline void operator()(const vtkm::Vec<vtkm::Id, 3>& faceIdPair,
|
||||
const FaceOffsetsPortalType& faceOffsets,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Id>& 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
|
||||
|
||||
// Each one of size segments will process
|
||||
// one face of the hex and domain
|
||||
VTKM_EXEC_CONSTANT
|
||||
static vtkm::Int32 SegmentToFace[6] = { 0, 2, 1, 3, 4, 5 };
|
||||
|
||||
// Each face/segment has 2 varying dimensions
|
||||
VTKM_EXEC_CONSTANT
|
||||
static 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 } };
|
||||
class StructuredExternalTriangles : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
typedef vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagPoint,
|
||||
vtkm::TopologyElementTagCell,
|
||||
3>
|
||||
ConnType;
|
||||
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];
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
template <typename TrianglePortalType>
|
||||
VTKM_EXEC inline void operator()(const vtkm::Id& index, TrianglePortalType& triangles) const
|
||||
{
|
||||
//
|
||||
// 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 ajust 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.
|
||||
vtkm::Int32 shapesFaceOffset = FaceLookUp[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[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() {}
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_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
|
||||
{
|
||||
vtkm::Id cellId = faceIdPair[0];
|
||||
vtkm::Id cellFace = faceIdPair[1];
|
||||
vtkm::Int32 shapeType = static_cast<vtkm::Int32>(shapes.Get(cellId));
|
||||
vtkm::Int32 faceStartIndex = FaceLookUp[CellTypeLookUp[shapeType]][0];
|
||||
if (faceStartIndex == -1)
|
||||
{
|
||||
//Unsupported Shape Type this should never happen
|
||||
triangleCount = 0;
|
||||
return;
|
||||
}
|
||||
vtkm::Int32 faceType = ShapesFaceList[faceStartIndex + 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() {}
|
||||
|
||||
|
||||
VTKM_CONT
|
||||
void BuildConnectivity(vtkm::cont::CellSetSingleType<>& cellSetUnstructured,
|
||||
DynamicArrayHandleExplicitCoordinateSystem& 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>(WriteFaceConn())
|
||||
.Invoke(
|
||||
cellFaceId, this->FaceOffsets, vtkm::exec::ExecutionWholeArray<vtkm::Id>(faceConnectivity));
|
||||
|
||||
|
||||
FaceConnectivity = faceConnectivity;
|
||||
OutsideTriangles = externalTriangles;
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void BuildConnectivity(vtkm::cont::CellSetExplicit<>& cellSetUnstructured,
|
||||
DynamicArrayHandleExplicitCoordinateSystem& 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>(WriteFaceConn())
|
||||
.Invoke(
|
||||
cellFaceId, this->FaceOffsets, vtkm::exec::ExecutionWholeArray<vtkm::Id>(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>(
|
||||
StructuredExternalTriangles(cellSetStructured.PrepareForInput(
|
||||
DeviceAdapter(), vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell())))
|
||||
.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,
|
||||
DynamicArrayHandleExplicitCoordinateSystem& coordinates,
|
||||
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();
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
// Count the number of total faces in the cell set
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> facesPerCell;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<CountFaces, DeviceAdapter>(CountFaces())
|
||||
.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 (consistant 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 everyting 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, DeviceAdapter>(
|
||||
MortonCodeFace(inverseExtent, minPoint))
|
||||
.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>, DeviceAdapter>(MemSet<vtkm::Id>(-1))
|
||||
.Invoke(faceConnectivity);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<MortonNeighbor, DeviceAdapter>(MortonNeighbor())
|
||||
.Invoke(faceMortonCodes,
|
||||
vtkm::exec::ExecutionWholeArray<vtkm::Vec<vtkm::Id, 3>>(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, DeviceAdapter>(
|
||||
CountExternalTriangles())
|
||||
.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, DeviceAdapter>(ExternalTriangles())
|
||||
.Invoke(
|
||||
externalFacePairs, shapes, shapeOffsets, conn, externalTriangles, externalTriangleOffsets);
|
||||
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
Logger::GetInstance()->AddLogData("external_faces", time);
|
||||
return externalTriangles;
|
||||
}
|
||||
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> FaceConnectivity;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> FaceOffsets;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> OutsideTriangles;
|
||||
};
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif
|
803
vtkm/rendering/raytracing/MeshConnectivityStructures.h
Normal file
803
vtkm/rendering/raytracing/MeshConnectivityStructures.h
Normal file
@ -0,0 +1,803 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#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:
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::UInt8> UCharHandle;
|
||||
// Control Environment Handles
|
||||
// FaceConn
|
||||
IdHandle FaceConnectivity;
|
||||
IdHandle FaceOffsets;
|
||||
//Cell Set
|
||||
IdHandle CellConn;
|
||||
IdHandle CellOffsets;
|
||||
UCharHandle Shapes;
|
||||
// Mesh Boundry
|
||||
Id4Handle ExternalTriangles;
|
||||
LinearBVH Bvh;
|
||||
|
||||
// Restrict the coordinates to the types that be for unstructured meshes
|
||||
DynamicArrayHandleExplicitCoordinateSystem Coordinates;
|
||||
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;
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
||||
|
||||
//
|
||||
// Reset the type lists to only contain the coordinate systemss of an
|
||||
// unstructured cell set.
|
||||
//
|
||||
|
||||
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
||||
.ResetStorageList(StorageListTagExplicitCoordinateSystem());
|
||||
|
||||
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)
|
||||
, Coordinates(other.Coordinates)
|
||||
, 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, Coordinates, 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);
|
||||
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, Coordinates, getCellIndex);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfCells() { return this->Shapes.GetPortalConstControl().GetNumberOfValues(); }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Control Environment Methods
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
DynamicArrayHandleExplicitCoordinateSystem GetCoordinates() { return Coordinates; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::UInt8> UCharHandle;
|
||||
typedef typename IdHandle::ExecutionTypes<Device>::PortalConst IdConstPortal;
|
||||
typedef typename UCharHandle::ExecutionTypes<Device>::PortalConst UCharConstPortal;
|
||||
|
||||
// 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
|
||||
{
|
||||
const vtkm::Int32 shapeId = static_cast<vtkm::Int32>(ShapesPortal.Get(cellId));
|
||||
const vtkm::Int32 numIndices = FaceLookUp[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:
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
typedef vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandle;
|
||||
typedef vtkm::cont::ArrayHandleConstant<vtkm::UInt8> ShapesHandle;
|
||||
typedef vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> NumIndicesHandle;
|
||||
// Control Environment Handles
|
||||
IdHandle FaceConnectivity;
|
||||
CountingHandle CellOffsets;
|
||||
IdHandle CellConnectivity;
|
||||
// Mesh Boundry
|
||||
LinearBVH Bvh;
|
||||
Id4Handle ExternalTriangles;
|
||||
// Restrict the coordinates to the types that be for unstructured meshes
|
||||
DynamicArrayHandleExplicitCoordinateSystem Coordinates;
|
||||
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;
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
||||
|
||||
//
|
||||
// Reset the type lists to only contain the coordinate systemss of an
|
||||
// unstructured cell set.
|
||||
//
|
||||
|
||||
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
||||
.ResetStorageList(StorageListTagExplicitCoordinateSystem());
|
||||
|
||||
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());
|
||||
|
||||
ShapeId = shapes.GetPortalConstControl().Get(0);
|
||||
NumIndices = FaceLookUp[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 = FaceLookUp[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)
|
||||
, Coordinates(other.Coordinates)
|
||||
, 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, Coordinates, CoordinateBounds);
|
||||
//
|
||||
// Initialize all of the array handles
|
||||
//
|
||||
FaceConnectivity = connBuilder.GetFaceConnectivity();
|
||||
ExternalTriangles = connBuilder.GetExternalTriangles();
|
||||
|
||||
//
|
||||
// Build BVH on external triangles
|
||||
//
|
||||
Bvh.SetData(Coords.GetData(), ExternalTriangles);
|
||||
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, Coordinates, getCellIndex);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
vtkm::Id GetNumberOfCells() { return this->Cellset.GetNumberOfCells(); }
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
Id4Handle GetExternalTriangles() { return ExternalTriangles; }
|
||||
//----------------------------------------------------------------------------
|
||||
VTKM_CONT
|
||||
DynamicArrayHandleExplicitCoordinateSystem GetCoordinates() { return Coordinates; }
|
||||
//----------------------------------------------------------------------------
|
||||
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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdHandle;
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
typedef typename vtkm::cont::ArrayHandleCounting<vtkm::Id> CountingHandle;
|
||||
typedef typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8> ShapesHandle;
|
||||
|
||||
typedef typename IdHandle::ExecutionTypes<Device>::PortalConst IdConstPortal;
|
||||
typedef typename CountingHandle::ExecutionTypes<Device>::PortalConst CountingPortal;
|
||||
typedef typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> NumIndicesHandle;
|
||||
// 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:
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
vtkm::Id3 CellDims;
|
||||
vtkm::Id3 PointDims;
|
||||
DynamicArrayHandleStructuredCoordinateSystem Coordinates;
|
||||
vtkm::Bounds CoordinateBounds;
|
||||
vtkm::cont::CoordinateSystem Coords;
|
||||
vtkm::cont::CellSetStructured<3> Cellset;
|
||||
// Mesh Boundry
|
||||
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;
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem dynamicCoordsHandle = coords.GetData();
|
||||
|
||||
//
|
||||
// Reset the type lists to only contain the coordinate systemss of an
|
||||
// unstructured cell set.
|
||||
//
|
||||
|
||||
Coordinates = dynamicCoordsHandle.ResetTypeList(ExplicitCoordinatesType())
|
||||
.ResetStorageList(StructuredStorage());
|
||||
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)
|
||||
, Coordinates(other.Coordinates)
|
||||
, 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);
|
||||
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, Coordinates, 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
|
||||
DynamicArrayHandleStructuredCoordinateSystem GetCoordinates() { return Coordinates; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Id4Handle;
|
||||
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
|
301
vtkm/rendering/raytracing/MortonCodes.h
Normal file
301
vtkm/rendering/raytracing/MortonCodes.h
Normal file
@ -0,0 +1,301 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_MortonCodes_h
|
||||
#define vtk_m_rendering_raytracing_MortonCodes_h
|
||||
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
|
||||
#include <vtkm/rendering/raytracing/CellTables.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
|
||||
//Note: if this takes a long time. we could use a lookup table
|
||||
//expands 10-bit unsigned int into 30 bits
|
||||
VTKM_EXEC inline vtkm::UInt32 ExpandBits32(vtkm::UInt32 x32)
|
||||
{
|
||||
x32 = (x32 | (x32 << 16)) & 0x030000FF;
|
||||
x32 = (x32 | (x32 << 8)) & 0x0300F00F;
|
||||
x32 = (x32 | (x32 << 4)) & 0x030C30C3;
|
||||
x32 = (x32 | (x32 << 2)) & 0x09249249;
|
||||
return x32;
|
||||
}
|
||||
|
||||
VTKM_EXEC inline vtkm::UInt64 ExpandBits64(vtkm::UInt32 x)
|
||||
{
|
||||
vtkm::UInt64 x64 = x & 0x1FFFFF;
|
||||
x64 = (x64 | x64 << 32) & 0x1F00000000FFFF;
|
||||
x64 = (x64 | x64 << 16) & 0x1F0000FF0000FF;
|
||||
x64 = (x64 | x64 << 8) & 0x100F00F00F00F00F;
|
||||
x64 = (x64 | x64 << 4) & 0x10c30c30c30c30c3;
|
||||
x64 = (x64 | x64 << 2) & 0x1249249249249249;
|
||||
|
||||
return x64;
|
||||
}
|
||||
|
||||
//Returns 30 bit morton code for coordinates for
|
||||
//coordinates in the unit cude
|
||||
VTKM_EXEC inline vtkm::UInt32 Morton3D(vtkm::Float32& x, vtkm::Float32& y, vtkm::Float32& z)
|
||||
{
|
||||
//take the first 10 bits
|
||||
x = vtkm::Min(vtkm::Max(x * 1024.0f, 0.0f), 1023.0f);
|
||||
y = vtkm::Min(vtkm::Max(y * 1024.0f, 0.0f), 1023.0f);
|
||||
z = vtkm::Min(vtkm::Max(z * 1024.0f, 0.0f), 1023.0f);
|
||||
//expand the 10 bits to 30
|
||||
vtkm::UInt32 xx = ExpandBits32((vtkm::UInt32)x);
|
||||
vtkm::UInt32 yy = ExpandBits32((vtkm::UInt32)y);
|
||||
vtkm::UInt32 zz = ExpandBits32((vtkm::UInt32)z);
|
||||
//interleave coordinates
|
||||
return (zz << 2 | yy << 1 | xx);
|
||||
}
|
||||
|
||||
//Returns 30 bit morton code for coordinates for
|
||||
//coordinates in the unit cude
|
||||
VTKM_EXEC inline vtkm::UInt64 Morton3D64(vtkm::Float32& x, vtkm::Float32& y, vtkm::Float32& z)
|
||||
{
|
||||
//take the first 21 bits
|
||||
x = vtkm::Min(vtkm::Max(x * 2097152.0f, 0.0f), 2097151.0f);
|
||||
y = vtkm::Min(vtkm::Max(y * 2097152.0f, 0.0f), 2097151.0f);
|
||||
z = vtkm::Min(vtkm::Max(z * 2097152.0f, 0.0f), 2097151.0f);
|
||||
//expand the 10 bits to 30
|
||||
vtkm::UInt64 xx = ExpandBits64((vtkm::UInt32)x);
|
||||
vtkm::UInt64 yy = ExpandBits64((vtkm::UInt32)y);
|
||||
vtkm::UInt64 zz = ExpandBits64((vtkm::UInt32)z);
|
||||
//interleave coordinates
|
||||
return (zz << 2 | yy << 1 | xx);
|
||||
}
|
||||
|
||||
class MortonCodeFace : public vtkm::worklet::WorkletMapPointToCell
|
||||
{
|
||||
private:
|
||||
// (1.f / dx),(1.f / dy), (1.f, / dz)
|
||||
vtkm::Vec<vtkm::Float32, 3> InverseExtent;
|
||||
vtkm::Vec<vtkm::Float32, 3> MinCoordinate;
|
||||
|
||||
VTKM_EXEC inline void Normalize(vtkm::Vec<vtkm::Float32, 3>& point) const
|
||||
{
|
||||
point = (point - MinCoordinate) * InverseExtent;
|
||||
}
|
||||
|
||||
VTKM_EXEC inline void Sort4(vtkm::Vec<vtkm::Id, 4>& indices) const
|
||||
{
|
||||
if (indices[0] < indices[1])
|
||||
{
|
||||
vtkm::Id temp = indices[1];
|
||||
indices[1] = indices[0];
|
||||
indices[0] = temp;
|
||||
}
|
||||
if (indices[2] < indices[3])
|
||||
{
|
||||
vtkm::Id temp = indices[3];
|
||||
indices[3] = indices[2];
|
||||
indices[2] = temp;
|
||||
}
|
||||
if (indices[0] < indices[2])
|
||||
{
|
||||
vtkm::Id temp = indices[2];
|
||||
indices[2] = indices[0];
|
||||
indices[0] = temp;
|
||||
}
|
||||
if (indices[1] < indices[3])
|
||||
{
|
||||
vtkm::Id temp = indices[3];
|
||||
indices[3] = indices[1];
|
||||
indices[1] = temp;
|
||||
}
|
||||
if (indices[1] < indices[2])
|
||||
{
|
||||
vtkm::Id temp = indices[2];
|
||||
indices[2] = indices[1];
|
||||
indices[1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
MortonCodeFace(const vtkm::Vec<vtkm::Float32, 3>& inverseExtent,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& minCoordinate)
|
||||
: InverseExtent(inverseExtent)
|
||||
, MinCoordinate(minCoordinate)
|
||||
{
|
||||
}
|
||||
|
||||
typedef void ControlSignature(CellSetIn cellset,
|
||||
WholeArrayIn<>,
|
||||
FieldInTo<>,
|
||||
WholeArrayOut<>,
|
||||
WholeArrayOut<>);
|
||||
|
||||
typedef void ExecutionSignature(CellShape, FromIndices, WorkIndex, _2, _3, _4, _5);
|
||||
|
||||
template <typename CellShape,
|
||||
typename CellNodeVecType,
|
||||
typename PointPortalType,
|
||||
typename MortonPortalType,
|
||||
typename CellFaceIdsPortalType>
|
||||
VTKM_EXEC inline void operator()(const CellShape& cellShape,
|
||||
const CellNodeVecType& cellIndices,
|
||||
const vtkm::Id& cellId,
|
||||
const PointPortalType& points,
|
||||
const vtkm::Id& offset,
|
||||
MortonPortalType& mortonCodes,
|
||||
CellFaceIdsPortalType& cellFaceIds) const
|
||||
{
|
||||
vtkm::Int32 faceCount;
|
||||
vtkm::Int32 tableOffset;
|
||||
// suppress some unused variables warnings
|
||||
(void)(CellTypeLookUp);
|
||||
(void)(ZooTable);
|
||||
(void)(ZooLookUp);
|
||||
|
||||
if (cellShape.Id == vtkm::CELL_SHAPE_TETRA)
|
||||
{
|
||||
faceCount = FaceLookUp[1][1];
|
||||
tableOffset = FaceLookUp[1][0];
|
||||
}
|
||||
else if (cellShape.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
|
||||
{
|
||||
faceCount = FaceLookUp[0][1];
|
||||
tableOffset = FaceLookUp[0][0];
|
||||
}
|
||||
else if (cellShape.Id == vtkm::CELL_SHAPE_WEDGE)
|
||||
{
|
||||
faceCount = FaceLookUp[2][1];
|
||||
tableOffset = FaceLookUp[2][0];
|
||||
}
|
||||
else if (cellShape.Id == vtkm::CELL_SHAPE_PYRAMID)
|
||||
{
|
||||
faceCount = FaceLookUp[3][1];
|
||||
tableOffset = FaceLookUp[3][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown shape type %d\n", (int)cellShape.Id);
|
||||
return;
|
||||
}
|
||||
|
||||
//calc the morton code at the center of each face
|
||||
for (vtkm::Int32 i = 0; i < faceCount; ++i)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> center;
|
||||
vtkm::UInt32 code;
|
||||
vtkm::Vec<vtkm::Id, 3> cellFace;
|
||||
cellFace[0] = cellId;
|
||||
|
||||
// We must be sure that this calulation is the same for all faces. If we didn't
|
||||
// then it is possible for the same face to end up in multiple morton "buckets" due to
|
||||
// the wonders of floating point math. This is bad. If we calculate in the same order
|
||||
// for all faces, then at worst, two different faces can enter the same bucket, which
|
||||
// we currently check for.
|
||||
vtkm::Vec<vtkm::Id, 4> faceIndices;
|
||||
faceIndices[3] = -1;
|
||||
const vtkm::Id indiceCount =
|
||||
ShapesFaceList[tableOffset + i][0]; //Number of indices this face has
|
||||
for (vtkm::Int32 j = 1; j <= indiceCount; j++)
|
||||
{
|
||||
faceIndices[j - 1] = cellIndices[ShapesFaceList[tableOffset + i][j]];
|
||||
}
|
||||
//sort the indices in descending order
|
||||
Sort4(faceIndices);
|
||||
|
||||
vtkm::Int32 count = 1;
|
||||
BOUNDS_CHECK(points, faceIndices[0]);
|
||||
center = points.Get(faceIndices[0]);
|
||||
for (int idx = 1; idx < indiceCount; ++idx)
|
||||
{
|
||||
BOUNDS_CHECK(points, faceIndices[idx]);
|
||||
center = center + points.Get(faceIndices[idx]);
|
||||
count++;
|
||||
}
|
||||
//TODO: we could make this a recipical, but this is not a bottleneck.
|
||||
center[0] = center[0] / vtkm::Float32(count + 1);
|
||||
center[1] = center[1] / vtkm::Float32(count + 1);
|
||||
center[2] = center[2] / vtkm::Float32(count + 1);
|
||||
Normalize(center);
|
||||
code = Morton3D(center[0], center[1], center[2]);
|
||||
BOUNDS_CHECK(mortonCodes, offset + i);
|
||||
mortonCodes.Set(offset + i, code);
|
||||
cellFace[1] = i;
|
||||
cellFace[2] = -1; //Need to initialize this for the next step
|
||||
BOUNDS_CHECK(cellFaceIds, offset + i);
|
||||
cellFaceIds.Set(offset + i, cellFace);
|
||||
}
|
||||
}
|
||||
}; // class MortonCodeFace
|
||||
|
||||
class MortonCodeAABB : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
// (1.f / dx),(1.f / dy), (1.f, / dz)
|
||||
vtkm::Vec<vtkm::Float32, 3> InverseExtent;
|
||||
vtkm::Vec<vtkm::Float32, 3> MinCoordinate;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
MortonCodeAABB(const vtkm::Vec<vtkm::Float32, 3>& inverseExtent,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& minCoordinate)
|
||||
: InverseExtent(inverseExtent)
|
||||
, MinCoordinate(minCoordinate)
|
||||
{
|
||||
}
|
||||
|
||||
typedef void
|
||||
ControlSignature(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
|
||||
typedef _7 InputDomain;
|
||||
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Float32& xmin,
|
||||
const vtkm::Float32& ymin,
|
||||
const vtkm::Float32& zmin,
|
||||
const vtkm::Float32& xmax,
|
||||
const vtkm::Float32& ymax,
|
||||
const vtkm::Float32& zmax,
|
||||
vtkm::UInt32& mortonCode) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> direction(xmax - xmin, ymax - ymin, zmax - zmin);
|
||||
vtkm::Float32 halfDistance = sqrtf(vtkm::dot(direction, direction)) * 0.5f;
|
||||
vtkm::Normalize(direction);
|
||||
vtkm::Float32 centroidx = xmin + halfDistance * direction[0] - MinCoordinate[0];
|
||||
vtkm::Float32 centroidy = ymin + halfDistance * direction[1] - MinCoordinate[1];
|
||||
vtkm::Float32 centroidz = zmin + halfDistance * direction[2] - MinCoordinate[2];
|
||||
//normalize the centroid tp 10 bits
|
||||
centroidx *= InverseExtent[0];
|
||||
centroidy *= InverseExtent[1];
|
||||
centroidz *= InverseExtent[2];
|
||||
mortonCode = Morton3D(centroidx, centroidy, centroidz);
|
||||
}
|
||||
}; // class MortonCodeAABB
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif
|
@ -19,9 +19,25 @@
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Ray_h
|
||||
#define vtk_m_rendering_raytracing_Ray_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/rendering/raytracing/ChannelBuffer.h>
|
||||
#include <vtkm/rendering/raytracing/Worklets.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define RAY_ACTIVE 0
|
||||
#define RAY_COMPLETE 1
|
||||
#define RAY_TERMINATED 2
|
||||
#define RAY_EXITED_MESH 3
|
||||
#define RAY_EXITED_DOMAIN 4
|
||||
#define RAY_LOST 5
|
||||
#define RAY_ABANDONED 6
|
||||
#define RAY_TUG_EPSILON 0.001
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
@ -29,66 +45,73 @@ namespace rendering
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class RayBase
|
||||
template <typename Precision>
|
||||
class Ray
|
||||
{
|
||||
public:
|
||||
RayBase() {}
|
||||
protected:
|
||||
bool IntersectionDataEnabled;
|
||||
|
||||
virtual ~RayBase();
|
||||
|
||||
virtual void resize(const vtkm::Int32 vtkmNotUsed(newSize)) {}
|
||||
};
|
||||
template <typename DeviceAdapter>
|
||||
class Ray : public RayBase
|
||||
{
|
||||
public:
|
||||
// composite vectors to hold array handles
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type
|
||||
Intersection;
|
||||
typename //tell the compiler we have a dependent type
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>>::type
|
||||
Intersection;
|
||||
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type Normal;
|
||||
typename //tell the compiler we have a dependent type
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>>::type Normal;
|
||||
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type Origin;
|
||||
typename //tell the compiler we have a dependent type
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>>::type Origin;
|
||||
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type Dir;
|
||||
typename //tell the compiler we have a dependent type
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>,
|
||||
vtkm::cont::ArrayHandle<Precision>>::type Dir;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> IntersectionX; //ray Normal
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> IntersectionY;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> IntersectionZ;
|
||||
vtkm::cont::ArrayHandle<Precision> IntersectionX; //ray Intersection
|
||||
vtkm::cont::ArrayHandle<Precision> IntersectionY;
|
||||
vtkm::cont::ArrayHandle<Precision> IntersectionZ;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> NormalX; //ray Normal
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> NormalY;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> NormalZ;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> OriginX; //ray Origin
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> OriginY;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> OriginZ;
|
||||
vtkm::cont::ArrayHandle<Precision> OriginX; //ray Origin
|
||||
vtkm::cont::ArrayHandle<Precision> OriginY;
|
||||
vtkm::cont::ArrayHandle<Precision> OriginZ;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirX; //ray Dir
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirY;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirZ;
|
||||
vtkm::cont::ArrayHandle<Precision> DirX; //ray Dir
|
||||
vtkm::cont::ArrayHandle<Precision> DirY;
|
||||
vtkm::cont::ArrayHandle<Precision> DirZ;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> U; //barycentric coordinates
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> V;
|
||||
vtkm::cont::ArrayHandle<Precision> U; //barycentric coordinates
|
||||
vtkm::cont::ArrayHandle<Precision> V;
|
||||
vtkm::cont::ArrayHandle<Precision> NormalX; //ray Normal
|
||||
vtkm::cont::ArrayHandle<Precision> NormalY;
|
||||
vtkm::cont::ArrayHandle<Precision> NormalZ;
|
||||
vtkm::cont::ArrayHandle<Precision> Scalar; //scalar
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> Distance; //distance to hit
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> Scalar; //scalar
|
||||
vtkm::cont::ArrayHandle<Precision> Distance; //distance to hit
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> HitIdx;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PixelIdx;
|
||||
|
||||
vtkm::cont::ArrayHandle<Precision> MinDistance; // distance to hit
|
||||
vtkm::cont::ArrayHandle<Precision> MaxDistance; // distance to hit
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> Status; // 0 = active 1 = miss 2 = lost
|
||||
|
||||
std::vector<ChannelBuffer<Precision>> Buffers;
|
||||
vtkm::Id DebugWidth;
|
||||
vtkm::Id DebugHeight;
|
||||
vtkm::Id NumRays;
|
||||
|
||||
vtkm::Int32 NumRays;
|
||||
VTKM_CONT
|
||||
Ray()
|
||||
{
|
||||
IntersectionDataEnabled = false;
|
||||
NumRays = 0;
|
||||
vtkm::IdComponent inComp[3];
|
||||
inComp[0] = 0;
|
||||
@ -105,34 +128,94 @@ public:
|
||||
|
||||
Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
DirX, inComp[0], DirY, inComp[1], DirZ, inComp[2]);
|
||||
|
||||
ChannelBuffer<Precision> buffer;
|
||||
buffer.Resize(NumRays);
|
||||
Buffers.push_back(buffer);
|
||||
DebugWidth = -1;
|
||||
DebugHeight = -1;
|
||||
}
|
||||
VTKM_CONT
|
||||
Ray(const vtkm::Int32 size)
|
||||
|
||||
template <typename Device>
|
||||
void EnableIntersectionData(Device)
|
||||
{
|
||||
if (IntersectionDataEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IntersectionDataEnabled = true;
|
||||
IntersectionX.PrepareForOutput(NumRays, Device());
|
||||
IntersectionY.PrepareForOutput(NumRays, Device());
|
||||
IntersectionZ.PrepareForOutput(NumRays, Device());
|
||||
U.PrepareForOutput(NumRays, Device());
|
||||
V.PrepareForOutput(NumRays, Device());
|
||||
Scalar.PrepareForOutput(NumRays, Device());
|
||||
|
||||
NormalX.PrepareForOutput(NumRays, Device());
|
||||
NormalY.PrepareForOutput(NumRays, Device());
|
||||
NormalZ.PrepareForOutput(NumRays, Device());
|
||||
}
|
||||
|
||||
void DisableIntersectionData()
|
||||
{
|
||||
if (!IntersectionDataEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IntersectionDataEnabled = false;
|
||||
IntersectionX.ReleaseResources();
|
||||
IntersectionY.ReleaseResources();
|
||||
IntersectionZ.ReleaseResources();
|
||||
U.ReleaseResources();
|
||||
V.ReleaseResources();
|
||||
Scalar.ReleaseResources();
|
||||
|
||||
NormalX.ReleaseResources();
|
||||
NormalY.ReleaseResources();
|
||||
NormalZ.ReleaseResources();
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT Ray(const vtkm::Int32 size, Device, bool enableIntersectionData = false)
|
||||
{
|
||||
NumRays = size;
|
||||
|
||||
IntersectionX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
IntersectionY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
IntersectionZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
IntersectionDataEnabled = enableIntersectionData;
|
||||
|
||||
NormalX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
NormalY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
NormalZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
if (IntersectionDataEnabled)
|
||||
{
|
||||
IntersectionX.PrepareForOutput(NumRays, Device());
|
||||
IntersectionY.PrepareForOutput(NumRays, Device());
|
||||
IntersectionZ.PrepareForOutput(NumRays, Device());
|
||||
|
||||
OriginX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
OriginY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
OriginZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
U.PrepareForOutput(NumRays, Device());
|
||||
V.PrepareForOutput(NumRays, Device());
|
||||
|
||||
DirX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
Scalar.PrepareForOutput(NumRays, Device());
|
||||
|
||||
U.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
V.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
Distance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
Scalar.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
NormalX.PrepareForOutput(NumRays, Device());
|
||||
NormalY.PrepareForOutput(NumRays, Device());
|
||||
NormalZ.PrepareForOutput(NumRays, Device());
|
||||
}
|
||||
|
||||
HitIdx.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
OriginX.PrepareForOutput(NumRays, Device());
|
||||
OriginY.PrepareForOutput(NumRays, Device());
|
||||
OriginZ.PrepareForOutput(NumRays, Device());
|
||||
|
||||
DirX.PrepareForOutput(NumRays, Device());
|
||||
DirY.PrepareForOutput(NumRays, Device());
|
||||
DirZ.PrepareForOutput(NumRays, Device());
|
||||
|
||||
Distance.PrepareForOutput(NumRays, Device());
|
||||
|
||||
MinDistance.PrepareForOutput(NumRays, Device());
|
||||
MaxDistance.PrepareForOutput(NumRays, Device());
|
||||
Status.PrepareForOutput(NumRays, Device());
|
||||
|
||||
HitIdx.PrepareForOutput(NumRays, Device());
|
||||
PixelIdx.PrepareForOutput(NumRays, Device());
|
||||
|
||||
vtkm::IdComponent inComp[3];
|
||||
inComp[0] = 0;
|
||||
@ -150,106 +233,26 @@ public:
|
||||
|
||||
Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
DirX, inComp[0], DirY, inComp[1], DirZ, inComp[2]);
|
||||
|
||||
|
||||
ChannelBuffer<Precision> buffer;
|
||||
buffer.Resize(NumRays, Device());
|
||||
this->Buffers.push_back(buffer);
|
||||
|
||||
DebugWidth = -1;
|
||||
DebugHeight = -1;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
virtual void resize(const vtkm::Int32 newSize)
|
||||
void AddBuffer(const vtkm::Int32 numChannels, const std::string name)
|
||||
{
|
||||
if (newSize == NumRays)
|
||||
return; //nothing to do
|
||||
|
||||
NumRays = newSize;
|
||||
|
||||
IntersectionX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
IntersectionY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
IntersectionZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
NormalX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
NormalY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
NormalZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
OriginX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
OriginY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
OriginZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
DirX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
U.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
V.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
Distance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
Scalar.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
HitIdx.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
}
|
||||
|
||||
}; // class ray
|
||||
template <typename DeviceAdapter>
|
||||
class VolumeRay : public RayBase
|
||||
{
|
||||
public:
|
||||
vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type Dir;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirX; //ray Dir
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirY;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> DirZ;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> MinDistance; //distance to hit
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> MaxDistance; //distance to hit
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> HitIndex;
|
||||
vtkm::Int32 NumRays;
|
||||
VTKM_CONT
|
||||
VolumeRay()
|
||||
{
|
||||
NumRays = 0;
|
||||
vtkm::IdComponent inComp[3];
|
||||
inComp[0] = 0;
|
||||
inComp[1] = 1;
|
||||
inComp[2] = 2;
|
||||
|
||||
Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
DirX, inComp[0], DirY, inComp[1], DirZ, inComp[2]);
|
||||
}
|
||||
VTKM_CONT
|
||||
VolumeRay(const vtkm::Int32 size)
|
||||
{
|
||||
NumRays = size;
|
||||
|
||||
DirX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
MinDistance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
MaxDistance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
HitIndex.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
vtkm::IdComponent inComp[3];
|
||||
inComp[0] = 0;
|
||||
inComp[1] = 1;
|
||||
inComp[2] = 2;
|
||||
|
||||
Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
DirX, inComp[0], DirY, inComp[1], DirZ, inComp[2]);
|
||||
}
|
||||
VTKM_CONT
|
||||
virtual void resize(const vtkm::Int32 newSize)
|
||||
{
|
||||
if (newSize == NumRays)
|
||||
return; //nothing to do
|
||||
|
||||
NumRays = newSize;
|
||||
|
||||
DirX.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirY.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
DirZ.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
|
||||
MinDistance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
MaxDistance.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
HitIndex.PrepareForOutput(NumRays, DeviceAdapter());
|
||||
ChannelBuffer<Precision> buffer(numChannels, this->NumRays);
|
||||
buffer.SetName(name);
|
||||
this->Buffers.push_back(buffer);
|
||||
}
|
||||
|
||||
friend class RayOperations;
|
||||
}; // class ray
|
||||
}
|
||||
}
|
||||
|
292
vtkm/rendering/raytracing/RayOperations.h
Normal file
292
vtkm/rendering/raytracing/RayOperations.h
Normal file
@ -0,0 +1,292 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Ray_Operations_h
|
||||
#define vtk_m_rendering_raytracing_Ray_Operations_h
|
||||
|
||||
#include <vtkm/rendering/raytracing/ChannelBufferOperations.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
#include <vtkm/rendering/raytracing/Worklets.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class RayStatusFilter : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
RayStatusFilter() {}
|
||||
typedef void ControlSignature(FieldIn<>, FieldInOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& hitIndex, vtkm::UInt8& rayStatus) const
|
||||
{
|
||||
if (hitIndex == -1)
|
||||
rayStatus = RAY_EXITED_DOMAIN;
|
||||
else if (rayStatus != RAY_EXITED_DOMAIN && rayStatus != RAY_TERMINATED)
|
||||
rayStatus = RAY_ACTIVE;
|
||||
//else printf("Bad status state %d \n",(int)rayStatus);
|
||||
}
|
||||
}; //class RayStatusFileter
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class RayOperations
|
||||
{
|
||||
public:
|
||||
template <typename Device, typename T>
|
||||
static void ResetStatus(Ray<T>& rays, vtkm::UInt8 status, Device)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<MemSet<vtkm::UInt8>, Device>(MemSet<vtkm::UInt8>(status))
|
||||
.Invoke(rays.Status);
|
||||
}
|
||||
|
||||
//
|
||||
// Some worklets like triangle intersection do not set the
|
||||
// ray status, so this operation sets the status based on
|
||||
// the ray hit index
|
||||
//
|
||||
template <typename Device, typename T>
|
||||
static void UpdateRayStatus(Ray<T>& rays, Device)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<detail::RayStatusFilter, Device>(detail::RayStatusFilter())
|
||||
.Invoke(rays.HitIdx, rays.Status);
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static vtkm::Id RaysInMesh(Ray<T>& rays, Device)
|
||||
{
|
||||
vtkm::Vec<UInt8, 2> maskValues;
|
||||
maskValues[0] = RAY_ACTIVE;
|
||||
maskValues[1] = RAY_LOST;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> masks;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<ManyMask<vtkm::UInt8, 2>, Device>(
|
||||
ManyMask<vtkm::UInt8, 2>(maskValues))
|
||||
.Invoke(rays.Status, masks);
|
||||
vtkm::cont::ArrayHandleCast<vtkm::Id, vtkm::cont::ArrayHandle<vtkm::UInt8>> castedMasks(masks);
|
||||
const vtkm::Id initVal = 0;
|
||||
vtkm::Id count = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(castedMasks, initVal);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static vtkm::Id GetStatusCount(Ray<T>& rays, vtkm::Id status, Device)
|
||||
{
|
||||
vtkm::UInt8 statusUInt8;
|
||||
if (status < 0 || status > 255)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Rays GetStatusCound: invalid status");
|
||||
return 0;
|
||||
}
|
||||
|
||||
statusUInt8 = static_cast<vtkm::UInt8>(status);
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> masks;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<Mask<vtkm::UInt8>, Device>(Mask<vtkm::UInt8>(statusUInt8))
|
||||
.Invoke(rays.Status, masks);
|
||||
vtkm::cont::ArrayHandleCast<vtkm::Id, vtkm::cont::ArrayHandle<vtkm::UInt8>> castedMasks(masks);
|
||||
const vtkm::Id initVal = 0;
|
||||
vtkm::Id count = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(castedMasks, initVal);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static vtkm::Id RaysProcessed(Ray<T>& rays, Device)
|
||||
{
|
||||
vtkm::Vec<UInt8, 3> maskValues;
|
||||
maskValues[0] = RAY_TERMINATED;
|
||||
maskValues[1] = RAY_EXITED_DOMAIN;
|
||||
maskValues[2] = RAY_ABANDONED;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> masks;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<ManyMask<vtkm::UInt8, 3>, Device>(
|
||||
ManyMask<vtkm::UInt8, 3>(maskValues))
|
||||
.Invoke(rays.Status, masks);
|
||||
vtkm::cont::ArrayHandleCast<vtkm::Id, vtkm::cont::ArrayHandle<vtkm::UInt8>> castedMasks(masks);
|
||||
const vtkm::Id initVal = 0;
|
||||
vtkm::Id count = vtkm::cont::DeviceAdapterAlgorithm<Device>::Reduce(castedMasks, initVal);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static vtkm::cont::ArrayHandle<vtkm::UInt8> CompactActiveRays(Ray<T>& rays, Device)
|
||||
{
|
||||
vtkm::Vec<UInt8, 1> maskValues;
|
||||
maskValues[0] = RAY_ACTIVE;
|
||||
vtkm::UInt8 statusUInt8 = static_cast<vtkm::UInt8>(RAY_ACTIVE);
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> masks;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<Mask<vtkm::UInt8>, Device>(Mask<vtkm::UInt8>(statusUInt8))
|
||||
.Invoke(rays.Status, masks);
|
||||
|
||||
//
|
||||
// Make empty composite vectors so we dont use up extra storage
|
||||
//
|
||||
vtkm::IdComponent inComp[3];
|
||||
inComp[0] = 0;
|
||||
inComp[1] = 1;
|
||||
inComp[2] = 2;
|
||||
|
||||
vtkm::cont::ArrayHandle<T> emptyHandle;
|
||||
|
||||
|
||||
rays.Normal = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
emptyHandle, inComp[0], emptyHandle, inComp[1], emptyHandle, inComp[2]);
|
||||
|
||||
rays.Origin = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
emptyHandle, inComp[0], emptyHandle, inComp[1], emptyHandle, inComp[2]);
|
||||
|
||||
rays.Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
emptyHandle, inComp[0], emptyHandle, inComp[1], emptyHandle, inComp[2]);
|
||||
const vtkm::Int32 numFloatArrays = 18;
|
||||
vtkm::cont::ArrayHandle<T>* floatArrayPointers[numFloatArrays];
|
||||
floatArrayPointers[0] = &rays.OriginX;
|
||||
floatArrayPointers[1] = &rays.OriginY;
|
||||
floatArrayPointers[2] = &rays.OriginZ;
|
||||
floatArrayPointers[3] = &rays.DirX;
|
||||
floatArrayPointers[4] = &rays.DirY;
|
||||
floatArrayPointers[5] = &rays.DirZ;
|
||||
floatArrayPointers[6] = &rays.Distance;
|
||||
floatArrayPointers[7] = &rays.MinDistance;
|
||||
floatArrayPointers[8] = &rays.MaxDistance;
|
||||
|
||||
floatArrayPointers[9] = &rays.Scalar;
|
||||
floatArrayPointers[10] = &rays.IntersectionX;
|
||||
floatArrayPointers[11] = &rays.IntersectionY;
|
||||
floatArrayPointers[12] = &rays.IntersectionZ;
|
||||
floatArrayPointers[13] = &rays.U;
|
||||
floatArrayPointers[14] = &rays.V;
|
||||
floatArrayPointers[15] = &rays.NormalX;
|
||||
floatArrayPointers[16] = &rays.NormalY;
|
||||
floatArrayPointers[17] = &rays.NormalZ;
|
||||
|
||||
const int breakPoint = rays.IntersectionDataEnabled ? -1 : 9;
|
||||
for (int i = 0; i < numFloatArrays; ++i)
|
||||
{
|
||||
if (i == breakPoint)
|
||||
{
|
||||
break;
|
||||
}
|
||||
vtkm::cont::ArrayHandle<T> compacted;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(*floatArrayPointers[i], masks, compacted);
|
||||
*floatArrayPointers[i] = compacted;
|
||||
}
|
||||
|
||||
//
|
||||
// restore the composite vectors
|
||||
//
|
||||
rays.Normal = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
rays.NormalX, inComp[0], rays.NormalY, inComp[1], rays.NormalZ, inComp[2]);
|
||||
|
||||
rays.Origin = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
rays.OriginX, inComp[0], rays.OriginY, inComp[1], rays.OriginZ, inComp[2]);
|
||||
|
||||
rays.Dir = vtkm::cont::make_ArrayHandleCompositeVector(
|
||||
rays.DirX, inComp[0], rays.DirY, inComp[1], rays.DirZ, inComp[2]);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> compactedHits;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(rays.HitIdx, masks, compactedHits);
|
||||
rays.HitIdx = compactedHits;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> compactedPixels;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(rays.PixelIdx, masks, compactedPixels);
|
||||
rays.PixelIdx = compactedPixels;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> compactedStatus;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::CopyIf(rays.Status, masks, compactedStatus);
|
||||
rays.Status = compactedStatus;
|
||||
|
||||
rays.NumRays = rays.Status.GetPortalConstControl().GetNumberOfValues();
|
||||
|
||||
const size_t bufferCount = static_cast<size_t>(rays.Buffers.size());
|
||||
for (size_t i = 0; i < bufferCount; ++i)
|
||||
{
|
||||
ChannelBufferOperations::Compact(rays.Buffers[i], masks, rays.NumRays, Device());
|
||||
}
|
||||
return masks;
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static void Resize(Ray<T>& rays, const vtkm::Int32 newSize, Device)
|
||||
{
|
||||
if (newSize == rays.NumRays)
|
||||
return; //nothing to do
|
||||
|
||||
rays.NumRays = newSize;
|
||||
|
||||
if (rays.IntersectionDataEnabled)
|
||||
{
|
||||
rays.IntersectionX.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.IntersectionY.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.IntersectionZ.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.U.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.V.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.Scalar.PrepareForOutput(rays.NumRays, Device());
|
||||
|
||||
rays.NormalX.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.NormalY.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.NormalZ.PrepareForOutput(rays.NumRays, Device());
|
||||
}
|
||||
|
||||
rays.OriginX.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.OriginY.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.OriginZ.PrepareForOutput(rays.NumRays, Device());
|
||||
|
||||
rays.DirX.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.DirY.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.DirZ.PrepareForOutput(rays.NumRays, Device());
|
||||
|
||||
rays.Distance.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.MinDistance.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.MaxDistance.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.Status.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.HitIdx.PrepareForOutput(rays.NumRays, Device());
|
||||
rays.PixelIdx.PrepareForOutput(rays.NumRays, Device());
|
||||
|
||||
const size_t bufferCount = static_cast<size_t>(rays.Buffers.size());
|
||||
for (size_t i = 0; i < bufferCount; ++i)
|
||||
{
|
||||
rays.Buffers[i].Resize(rays.NumRays, Device());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Device, typename T>
|
||||
static void CopyDistancesToMin(Ray<T> rays, Device, const T offset = 0.f)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<CopyAndOffsetMask<T>, Device>(
|
||||
CopyAndOffsetMask<T>(offset, RAY_EXITED_MESH))
|
||||
.Invoke(rays.Distance, rays.MinDistance, rays.Status);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace vktm::rendering::raytracing
|
||||
#endif
|
531
vtkm/rendering/raytracing/RayTracer.cxx
Normal file
531
vtkm/rendering/raytracing/RayTracer.cxx
Normal file
@ -0,0 +1,531 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/raytracing/RayTracer.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class IntersectionPoint : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
IntersectionPoint() {}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>);
|
||||
typedef void ExecutionSignature(_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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst IndicesArrayPortal;
|
||||
|
||||
IndicesArrayPortal IndicesPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CalculateNormals(const Vec4IntArrayHandle& indices)
|
||||
: IndicesPortal(indices.PrepareForInput(Device()))
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<Vec3RenderingTypes>);
|
||||
typedef void ExecutionSignature(_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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst IndicesArrayPortal;
|
||||
|
||||
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;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<ScalarRenderingTypes>);
|
||||
typedef void ExecutionSignature(_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:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef typename Vec4IntArrayHandle::ExecutionTypes<Device>::PortalConst IndicesArrayPortal;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>, WholeArrayIn<ScalarRenderingTypes>);
|
||||
|
||||
typedef void ExecutionSignature(_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::DynamicArrayHandleCoordinateSystem& coordsHandle,
|
||||
const vtkm::cont::Field* scalarField,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
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 accociated with cell set or points");
|
||||
bool isAssocPoints = scalarField->GetAssociation() == vtkm::cont::Field::ASSOC_POINTS;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<CalculateNormals, Device>(CalculateNormals(bvh.LeafNodes))
|
||||
.Invoke(rays.HitIdx, rays.Dir, rays.NormalX, rays.NormalY, rays.NormalZ, coordsHandle);
|
||||
|
||||
if (isAssocPoints)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<LerpScalar<Precision>, Device>(
|
||||
LerpScalar<Precision>(
|
||||
bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
|
||||
.Invoke(rays.HitIdx, rays.U, rays.V, rays.Scalar, *scalarField);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<NodalScalar<Precision>, Device>(
|
||||
NodalScalar<Precision>(
|
||||
bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
|
||||
.Invoke(rays.HitIdx, rays.Scalar, *scalarField);
|
||||
}
|
||||
} // Run
|
||||
|
||||
}; // Class IntersectionData
|
||||
|
||||
template <typename Device>
|
||||
class SurfaceColor
|
||||
{
|
||||
public:
|
||||
class MapScalarToColor : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorArrayHandle;
|
||||
typedef typename ColorArrayHandle::ExecutionTypes<Device>::PortalConst ColorArrayPortal;
|
||||
|
||||
ColorArrayPortal ColorMap;
|
||||
vtkm::Int32 ColorMapSize;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightPosition;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightAbmient;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightDiffuse;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightSpecular;
|
||||
vtkm::Float32 SpecularExponent;
|
||||
vtkm::Vec<vtkm::Float32, 3> CameraPosition;
|
||||
vtkm::Vec<vtkm::Float32, 3> LookAt;
|
||||
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
MapScalarToColor(const ColorArrayHandle& colorMap,
|
||||
const vtkm::Int32& colorMapSize,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& lightPosition,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& cameraPosition,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& lookAt,
|
||||
const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
||||
: ColorMap(colorMap.PrepareForInput(Device()))
|
||||
, ColorMapSize(colorMapSize)
|
||||
, LightPosition(lightPosition)
|
||||
, CameraPosition(cameraPosition)
|
||||
, LookAt(lookAt)
|
||||
, BackgroundColor(backgroundColor)
|
||||
{
|
||||
//Set up some default lighting parameters for now
|
||||
LightAbmient[0] = .5f;
|
||||
LightAbmient[1] = .5f;
|
||||
LightAbmient[2] = .5f;
|
||||
LightDiffuse[0] = .7f;
|
||||
LightDiffuse[1] = .7f;
|
||||
LightDiffuse[2] = .7f;
|
||||
LightSpecular[0] = .7f;
|
||||
LightSpecular[1] = .7f;
|
||||
LightSpecular[2] = .7f;
|
||||
SpecularExponent = 20.f;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, WholeArrayInOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, WorkIndex);
|
||||
template <typename ColorPortalType, typename Precision>
|
||||
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,
|
||||
const vtkm::Id& idx) const
|
||||
{
|
||||
vtkm::Vec<Precision, 4> color;
|
||||
vtkm::Id offset = idx * 4;
|
||||
|
||||
if (hitIdx < 0)
|
||||
{
|
||||
color = BackgroundColor;
|
||||
colors.Set(offset + 0, color[0]);
|
||||
colors.Set(offset + 1, color[1]);
|
||||
colors.Set(offset + 2, color[2]);
|
||||
colors.Set(offset + 3, color[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
color[0] = colors.Get(offset + 0);
|
||||
color[1] = colors.Get(offset + 1);
|
||||
color[2] = colors.Get(offset + 2);
|
||||
color[3] = colors.Get(offset + 3);
|
||||
|
||||
vtkm::Vec<Precision, 3> lightDir = LightPosition - intersection;
|
||||
vtkm::Vec<Precision, 3> viewDir = CameraPosition - LookAt;
|
||||
vtkm::Normalize(lightDir);
|
||||
vtkm::Normalize(viewDir);
|
||||
//Diffuse lighting
|
||||
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::Normalize(reflect);
|
||||
Precision cosPhi = vtkm::dot(reflect, viewDir);
|
||||
Precision specularConstant = Precision(pow(vtkm::Max(cosPhi, zero), SpecularExponent));
|
||||
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);
|
||||
|
||||
color[0] *= vtkm::Min(
|
||||
LightAbmient[0] + LightDiffuse[0] * cosTheta + LightSpecular[0] * specularConstant, one);
|
||||
color[1] *= vtkm::Min(
|
||||
LightAbmient[1] + LightDiffuse[1] * cosTheta + LightSpecular[1] * specularConstant, one);
|
||||
color[2] *= vtkm::Min(
|
||||
LightAbmient[2] + LightDiffuse[2] * cosTheta + LightSpecular[2] * specularConstant, one);
|
||||
|
||||
//color[0] *= vtkm::Min(LightDiffuse[0] * cosTheta, one);
|
||||
//color[1] *= vtkm::Min(LightDiffuse[1] * cosTheta, one);
|
||||
//color[2] *= vtkm::Min(LightDiffuse[2] * cosTheta, one);
|
||||
|
||||
colors.Set(offset + 0, color[0]);
|
||||
colors.Set(offset + 1, color[1]);
|
||||
colors.Set(offset + 2, color[2]);
|
||||
colors.Set(offset + 3, color[3]);
|
||||
}
|
||||
|
||||
}; //class MapScalarToColor
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_CONT void run(Ray<Precision>& rays,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap,
|
||||
const vtkm::rendering::raytracing::Camera& camera,
|
||||
const vtkm::Vec<vtkm::Float32, 4> backgroundColor)
|
||||
{
|
||||
// TODO: support light positions
|
||||
vtkm::Vec<vtkm::Float32, 3> scale(5, 5, 5);
|
||||
vtkm::Vec<vtkm::Float32, 3> lightPosition = camera.GetPosition() + scale * camera.GetUp();
|
||||
const vtkm::Int32 colorMapSize = vtkm::Int32(colorMap.GetNumberOfValues());
|
||||
vtkm::worklet::DispatcherMapField<MapScalarToColor, Device>(
|
||||
MapScalarToColor(colorMap,
|
||||
colorMapSize,
|
||||
lightPosition,
|
||||
camera.GetPosition(),
|
||||
camera.GetLookAt(),
|
||||
backgroundColor))
|
||||
.Invoke(rays.HitIdx, rays.Scalar, rays.Normal, rays.Intersection, rays.Buffers.at(0).Buffer);
|
||||
}
|
||||
}; // class SurfaceColor
|
||||
|
||||
} // namespace detail
|
||||
|
||||
RayTracer::RayTracer()
|
||||
{
|
||||
}
|
||||
|
||||
void RayTracer::SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
||||
{
|
||||
BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
Camera& RayTracer::GetCamera()
|
||||
{
|
||||
return camera;
|
||||
}
|
||||
|
||||
void RayTracer::SetData(const vtkm::cont::DynamicArrayHandleCoordinateSystem& coordsHandle,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>>& indices,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::Id& numberOfTriangles,
|
||||
const vtkm::Range& scalarRange,
|
||||
const vtkm::Bounds& dataBounds)
|
||||
{
|
||||
CoordsHandle = coordsHandle;
|
||||
Indices = indices;
|
||||
ScalarField = &scalarField;
|
||||
NumberOfTriangles = numberOfTriangles;
|
||||
ScalarRange = scalarRange;
|
||||
DataBounds = dataBounds;
|
||||
Bvh.SetData(coordsHandle, indices);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
template <typename Device, typename Precision>
|
||||
void RayTracer::RenderOnDevice(Ray<Precision>& rays, Device)
|
||||
{
|
||||
rays.EnableIntersectionData(Device());
|
||||
|
||||
Logger* logger = Logger::GetInstance();
|
||||
vtkm::cont::Timer<Device> renderTimer;
|
||||
vtkm::Float64 time = 0.;
|
||||
logger->OpenLogEntry("ray_tracer");
|
||||
logger->AddLogData("device", GetDeviceString(Device()));
|
||||
|
||||
Bvh.ConstructOnDevice(Device());
|
||||
logger->AddLogData("triangles", NumberOfTriangles);
|
||||
logger->AddLogData("num_rays", rays.NumRays);
|
||||
|
||||
if (NumberOfTriangles > 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();
|
||||
|
||||
// Calculate normal and scalar value (TODO: find a better name)
|
||||
detail::IntersectionData<Device> intData;
|
||||
intData.run(rays, Bvh, CoordsHandle, ScalarField, ScalarRange);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("intersection_data", time);
|
||||
timer.Reset();
|
||||
|
||||
// Find the intersection point from hit distance
|
||||
vtkm::worklet::DispatcherMapField<detail::IntersectionPoint, Device>(
|
||||
detail::IntersectionPoint())
|
||||
.Invoke(rays.HitIdx,
|
||||
rays.Distance,
|
||||
rays.Dir,
|
||||
rays.Origin,
|
||||
rays.IntersectionX,
|
||||
rays.IntersectionY,
|
||||
rays.IntersectionZ);
|
||||
|
||||
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, BackgroundColor);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("shade", time);
|
||||
timer.Reset();
|
||||
}
|
||||
|
||||
time = renderTimer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
} // RenderOnDevice
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::rendering::raytracing
|
@ -19,12 +19,16 @@
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_RayTracer_h
|
||||
#define vtk_m_rendering_raytracing_RayTracer_h
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/ColorTable.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>
|
||||
@ -37,345 +41,12 @@ namespace rendering
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class IntersectionPoint : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
IntersectionPoint() {}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& hitIndex,
|
||||
const vtkm::Float32& distance,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& rayDir,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& rayOrigin,
|
||||
vtkm::Float32& intersectionX,
|
||||
vtkm::Float32& intersectionY,
|
||||
vtkm::Float32& 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 DeviceAdapter>
|
||||
class Reflector
|
||||
{
|
||||
public:
|
||||
// Worklet to calutate the normals of a triagle if
|
||||
// none are stored in the data set
|
||||
class CalculateNormals : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef
|
||||
typename Vec4IntArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IndicesArrayPortal;
|
||||
|
||||
IndicesArrayPortal IndicesPortal;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CalculateNormals(const Vec4IntArrayHandle& indices)
|
||||
: IndicesPortal(indices.PrepareForInput(DeviceAdapter()))
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<Vec3RenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6);
|
||||
template <typename PointPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& rayDir,
|
||||
vtkm::Float32& normalX,
|
||||
vtkm::Float32& normalY,
|
||||
vtkm::Float32& normalZ,
|
||||
const PointPortalType& points) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
|
||||
vtkm::Vec<Float32, 3> a = points.Get(indices[1]);
|
||||
vtkm::Vec<Float32, 3> b = points.Get(indices[2]);
|
||||
vtkm::Vec<Float32, 3> c = points.Get(indices[3]);
|
||||
|
||||
vtkm::Vec<Float32, 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
|
||||
|
||||
class LerpScalar : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef
|
||||
typename Vec4IntArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IndicesArrayPortal;
|
||||
|
||||
IndicesArrayPortal IndicesPortal;
|
||||
vtkm::Float32 MinScalar;
|
||||
vtkm::Float32 invDeltaScalar;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
LerpScalar(const Vec4IntArrayHandle& indices,
|
||||
const vtkm::Float32& minScalar,
|
||||
const vtkm::Float32& maxScalar)
|
||||
: IndicesPortal(indices.PrepareForInput(DeviceAdapter()))
|
||||
, MinScalar(minScalar)
|
||||
{
|
||||
//Make sure the we don't divide by zero on
|
||||
//something like an iso-surface
|
||||
if (maxScalar - MinScalar != 0.f)
|
||||
invDeltaScalar = 1.f / (maxScalar - MinScalar);
|
||||
else
|
||||
invDeltaScalar = 1.f / minScalar;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
WholeArrayIn<ScalarRenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5);
|
||||
template <typename ScalarPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
|
||||
const vtkm::Float32& u,
|
||||
const vtkm::Float32& v,
|
||||
vtkm::Float32& lerpedScalar,
|
||||
const ScalarPortalType& scalars) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
|
||||
|
||||
vtkm::Float32 n = 1.f - u - v;
|
||||
vtkm::Float32 aScalar = vtkm::Float32(scalars.Get(indices[1]));
|
||||
vtkm::Float32 bScalar = vtkm::Float32(scalars.Get(indices[2]));
|
||||
vtkm::Float32 cScalar = vtkm::Float32(scalars.Get(indices[3]));
|
||||
lerpedScalar = aScalar * n + bScalar * u + cScalar * v;
|
||||
//normalize
|
||||
lerpedScalar = (lerpedScalar - MinScalar) * invDeltaScalar;
|
||||
}
|
||||
}; //class LerpScalar
|
||||
|
||||
class NodalScalar : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int32, 4>> Vec4IntArrayHandle;
|
||||
typedef
|
||||
typename Vec4IntArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IndicesArrayPortal;
|
||||
|
||||
IndicesArrayPortal IndicesPortal;
|
||||
vtkm::Float32 MinScalar;
|
||||
vtkm::Float32 invDeltaScalar;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
NodalScalar(const Vec4IntArrayHandle& indices,
|
||||
const vtkm::Float32& minScalar,
|
||||
const vtkm::Float32& maxScalar)
|
||||
: IndicesPortal(indices.PrepareForInput(DeviceAdapter()))
|
||||
, MinScalar(minScalar)
|
||||
{
|
||||
//Make sure the we don't divide by zero on
|
||||
//something like an iso-surface
|
||||
if (maxScalar - MinScalar != 0.f)
|
||||
invDeltaScalar = 1.f / (maxScalar - MinScalar);
|
||||
else
|
||||
invDeltaScalar = 1.f / minScalar;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>, WholeArrayIn<ScalarRenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
template <typename ScalarPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
|
||||
vtkm::Float32& scalar,
|
||||
const ScalarPortalType& scalars) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Vec<Int32, 4> indices = IndicesPortal.Get(hitIndex);
|
||||
|
||||
//Todo: one normalization
|
||||
scalar = vtkm::Float32(scalars.Get(indices[0]));
|
||||
|
||||
//normalize
|
||||
scalar = (scalar - MinScalar) * invDeltaScalar;
|
||||
}
|
||||
}; //class LerpScalar
|
||||
|
||||
VTKM_CONT
|
||||
void run(Ray<DeviceAdapter>& rays,
|
||||
LinearBVH& bvh,
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem& coordsHandle,
|
||||
const vtkm::cont::Field* scalarField,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
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 accociated with cell set or points");
|
||||
bool isAssocPoints = scalarField->GetAssociation() == vtkm::cont::Field::ASSOC_POINTS;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<CalculateNormals>(CalculateNormals(bvh.LeafNodes))
|
||||
.Invoke(rays.HitIdx, rays.Dir, rays.NormalX, rays.NormalY, rays.NormalZ, coordsHandle);
|
||||
|
||||
if (isAssocPoints)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<LerpScalar>(
|
||||
LerpScalar(bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
|
||||
.Invoke(rays.HitIdx, rays.U, rays.V, rays.Scalar, *scalarField);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<NodalScalar>(
|
||||
NodalScalar(bvh.LeafNodes, vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
|
||||
.Invoke(rays.HitIdx, rays.Scalar, *scalarField);
|
||||
}
|
||||
} // Run
|
||||
|
||||
}; // Class reflector
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
class SurfaceColor
|
||||
{
|
||||
public:
|
||||
class MapScalarToColor : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorArrayHandle;
|
||||
typedef typename ColorArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst ColorArrayPortal;
|
||||
|
||||
ColorArrayPortal ColorMap;
|
||||
vtkm::Int32 ColorMapSize;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightPosition;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightAbmient;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightDiffuse;
|
||||
vtkm::Vec<vtkm::Float32, 3> LightSpecular;
|
||||
vtkm::Float32 SpecularExponent;
|
||||
vtkm::Vec<vtkm::Float32, 3> CameraPosition;
|
||||
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
MapScalarToColor(const ColorArrayHandle& colorMap,
|
||||
const vtkm::Int32& colorMapSize,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& lightPosition,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& cameraPosition,
|
||||
const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
||||
: ColorMap(colorMap.PrepareForInput(DeviceAdapter()))
|
||||
, ColorMapSize(colorMapSize)
|
||||
, LightPosition(lightPosition)
|
||||
, CameraPosition(cameraPosition)
|
||||
, BackgroundColor(backgroundColor)
|
||||
{
|
||||
//Set up some default lighting parameters for now
|
||||
LightAbmient[0] = .3f;
|
||||
LightAbmient[1] = .3f;
|
||||
LightAbmient[2] = .3f;
|
||||
LightDiffuse[0] = .7f;
|
||||
LightDiffuse[1] = .7f;
|
||||
LightDiffuse[2] = .7f;
|
||||
LightSpecular[0] = .7f;
|
||||
LightSpecular[1] = .7f;
|
||||
LightSpecular[2] = .7f;
|
||||
SpecularExponent = 80.f;
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldIn<>, FieldIn<>, FieldIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Id& hitIdx,
|
||||
const vtkm::Float32& scalar,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& normal,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& intersection,
|
||||
vtkm::Vec<vtkm::Float32, 4>& color) const
|
||||
{
|
||||
if (hitIdx < 0)
|
||||
{
|
||||
color = BackgroundColor;
|
||||
return;
|
||||
}
|
||||
vtkm::Vec<vtkm::Float32, 3> lightDir = LightPosition - intersection;
|
||||
vtkm::Vec<vtkm::Float32, 3> viewDir = CameraPosition - intersection;
|
||||
vtkm::Normalize(lightDir);
|
||||
vtkm::Normalize(viewDir);
|
||||
|
||||
//Diffuse lighting
|
||||
vtkm::Float32 cosTheta = vtkm::dot(-normal, lightDir);
|
||||
//clamp tp [0,1]
|
||||
cosTheta = vtkm::Min(vtkm::Max(cosTheta, 0.f), 1.f);
|
||||
|
||||
//Specular lighting
|
||||
vtkm::Vec<vtkm::Float32, 3> halfVector = viewDir + lightDir;
|
||||
vtkm::Normalize(halfVector);
|
||||
vtkm::Float32 cosPhi = vtkm::dot(-normal, halfVector);
|
||||
vtkm::Float32 specularConstant = vtkm::Float32(pow(fmaxf(cosPhi, 0.f), SpecularExponent));
|
||||
|
||||
vtkm::Int32 colorIdx = vtkm::Int32(scalar * vtkm::Float32(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);
|
||||
//std::cout<<" Before "<<color<< " at index "<<colorIdx<<" ";
|
||||
//std::cout<<"CosTheta "<<cosTheta<<" CosPhi "<<cosPhi<<" | ";
|
||||
color[0] *= vtkm::Min(
|
||||
LightAbmient[0] + LightDiffuse[0] * cosTheta + LightSpecular[0] * specularConstant, 1.f);
|
||||
color[1] *= vtkm::Min(
|
||||
LightAbmient[1] + LightDiffuse[1] * cosTheta + LightSpecular[1] * specularConstant, 1.f);
|
||||
color[2] *= vtkm::Min(
|
||||
LightAbmient[2] + LightDiffuse[2] * cosTheta + LightSpecular[2] * specularConstant, 1.f);
|
||||
//color[0] =1.f;
|
||||
//std::cout<<color;
|
||||
}
|
||||
}; //class MapScalarToColor
|
||||
|
||||
VTKM_CONT
|
||||
void run(Ray<DeviceAdapter>& rays,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap,
|
||||
ColorBuffer4f& colorBuffer,
|
||||
const vtkm::Vec<vtkm::Float32, 3> cameraPosition,
|
||||
const vtkm::Vec<vtkm::Float32, 4> backgroundColor)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> lightPosition = cameraPosition;
|
||||
// lightPosition[0] = 0.f;
|
||||
// lightPosition[1] = 0.f;
|
||||
// lightPosition[2] = -10.f;
|
||||
const vtkm::Int32 colorMapSize = vtkm::Int32(colorMap.GetNumberOfValues());
|
||||
vtkm::worklet::DispatcherMapField<MapScalarToColor>(
|
||||
MapScalarToColor(colorMap, colorMapSize, lightPosition, cameraPosition, backgroundColor))
|
||||
.Invoke(rays.HitIdx, rays.Scalar, rays.Normal, rays.Intersection, colorBuffer);
|
||||
}
|
||||
}; // class SurfaceColor
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
class RayTracer
|
||||
{
|
||||
protected:
|
||||
bool IsSceneDirty;
|
||||
Ray<DeviceAdapter> Rays;
|
||||
LinearBVHBuilder<DeviceAdapter> Builder;
|
||||
LinearBVH Bvh;
|
||||
Camera<DeviceAdapter> camera;
|
||||
Camera camera;
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem CoordsHandle;
|
||||
const vtkm::cont::Field* ScalarField;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 4>> Indices;
|
||||
@ -385,19 +56,21 @@ protected:
|
||||
vtkm::Range ScalarRange;
|
||||
vtkm::Bounds DataBounds;
|
||||
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
|
||||
template <typename Precision>
|
||||
struct RenderFunctor;
|
||||
|
||||
template <typename Device, typename Precision>
|
||||
void RenderOnDevice(Ray<Precision>& rays, Device);
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
RayTracer() { IsSceneDirty = true; }
|
||||
RayTracer();
|
||||
|
||||
VTKM_CONT
|
||||
void SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor)
|
||||
{
|
||||
BackgroundColor = backgroundColor;
|
||||
}
|
||||
void SetBackgroundColor(const vtkm::Vec<vtkm::Float32, 4>& backgroundColor);
|
||||
|
||||
VTKM_CONT
|
||||
Camera<DeviceAdapter>& GetCamera() { return camera; }
|
||||
Camera& GetCamera();
|
||||
|
||||
VTKM_CONT
|
||||
void SetData(const vtkm::cont::DynamicArrayHandleCoordinateSystem& coordsHandle,
|
||||
@ -405,57 +78,14 @@ public:
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::Id& numberOfTriangles,
|
||||
const vtkm::Range& scalarRange,
|
||||
const vtkm::Bounds& dataBounds)
|
||||
{
|
||||
IsSceneDirty = true;
|
||||
CoordsHandle = coordsHandle;
|
||||
Indices = indices;
|
||||
ScalarField = &scalarField;
|
||||
NumberOfTriangles = numberOfTriangles;
|
||||
ScalarRange = scalarRange;
|
||||
DataBounds = dataBounds;
|
||||
}
|
||||
const vtkm::Bounds& dataBounds);
|
||||
|
||||
VTKM_CONT
|
||||
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap)
|
||||
{
|
||||
ColorMap = colorMap;
|
||||
}
|
||||
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap);
|
||||
|
||||
VTKM_CONT
|
||||
void Init()
|
||||
{
|
||||
Builder.run(CoordsHandle, Indices, NumberOfTriangles, Bvh);
|
||||
camera.CreateRays(Rays, DataBounds);
|
||||
IsSceneDirty = false;
|
||||
}
|
||||
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float32>& rays);
|
||||
void Render(vtkm::rendering::raytracing::Ray<vtkm::Float64>& rays);
|
||||
|
||||
VTKM_CONT
|
||||
void Render(CanvasRayTracer* canvas)
|
||||
{
|
||||
if (IsSceneDirty)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
TriangleIntersector<DeviceAdapter> intersector;
|
||||
intersector.run(Rays, Bvh, CoordsHandle);
|
||||
Reflector<DeviceAdapter> reflector;
|
||||
reflector.run(Rays, Bvh, CoordsHandle, ScalarField, ScalarRange);
|
||||
vtkm::worklet::DispatcherMapField<IntersectionPoint>(IntersectionPoint())
|
||||
.Invoke(Rays.HitIdx,
|
||||
Rays.Distance,
|
||||
Rays.Dir,
|
||||
Rays.Origin,
|
||||
Rays.IntersectionX,
|
||||
Rays.IntersectionY,
|
||||
Rays.IntersectionZ);
|
||||
|
||||
SurfaceColor<DeviceAdapter> surfaceColor;
|
||||
surfaceColor.run(Rays, ColorMap, camera.FrameBuffer, camera.GetPosition(), BackgroundColor);
|
||||
|
||||
camera.WriteToSurface(canvas, Rays.Distance);
|
||||
}
|
||||
}; //class RayTracer
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,84 @@
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_RayTracingTypeDefs_h
|
||||
#define vtk_m_rendering_raytracing_RayTracingTypeDefs_h
|
||||
|
||||
#include <type_traits>
|
||||
#include <vtkm/ListTag.h>
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/DeviceAdapterListTag.h>
|
||||
#include <vtkm/cont/DynamicArrayHandle.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
// A more useful bounds check that tells you where it happened
|
||||
#ifndef NDEBUG
|
||||
#define BOUNDS_CHECK(HANDLE, INDEX) \
|
||||
{ \
|
||||
BoundsCheck((HANDLE), (INDEX), __FILE__, __LINE__); \
|
||||
}
|
||||
#else
|
||||
#define BOUNDS_CHECK(HANDLE, INDEX)
|
||||
#endif
|
||||
|
||||
template <typename ArrayHandleType>
|
||||
inline void BoundsCheck(const ArrayHandleType& handle,
|
||||
const vtkm::Id& index,
|
||||
const char* file,
|
||||
int line)
|
||||
{
|
||||
if (index < 0 || index >= handle.GetNumberOfValues())
|
||||
printf("Bad Index %d at file %s line %d\n", (int)index, file, line);
|
||||
}
|
||||
|
||||
namespace raytracing
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT inline void GetInfinity(T& vtkmNotUsed(infinity));
|
||||
//{
|
||||
// static_assert(!std::is_floating_point<T>(),
|
||||
// "Get Infinity can only be called with float or double");
|
||||
//}
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline void GetInfinity<vtkm::Float32>(vtkm::Float32& infinity)
|
||||
{
|
||||
infinity = vtkm::Infinity32();
|
||||
}
|
||||
|
||||
template <>
|
||||
VTKM_EXEC_CONT inline void GetInfinity<vtkm::Float64>(vtkm::Float64& infinity)
|
||||
{
|
||||
infinity = vtkm::Infinity64();
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
inline std::string GetDeviceString(Device);
|
||||
|
||||
template <>
|
||||
inline std::string GetDeviceString<vtkm::cont::DeviceAdapterTagSerial>(
|
||||
vtkm::cont::DeviceAdapterTagSerial)
|
||||
{
|
||||
return "serial";
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string GetDeviceString<vtkm::cont::DeviceAdapterTagTBB>(vtkm::cont::DeviceAdapterTagTBB)
|
||||
{
|
||||
return "tbb";
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string GetDeviceString<vtkm::cont::DeviceAdapterTagCuda>(
|
||||
vtkm::cont::DeviceAdapterTagCuda)
|
||||
{
|
||||
return "cuda";
|
||||
}
|
||||
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorBuffer4f;
|
||||
typedef vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::UInt8, 4>> ColorBuffer4b;
|
||||
@ -47,6 +117,73 @@ typedef vtkm::Float64 ScalarD;
|
||||
struct ScalarRenderingTypes : vtkm::ListTagBase<ScalarF, ScalarD>
|
||||
{
|
||||
};
|
||||
|
||||
//Restrict Coordinate types to explicit for volume renderer
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::type
|
||||
ArrayHandleCompositeVectorFloat32_3Default;
|
||||
|
||||
typedef vtkm::cont::ArrayHandleCompositeVectorType<vtkm::cont::ArrayHandle<vtkm::Float64>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64>>::type
|
||||
ArrayHandleCompositeVectorFloat64_3Default;
|
||||
|
||||
struct StructuredStorageListTagCoordinateSystem
|
||||
: vtkm::ListTagBase<vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
vtkm::cont::ArrayHandleCartesianProduct<
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>::StorageTag>
|
||||
{
|
||||
};
|
||||
/*
|
||||
* This would be for support of curvilinear meshes
|
||||
struct StructuredStorageListTagCoordinateSystem
|
||||
: vtkm::ListTagJoin<
|
||||
VTKM_DEFAULT_STORAGE_LIST_TAG,
|
||||
vtkm::ListTagBase<vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
vtkm::cont::ArrayHandleCartesianProduct<
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> >::StorageTag > >
|
||||
{ };*/
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/*
|
||||
* This is a less restrictive type list for Explicit meshes
|
||||
struct ExplicitCoordinatesType : vtkm::ListTagBase<vtkm::Vec<vtkm::Float32,3>,
|
||||
vtkm::Vec<vtkm::Float64,3> > {};
|
||||
|
||||
|
||||
struct StorageListTagExplicitCoordinateSystem
|
||||
: vtkm::ListTagBase<vtkm::cont::StorageTagBasic,
|
||||
detail::ArrayHandleCompositeVectorFloat32_3Default::StorageTag,
|
||||
detail::ArrayHandleCompositeVectorFloat64_3Default::StorageTag >{ };
|
||||
*/
|
||||
//Super restrictive
|
||||
|
||||
struct ExplicitCoordinatesType
|
||||
: vtkm::ListTagBase<vtkm::Vec<vtkm::Float32, 3>, vtkm::Vec<vtkm::Float64, 3>>
|
||||
{
|
||||
};
|
||||
struct StorageListTagExplicitCoordinateSystem : vtkm::ListTagBase<vtkm::cont::StorageTagBasic>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
typedef detail::StructuredStorageListTagCoordinateSystem StructuredStorage;
|
||||
|
||||
typedef vtkm::cont::DynamicArrayHandleBase<ExplicitCoordinatesType, StructuredStorage>
|
||||
DynamicArrayHandleStructuredCoordinateSystem;
|
||||
|
||||
typedef vtkm::cont::DynamicArrayHandleBase<ExplicitCoordinatesType,
|
||||
StorageListTagExplicitCoordinateSystem>
|
||||
DynamicArrayHandleExplicitCoordinateSystem;
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,12 +26,16 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/CoordinateSystem.h>
|
||||
#include <vtkm/cont/ErrorBadValue.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/rendering/ColorTable.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/Ray.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
@ -299,8 +303,9 @@ public:
|
||||
|
||||
}; // class UniformLocator
|
||||
|
||||
|
||||
} //namespace
|
||||
template <typename Device>
|
||||
|
||||
class VolumeRendererStructured
|
||||
{
|
||||
public:
|
||||
@ -308,13 +313,12 @@ public:
|
||||
typedef vtkm::cont::ArrayHandleCartesianProduct<DefaultHandle, DefaultHandle, DefaultHandle>
|
||||
CartesianArrayHandle;
|
||||
|
||||
template <typename LocatorType>
|
||||
template <typename Device, typename LocatorType>
|
||||
class Sampler : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorArrayHandle;
|
||||
typedef typename ColorArrayHandle::ExecutionTypes<Device>::PortalConst ColorArrayPortal;
|
||||
vtkm::Vec<vtkm::Float32, 3> CameraPosition;
|
||||
ColorArrayPortal ColorMap;
|
||||
vtkm::Id ColorMapSize;
|
||||
vtkm::Float32 MinScalar;
|
||||
@ -324,14 +328,12 @@ public:
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Sampler(vtkm::Vec<vtkm::Float32, 3> cameraPosition,
|
||||
const ColorArrayHandle& colorMap,
|
||||
Sampler(const ColorArrayHandle& colorMap,
|
||||
const vtkm::Float32& minScalar,
|
||||
const vtkm::Float32& maxScalar,
|
||||
const vtkm::Float32& sampleDistance,
|
||||
const LocatorType& locator)
|
||||
: CameraPosition(cameraPosition)
|
||||
, ColorMap(colorMap.PrepareForInput(Device()))
|
||||
: ColorMap(colorMap.PrepareForInput(Device()))
|
||||
, MinScalar(minScalar)
|
||||
, SampleDistance(sampleDistance)
|
||||
, Locator(locator)
|
||||
@ -344,25 +346,34 @@ public:
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldIn<>,
|
||||
WholeArrayInOut<>,
|
||||
WholeArrayIn<ScalarRenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, WorkIndex);
|
||||
|
||||
template <typename ScalarPortalType>
|
||||
template <typename ScalarPortalType, typename ColorBufferType>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Float32, 3>& rayDir,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& rayOrigin,
|
||||
const vtkm::Float32& minDistance,
|
||||
vtkm::Vec<vtkm::Float32, 4>& color,
|
||||
ScalarPortalType& scalars) const
|
||||
ColorBufferType& colorBuffer,
|
||||
ScalarPortalType& scalars,
|
||||
const vtkm::Id& pixelIndex) const
|
||||
{
|
||||
color[0] = 0.f;
|
||||
color[1] = 0.f;
|
||||
color[2] = 0.f;
|
||||
color[3] = 0.f;
|
||||
vtkm::Vec<vtkm::Float32, 4> color;
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
color[0] = colorBuffer.Get(pixelIndex * 4 + 0);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
color[1] = colorBuffer.Get(pixelIndex * 4 + 1);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
color[2] = colorBuffer.Get(pixelIndex * 4 + 2);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
color[3] = colorBuffer.Get(pixelIndex * 4 + 3);
|
||||
|
||||
if (minDistance == -1.f)
|
||||
return; //TODO: Compact? or just image subset...
|
||||
//get the initial sample position;
|
||||
vtkm::Vec<vtkm::Float32, 3> sampleLocation;
|
||||
sampleLocation = CameraPosition + (0.0001f + minDistance) * rayDir;
|
||||
sampleLocation = rayOrigin + (0.0001f + minDistance) * rayDir;
|
||||
/*
|
||||
7----------6
|
||||
/| /|
|
||||
@ -388,7 +399,8 @@ public:
|
||||
vtkm::Float32 scalar7 = 0.f;
|
||||
|
||||
vtkm::Vec<vtkm::Id, 3> cell(0, 0, 0);
|
||||
vtkm::Vec<vtkm::Float32, 3> invSpacing;
|
||||
vtkm::Vec<vtkm::Float32, 3> invSpacing(0.f, 0.f, 0.f);
|
||||
|
||||
|
||||
while (Locator.IsInside(sampleLocation))
|
||||
{
|
||||
@ -465,20 +477,29 @@ public:
|
||||
if (color[3] >= 1.f)
|
||||
break;
|
||||
}
|
||||
|
||||
color[0] = vtkm::Min(color[0], 1.f);
|
||||
color[1] = vtkm::Min(color[1], 1.f);
|
||||
color[2] = vtkm::Min(color[2], 1.f);
|
||||
color[3] = vtkm::Min(color[3], 1.f);
|
||||
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
colorBuffer.Set(pixelIndex * 4 + 0, color[0]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
colorBuffer.Set(pixelIndex * 4 + 1, color[1]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
colorBuffer.Set(pixelIndex * 4 + 2, color[2]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
colorBuffer.Set(pixelIndex * 4 + 3, color[3]);
|
||||
}
|
||||
}; //Sampler
|
||||
|
||||
template <typename LocatorType>
|
||||
template <typename Device, typename LocatorType>
|
||||
class SamplerCellAssoc : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
typedef typename vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>> ColorArrayHandle;
|
||||
typedef typename ColorArrayHandle::ExecutionTypes<Device>::PortalConst ColorArrayPortal;
|
||||
vtkm::Vec<vtkm::Float32, 3> CameraPosition;
|
||||
ColorArrayPortal ColorMap;
|
||||
vtkm::Id ColorMapSize;
|
||||
vtkm::Float32 MinScalar;
|
||||
@ -488,14 +509,12 @@ public:
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
SamplerCellAssoc(vtkm::Vec<vtkm::Float32, 3> cameraPosition,
|
||||
const ColorArrayHandle& colorMap,
|
||||
SamplerCellAssoc(const ColorArrayHandle& colorMap,
|
||||
const vtkm::Float32& minScalar,
|
||||
const vtkm::Float32& maxScalar,
|
||||
const vtkm::Float32& sampleDistance,
|
||||
const LocatorType& locator)
|
||||
: CameraPosition(cameraPosition)
|
||||
, ColorMap(colorMap.PrepareForInput(Device()))
|
||||
: ColorMap(colorMap.PrepareForInput(Device()))
|
||||
, MinScalar(minScalar)
|
||||
, SampleDistance(sampleDistance)
|
||||
, Locator(locator)
|
||||
@ -508,25 +527,34 @@ public:
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>,
|
||||
FieldIn<>,
|
||||
FieldOut<>,
|
||||
FieldIn<>,
|
||||
WholeArrayInOut<>,
|
||||
WholeArrayIn<ScalarRenderingTypes>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, WorkIndex);
|
||||
|
||||
template <typename ScalarPortalType>
|
||||
template <typename ScalarPortalType, typename ColorBufferType>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::Float32, 3>& rayDir,
|
||||
const vtkm::Vec<vtkm::Float32, 3>& rayOrigin,
|
||||
const vtkm::Float32& minDistance,
|
||||
vtkm::Vec<vtkm::Float32, 4>& color,
|
||||
const ScalarPortalType& scalars) const
|
||||
ColorBufferType& colorBuffer,
|
||||
const ScalarPortalType& scalars,
|
||||
const vtkm::Id& pixelIndex) const
|
||||
{
|
||||
color[0] = 0.f;
|
||||
color[1] = 0.f;
|
||||
color[2] = 0.f;
|
||||
color[3] = 0.f;
|
||||
vtkm::Vec<vtkm::Float32, 4> color;
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
color[0] = colorBuffer.Get(pixelIndex * 4 + 0);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
color[1] = colorBuffer.Get(pixelIndex * 4 + 1);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
color[2] = colorBuffer.Get(pixelIndex * 4 + 2);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
color[3] = colorBuffer.Get(pixelIndex * 4 + 3);
|
||||
|
||||
if (minDistance == -1.f)
|
||||
return; //TODO: Compact? or just image subset...
|
||||
//get the initial sample position;
|
||||
vtkm::Vec<vtkm::Float32, 3> sampleLocation;
|
||||
sampleLocation = CameraPosition + (0.0001f + minDistance) * rayDir;
|
||||
sampleLocation = rayOrigin + (0.0001f + minDistance) * rayDir;
|
||||
|
||||
/*
|
||||
7----------6
|
||||
@ -542,9 +570,9 @@ public:
|
||||
vtkm::Float32 ty = 2.f;
|
||||
vtkm::Float32 tz = 2.f;
|
||||
vtkm::Float32 scalar0 = 0.f;
|
||||
vtkm::Vec<vtkm::Float32, 4> sampleColor(0, 0, 0, 0);
|
||||
vtkm::Vec<vtkm::Float32, 3> bottomLeft(0, 0, 0);
|
||||
vtkm::Vec<vtkm::Float32, 3> invSpacing;
|
||||
vtkm::Vec<vtkm::Float32, 4> sampleColor(0.f, 0.f, 0.f, 0.f);
|
||||
vtkm::Vec<vtkm::Float32, 3> bottomLeft(0.f, 0.f, 0.f);
|
||||
vtkm::Vec<vtkm::Float32, 3> invSpacing(0.f, 0.f, 0.f);
|
||||
vtkm::Vec<vtkm::Id, 3> cell(0, 0, 0);
|
||||
while (Locator.IsInside(sampleLocation))
|
||||
{
|
||||
@ -588,11 +616,19 @@ public:
|
||||
ty = (sampleLocation[1] - bottomLeft[1]) * invSpacing[1];
|
||||
tz = (sampleLocation[2] - bottomLeft[2]) * invSpacing[2];
|
||||
}
|
||||
|
||||
color[0] = vtkm::Min(color[0], 1.f);
|
||||
color[1] = vtkm::Min(color[1], 1.f);
|
||||
color[2] = vtkm::Min(color[2], 1.f);
|
||||
color[3] = vtkm::Min(color[3], 1.f);
|
||||
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
colorBuffer.Set(pixelIndex * 4 + 0, color[0]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
colorBuffer.Set(pixelIndex * 4 + 1, color[1]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
colorBuffer.Set(pixelIndex * 4 + 2, color[2]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
colorBuffer.Set(pixelIndex * 4 + 3, color[3]);
|
||||
}
|
||||
}; //SamplerCell
|
||||
|
||||
@ -604,12 +640,10 @@ public:
|
||||
vtkm::Float32 Xmax;
|
||||
vtkm::Float32 Ymax;
|
||||
vtkm::Float32 Zmax;
|
||||
vtkm::Vec<vtkm::Float32, 3> CameraPosition;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CalcRayStart(vtkm::Vec<vtkm::Float32, 3> cameraPosition, const vtkm::Bounds boundingBox)
|
||||
: CameraPosition(cameraPosition)
|
||||
CalcRayStart(const vtkm::Bounds boundingBox)
|
||||
{
|
||||
Xmin = static_cast<vtkm::Float32>(boundingBox.X.Min);
|
||||
Xmax = static_cast<vtkm::Float32>(boundingBox.X.Max);
|
||||
@ -625,24 +659,28 @@ public:
|
||||
VTKM_EXEC
|
||||
vtkm::Float32 rcp_safe(vtkm::Float32 f) const { return rcp((fabs(f) < 1e-8f) ? 1e-8f : f); }
|
||||
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Vec<vtkm::Float32, 3>& rayDir,
|
||||
vtkm::Float32& minDistance,
|
||||
vtkm::Float32& maxDistance) const
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>, FieldOut<>, FieldIn<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4);
|
||||
template <typename Precision>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<Precision, 3>& rayDir,
|
||||
vtkm::Float32& minDistance,
|
||||
vtkm::Float32& maxDistance,
|
||||
const vtkm::Vec<Precision, 3>& rayOrigin) const
|
||||
{
|
||||
vtkm::Float32 dirx = rayDir[0];
|
||||
vtkm::Float32 diry = rayDir[1];
|
||||
vtkm::Float32 dirz = rayDir[2];
|
||||
vtkm::Float32 dirx = static_cast<vtkm::Float32>(rayDir[0]);
|
||||
vtkm::Float32 diry = static_cast<vtkm::Float32>(rayDir[1]);
|
||||
vtkm::Float32 dirz = static_cast<vtkm::Float32>(rayDir[2]);
|
||||
vtkm::Float32 origx = static_cast<vtkm::Float32>(rayOrigin[0]);
|
||||
vtkm::Float32 origy = static_cast<vtkm::Float32>(rayOrigin[1]);
|
||||
vtkm::Float32 origz = static_cast<vtkm::Float32>(rayOrigin[2]);
|
||||
|
||||
vtkm::Float32 invDirx = rcp_safe(dirx);
|
||||
vtkm::Float32 invDiry = rcp_safe(diry);
|
||||
vtkm::Float32 invDirz = rcp_safe(dirz);
|
||||
|
||||
vtkm::Float32 odirx = CameraPosition[0] * invDirx;
|
||||
vtkm::Float32 odiry = CameraPosition[1] * invDiry;
|
||||
vtkm::Float32 odirz = CameraPosition[2] * invDirz;
|
||||
vtkm::Float32 odirx = origx * invDirx;
|
||||
vtkm::Float32 odiry = origy * invDiry;
|
||||
vtkm::Float32 odirz = origz * invDirz;
|
||||
|
||||
vtkm::Float32 xmin = Xmin * invDirx - odirx;
|
||||
vtkm::Float32 ymin = Ymin * invDiry - odiry;
|
||||
@ -651,6 +689,7 @@ public:
|
||||
vtkm::Float32 ymax = Ymax * invDiry - odiry;
|
||||
vtkm::Float32 zmax = Zmax * invDirz - odirz;
|
||||
|
||||
|
||||
minDistance = vtkm::Max(
|
||||
vtkm::Max(vtkm::Max(vtkm::Min(ymin, ymax), vtkm::Min(xmin, xmax)), vtkm::Min(zmin, zmax)),
|
||||
0.f);
|
||||
@ -674,19 +713,40 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldInOut<>);
|
||||
typedef void ExecutionSignature(_1);
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Vec<vtkm::Float32, 4>& color) const
|
||||
typedef void ControlSignature(FieldIn<>, WholeArrayInOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
|
||||
template <typename ColorBufferType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pixelIndex, ColorBufferType& colorBuffer) const
|
||||
{
|
||||
|
||||
vtkm::Vec<vtkm::Float32, 4> color;
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
color[0] = colorBuffer.Get(pixelIndex * 4 + 0);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
color[1] = colorBuffer.Get(pixelIndex * 4 + 1);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
color[2] = colorBuffer.Get(pixelIndex * 4 + 2);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
color[3] = colorBuffer.Get(pixelIndex * 4 + 3);
|
||||
|
||||
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];
|
||||
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 0);
|
||||
colorBuffer.Set(pixelIndex * 4 + 0, color[0]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 1);
|
||||
colorBuffer.Set(pixelIndex * 4 + 1, color[1]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 2);
|
||||
colorBuffer.Set(pixelIndex * 4 + 2, color[2]);
|
||||
BOUNDS_CHECK(colorBuffer, pixelIndex * 4 + 3);
|
||||
colorBuffer.Set(pixelIndex * 4 + 3, color[3]);
|
||||
}
|
||||
}; //class CompositeBackground
|
||||
|
||||
@ -694,13 +754,17 @@ public:
|
||||
VolumeRendererStructured()
|
||||
{
|
||||
IsSceneDirty = false;
|
||||
DoCompositeBackground = true;
|
||||
IsUniformDataSet = true;
|
||||
SampleDistance = -1.f;
|
||||
DoCompositeBackground = false;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
Camera<Device>& GetCamera() { return camera; }
|
||||
void SetCompositeBackground(bool compositeBackground)
|
||||
{
|
||||
DoCompositeBackground = compositeBackground;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void SetColorMap(const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 4>>& colorMap)
|
||||
@ -708,50 +772,82 @@ public:
|
||||
ColorMap = colorMap;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Init()
|
||||
{
|
||||
camera.CreateRays(Rays, DataBounds);
|
||||
IsSceneDirty = true;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void SetData(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::Bounds& coordsBounds,
|
||||
const vtkm::cont::CellSetStructured<3>& cellset,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
if (coords.GetData().IsSameType(CartesianArrayHandle()))
|
||||
IsUniformDataSet = false;
|
||||
IsSceneDirty = true;
|
||||
SpatialExtent = coords.GetBounds();
|
||||
Coordinates = coords.GetData();
|
||||
ScalarField = &scalarField;
|
||||
DataBounds = coordsBounds;
|
||||
Cellset = cellset;
|
||||
ScalarRange = scalarRange;
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
void Render(CanvasRayTracer* canvas)
|
||||
template <typename Precision>
|
||||
struct RenderFunctor
|
||||
{
|
||||
if (IsSceneDirty)
|
||||
protected:
|
||||
vtkm::rendering::raytracing::VolumeRendererStructured* Self;
|
||||
vtkm::rendering::raytracing::Ray<Precision>& Rays;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
RenderFunctor(vtkm::rendering::raytracing::VolumeRendererStructured* self,
|
||||
vtkm::rendering::raytracing::Ray<Precision>& rays)
|
||||
: Self(self)
|
||||
, Rays(rays)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT bool operator()(Device)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
|
||||
this->Self->RenderOnDevice(this->Rays, Device());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_CONT void Render(vtkm::rendering::raytracing::Ray<Precision>& rays)
|
||||
{
|
||||
RenderFunctor<Precision> functor(this, rays);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
template <typename Precision, typename Device>
|
||||
VTKM_CONT void RenderOnDevice(vtkm::rendering::raytracing::Ray<Precision>& rays, Device)
|
||||
{
|
||||
vtkm::cont::Timer<Device> renderTimer;
|
||||
Logger* logger = Logger::GetInstance();
|
||||
logger->OpenLogEntry("volume_render_structured");
|
||||
logger->AddLogData("device", GetDeviceString(Device()));
|
||||
|
||||
if (SampleDistance <= 0.f)
|
||||
{
|
||||
vtkm::Vec<vtkm::Float32, 3> extent;
|
||||
extent[0] = static_cast<vtkm::Float32>(this->DataBounds.X.Length());
|
||||
extent[1] = static_cast<vtkm::Float32>(this->DataBounds.Y.Length());
|
||||
extent[2] = static_cast<vtkm::Float32>(this->DataBounds.Z.Length());
|
||||
extent[0] = static_cast<vtkm::Float32>(this->SpatialExtent.X.Length());
|
||||
extent[1] = static_cast<vtkm::Float32>(this->SpatialExtent.Y.Length());
|
||||
extent[2] = static_cast<vtkm::Float32>(this->SpatialExtent.Z.Length());
|
||||
const vtkm::Float32 defaultNumberOfSamples = 200.f;
|
||||
SampleDistance = vtkm::Magnitude(extent) / defaultNumberOfSamples;
|
||||
}
|
||||
|
||||
vtkm::worklet::DispatcherMapField<CalcRayStart, Device>(
|
||||
CalcRayStart(camera.GetPosition(), this->DataBounds))
|
||||
.Invoke(Rays.Dir, Rays.MinDistance, Rays.MaxDistance);
|
||||
vtkm::cont::Timer<Device> timer;
|
||||
vtkm::worklet::DispatcherMapField<CalcRayStart, Device>(CalcRayStart(this->SpatialExtent))
|
||||
.Invoke(rays.Dir, rays.MinDistance, rays.MaxDistance, rays.Origin);
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("calc_ray_start", time);
|
||||
timer.Reset();
|
||||
|
||||
bool isSupportedField = (ScalarField->GetAssociation() == vtkm::cont::Field::ASSOC_POINTS ||
|
||||
ScalarField->GetAssociation() == vtkm::cont::Field::ASSOC_CELL_SET);
|
||||
if (!isSupportedField)
|
||||
@ -760,32 +856,29 @@ public:
|
||||
|
||||
if (IsUniformDataSet)
|
||||
{
|
||||
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates vertices;
|
||||
vertices = Coordinates.Cast<vtkm::cont::ArrayHandleUniformPointCoordinates>();
|
||||
UniformLocator<Device> locator(vertices, Cellset);
|
||||
|
||||
if (isAssocPoints)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<Sampler<UniformLocator<Device>>, Device>(
|
||||
Sampler<UniformLocator<Device>>(camera.GetPosition(),
|
||||
ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(Rays.Dir, Rays.MinDistance, camera.FrameBuffer, *ScalarField);
|
||||
vtkm::worklet::DispatcherMapField<Sampler<Device, UniformLocator<Device>>, Device>(
|
||||
Sampler<Device, UniformLocator<Device>>(ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(rays.Dir, rays.Origin, rays.MinDistance, rays.Buffers.at(0).Buffer, *ScalarField);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<SamplerCellAssoc<UniformLocator<Device>>>(
|
||||
SamplerCellAssoc<UniformLocator<Device>>(camera.GetPosition(),
|
||||
ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(Rays.Dir, Rays.MinDistance, camera.FrameBuffer, *ScalarField);
|
||||
vtkm::worklet::DispatcherMapField<SamplerCellAssoc<Device, UniformLocator<Device>>>(
|
||||
SamplerCellAssoc<Device, UniformLocator<Device>>(ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(rays.Dir, rays.Origin, rays.MinDistance, rays.Buffers.at(0).Buffer, *ScalarField);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -795,34 +888,44 @@ public:
|
||||
RectilinearLocator<Device> locator(vertices, Cellset);
|
||||
if (isAssocPoints)
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<Sampler<RectilinearLocator<Device>>, Device>(
|
||||
Sampler<RectilinearLocator<Device>>(camera.GetPosition(),
|
||||
ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(Rays.Dir, Rays.MinDistance, camera.FrameBuffer, *ScalarField);
|
||||
vtkm::worklet::DispatcherMapField<Sampler<Device, RectilinearLocator<Device>>, Device>(
|
||||
Sampler<Device, RectilinearLocator<Device>>(ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(rays.Dir, rays.Origin, rays.MinDistance, rays.Buffers.at(0).Buffer, *ScalarField);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::worklet::DispatcherMapField<SamplerCellAssoc<RectilinearLocator<Device>>, Device>(
|
||||
SamplerCellAssoc<RectilinearLocator<Device>>(camera.GetPosition(),
|
||||
ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(Rays.Dir, Rays.MinDistance, camera.FrameBuffer, *ScalarField);
|
||||
vtkm::worklet::DispatcherMapField<SamplerCellAssoc<Device, RectilinearLocator<Device>>,
|
||||
Device>(
|
||||
SamplerCellAssoc<Device, RectilinearLocator<Device>>(ColorMap,
|
||||
vtkm::Float32(ScalarRange.Min),
|
||||
vtkm::Float32(ScalarRange.Max),
|
||||
SampleDistance,
|
||||
locator))
|
||||
.Invoke(rays.Dir, rays.Origin, rays.MinDistance, rays.Buffers.at(0).Buffer, *ScalarField);
|
||||
}
|
||||
}
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("sample", time);
|
||||
timer.Reset();
|
||||
|
||||
if (DoCompositeBackground)
|
||||
{
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> rayIterator(0, 1, rays.NumRays);
|
||||
vtkm::worklet::DispatcherMapField<CompositeBackground>(CompositeBackground(BackgroundColor))
|
||||
.Invoke(camera.FrameBuffer);
|
||||
.Invoke(rayIterator, rays.Buffers.at(0).Buffer);
|
||||
|
||||
time = timer.GetElapsedTime();
|
||||
logger->AddLogData("compsosite_background", time);
|
||||
timer.Reset();
|
||||
}
|
||||
camera.WriteToSurface(canvas, Rays.MinDistance);
|
||||
|
||||
time = renderTimer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
} //Render
|
||||
|
||||
VTKM_CONT
|
||||
@ -839,17 +942,11 @@ public:
|
||||
BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
void SetCompositeBackground(bool compositeBackground)
|
||||
{
|
||||
DoCompositeBackground = compositeBackground;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool IsSceneDirty;
|
||||
bool IsUniformDataSet;
|
||||
bool DoCompositeBackground;
|
||||
VolumeRay<Device> Rays;
|
||||
Camera<Device> camera;
|
||||
bool IsUniformDataSet;
|
||||
vtkm::Bounds SpatialExtent;
|
||||
vtkm::cont::DynamicArrayHandleCoordinateSystem Coordinates;
|
||||
vtkm::cont::CellSetStructured<3> Cellset;
|
||||
const vtkm::cont::Field* ScalarField;
|
||||
@ -857,7 +954,6 @@ protected:
|
||||
vtkm::Float32 SampleDistance;
|
||||
vtkm::Vec<vtkm::Float32, 4> BackgroundColor;
|
||||
vtkm::Range ScalarRange;
|
||||
vtkm::Bounds DataBounds;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,106 @@ public:
|
||||
void operator()(T& outValue) const { outValue = Value; }
|
||||
}; //class MemSet
|
||||
|
||||
template <typename FloatType>
|
||||
class CopyAndOffset : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
FloatType Offset;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CopyAndOffset(const FloatType offset = 0.00001)
|
||||
: Offset(offset)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
|
||||
VTKM_EXEC inline void operator()(const FloatType& inValue, FloatType& outValue) const
|
||||
{
|
||||
outValue = inValue + Offset;
|
||||
}
|
||||
}; //class Copy and iffset
|
||||
|
||||
template <typename FloatType>
|
||||
class CopyAndOffsetMask : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
FloatType Offset;
|
||||
vtkm::UInt8 MaskValue;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CopyAndOffsetMask(const FloatType offset = 0.00001, const vtkm::UInt8 mask = 1)
|
||||
: Offset(offset)
|
||||
, MaskValue(mask)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldInOut<>, FieldIn<>);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
|
||||
template <typename MaskType>
|
||||
VTKM_EXEC inline void operator()(const FloatType& inValue,
|
||||
FloatType& outValue,
|
||||
const MaskType& mask) const
|
||||
{
|
||||
if (mask == MaskValue)
|
||||
outValue = inValue + Offset;
|
||||
}
|
||||
}; //class Copy and iffset
|
||||
|
||||
template <class T>
|
||||
class Mask : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
T Value;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Mask(T value)
|
||||
: Value(value)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
|
||||
template <typename O>
|
||||
VTKM_EXEC void operator()(const T& inValue, O& outValue) const
|
||||
{
|
||||
if (inValue == Value)
|
||||
outValue = static_cast<O>(1);
|
||||
else
|
||||
outValue = static_cast<O>(0);
|
||||
}
|
||||
}; //class mask
|
||||
|
||||
template <class T, int N>
|
||||
class ManyMask : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::Vec<T, N> Values;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
ManyMask(vtkm::Vec<T, N> values)
|
||||
: Values(values)
|
||||
{
|
||||
}
|
||||
typedef void ControlSignature(FieldIn<>, FieldOut<>);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
|
||||
template <typename O>
|
||||
VTKM_EXEC void operator()(const T& inValue, O& outValue) const
|
||||
{
|
||||
bool doMask = false;
|
||||
for (vtkm::Int32 i = 0; i < N; ++i)
|
||||
{
|
||||
if (inValue == Values[i])
|
||||
doMask = true;
|
||||
}
|
||||
if (doMask)
|
||||
outValue = static_cast<O>(1);
|
||||
else
|
||||
outValue = static_cast<O>(0);
|
||||
}
|
||||
}; //class doube mask
|
||||
|
||||
struct MaxValue
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -25,6 +25,7 @@ set(headers
|
||||
vtkm_declare_headers(${headers})
|
||||
|
||||
set(unit_tests
|
||||
UnitTestMapperConnectivity.cxx
|
||||
UnitTestMapperRayTracer.cxx
|
||||
UnitTestMapperVolume.cxx
|
||||
)
|
||||
|
57
vtkm/rendering/testing/UnitTestMapperConnectivity.cxx
Normal file
57
vtkm/rendering/testing/UnitTestMapperConnectivity.cxx
Normal file
@ -0,0 +1,57 @@
|
||||
//============================================================================
|
||||
// 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 Sandia Corporation.
|
||||
// Copyright 2015 UT-Battelle, LLC.
|
||||
// Copyright 2015 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/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/rendering/Actor.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/MapperConnectivity.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/View3D.h>
|
||||
#include <vtkm/rendering/testing/RenderTest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void RenderTests()
|
||||
{
|
||||
typedef vtkm::rendering::MapperConnectivity M;
|
||||
typedef vtkm::rendering::CanvasRayTracer C;
|
||||
typedef vtkm::rendering::View3D V3;
|
||||
|
||||
vtkm::cont::testing::MakeTestDataSet maker;
|
||||
vtkm::rendering::ColorTable colorTable("thermal");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
||||
int UnitTestMapperConnectivity(int, char* [])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(RenderTests);
|
||||
}
|
Loading…
Reference in New Issue
Block a user