mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Add MapperGlyphScalar and MapperGlyphVector mappers
These mappers can be used to render cell sets as glyphs. The following glyph types are available for scalar fields: - Cube - Sphere - Axes - Quads For vector fields: - Arrows
This commit is contained in:
parent
12acf31097
commit
814ec27f1e
3
data/baseline/rendering/glyph_scalar/cells.png
Normal file
3
data/baseline/rendering/glyph_scalar/cells.png
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b70d68db818220a5c30d34b4dd14db000d6a2d7f4e117c5509f03e236186825b
|
||||
size 20123
|
3
data/baseline/rendering/glyph_scalar/regular3D.png
Normal file
3
data/baseline/rendering/glyph_scalar/regular3D.png
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8012ca572ca38b64fda0f617a9471a48d268e35c12a1352ce3725e8e27577a58
|
||||
size 16910
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3ad37f93e562178c5491e06256083630ad6b5d500f9b19683a72ad91c0b4ab05
|
||||
size 95406
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e500611307400dd0d618a37d4160722d471a971db4f4accb698c207259c38bb7
|
||||
size 25221
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:91506c6a411f536fcf549ecdb74520d072b184d4b6e168c19f11b864db0f6bb4
|
||||
size 37260
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bb998a6d7ae70371a82e1de0778fcc0259996d0bb13bbf55bc14a9efd0f663e4
|
||||
size 131853
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6658a13bb64a4921bda3ed49d2de7021cf2e31257e5b9e5bbbbfd2ad3c85c044
|
||||
size 21634
|
@ -83,8 +83,6 @@ Actor::Actor(const vtkm::cont::UnknownCellSet& cells,
|
||||
void Actor::Init(const vtkm::cont::CoordinateSystem& coordinates,
|
||||
const vtkm::cont::Field& scalarField)
|
||||
{
|
||||
VTKM_ASSERT(scalarField.GetData().GetNumberOfComponentsFlat() == 1);
|
||||
|
||||
scalarField.GetRange(&this->Internals->ScalarRange);
|
||||
this->Internals->SpatialBounds = coordinates.GetBounds();
|
||||
}
|
||||
|
@ -35,12 +35,16 @@ set(headers
|
||||
Cylinderizer.h
|
||||
DecodePNG.h # deprecated
|
||||
EncodePNG.h # deprecated
|
||||
GlyphType.h
|
||||
LineRenderer.h
|
||||
LineRendererBatcher.h
|
||||
MatrixHelpers.h
|
||||
Scene.h
|
||||
Mapper.h
|
||||
MapperCylinder.h
|
||||
MapperGlyphBase.h
|
||||
MapperGlyphScalar.h
|
||||
MapperGlyphVector.h
|
||||
MapperPoint.h
|
||||
MapperQuad.h
|
||||
MapperRayTracer.h
|
||||
@ -103,6 +107,9 @@ set(device_sources
|
||||
ConnectivityProxy.cxx
|
||||
LineRendererBatcher.cxx
|
||||
MapperCylinder.cxx
|
||||
MapperGlyphBase.cxx
|
||||
MapperGlyphScalar.cxx
|
||||
MapperGlyphVector.cxx
|
||||
MapperPoint.cxx
|
||||
MapperQuad.cxx
|
||||
MapperRayTracer.cxx
|
||||
@ -119,6 +126,10 @@ set(device_sources
|
||||
raytracing/ConnectivityTracer.cxx
|
||||
raytracing/CylinderExtractor.cxx
|
||||
raytracing/CylinderIntersector.cxx
|
||||
raytracing/GlyphExtractor.cxx
|
||||
raytracing/GlyphExtractorVector.cxx
|
||||
raytracing/GlyphIntersector.cxx
|
||||
raytracing/GlyphIntersectorVector.cxx
|
||||
raytracing/MeshConnectivityBuilder.cxx
|
||||
raytracing/QuadExtractor.cxx
|
||||
raytracing/QuadIntersector.cxx
|
||||
|
30
vtkm/rendering/GlyphType.h
Normal file
30
vtkm/rendering/GlyphType.h
Normal file
@ -0,0 +1,30 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_GlyphType_h
|
||||
#define vtk_m_rendering_GlyphType_h
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
enum struct GlyphType
|
||||
{
|
||||
Arrow,
|
||||
Axes,
|
||||
Cube,
|
||||
Quad,
|
||||
Sphere,
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
161
vtkm/rendering/MapperGlyphBase.cxx
Normal file
161
vtkm/rendering/MapperGlyphBase.cxx
Normal file
@ -0,0 +1,161 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/rendering/MapperGlyphBase.h>
|
||||
|
||||
#include <vtkm/filter/entity_extraction/MaskPoints.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
MapperGlyphBase::MapperGlyphBase()
|
||||
: Canvas(nullptr)
|
||||
, CompositeBackground(true)
|
||||
, UseNodes(true)
|
||||
, UseStride(false)
|
||||
, Stride(1)
|
||||
, ScaleByValue(false)
|
||||
, BaseSize(-1.f)
|
||||
, ScaleDelta(0.5f)
|
||||
{
|
||||
}
|
||||
|
||||
MapperGlyphBase::~MapperGlyphBase() {}
|
||||
|
||||
void MapperGlyphBase::SetCanvas(vtkm::rendering::Canvas* canvas)
|
||||
{
|
||||
vtkm::rendering::CanvasRayTracer* canvasRT =
|
||||
dynamic_cast<vtkm::rendering::CanvasRayTracer*>(canvas);
|
||||
if (canvasRT == nullptr)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphBase: bad canvas type. Must be CanvasRayTracer");
|
||||
}
|
||||
|
||||
this->Canvas = canvasRT;
|
||||
}
|
||||
|
||||
vtkm::rendering::Canvas* MapperGlyphBase::GetCanvas() const
|
||||
{
|
||||
return this->Canvas;
|
||||
}
|
||||
|
||||
bool MapperGlyphBase::GetUseCells() const
|
||||
{
|
||||
return !this->UseNodes;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetUseCells()
|
||||
{
|
||||
this->UseNodes = false;
|
||||
}
|
||||
|
||||
bool MapperGlyphBase::GetUseNodes() const
|
||||
{
|
||||
return this->UseNodes;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetUseNodes()
|
||||
{
|
||||
this->UseNodes = true;
|
||||
}
|
||||
|
||||
vtkm::Float32 MapperGlyphBase::GetBaseSize() const
|
||||
{
|
||||
return this->BaseSize;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetBaseSize(vtkm::Float32 size)
|
||||
{
|
||||
if (size <= 0.f)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphBase: base size must be positive");
|
||||
}
|
||||
this->BaseSize = size;
|
||||
}
|
||||
|
||||
bool MapperGlyphBase::GetScaleByValue() const
|
||||
{
|
||||
return this->ScaleByValue;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetScaleByValue(bool on)
|
||||
{
|
||||
this->ScaleByValue = on;
|
||||
}
|
||||
|
||||
vtkm::Float32 MapperGlyphBase::GetScaleDelta() const
|
||||
{
|
||||
return this->ScaleDelta;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetScaleDelta(vtkm::Float32 delta)
|
||||
{
|
||||
if (delta < 0.0f)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphBase: scale delta must be non-negative");
|
||||
}
|
||||
|
||||
this->ScaleDelta = delta;
|
||||
}
|
||||
|
||||
bool MapperGlyphBase::GetUseStride() const
|
||||
{
|
||||
return this->UseStride;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetUseStride(bool on)
|
||||
{
|
||||
this->UseStride = on;
|
||||
}
|
||||
|
||||
vtkm::Id MapperGlyphBase::GetStride() const
|
||||
{
|
||||
return this->Stride;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetStride(vtkm::Id stride)
|
||||
{
|
||||
if (stride < 1)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphBase: stride must be positive");
|
||||
}
|
||||
this->Stride = stride;
|
||||
}
|
||||
|
||||
void MapperGlyphBase::SetCompositeBackground(bool on)
|
||||
{
|
||||
this->CompositeBackground = on;
|
||||
}
|
||||
|
||||
vtkm::cont::DataSet MapperGlyphBase::FilterPoints(const vtkm::cont::UnknownCellSet& cellSet,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field) const
|
||||
{
|
||||
vtkm::cont::DataSet result;
|
||||
result.SetCellSet(cellSet);
|
||||
result.AddCoordinateSystem(coords);
|
||||
result.AddField(field);
|
||||
|
||||
if (this->UseStride)
|
||||
{
|
||||
vtkm::filter::entity_extraction::MaskPoints pointMasker;
|
||||
pointMasker.SetCompactPoints(true);
|
||||
pointMasker.SetStride(this->Stride);
|
||||
result = pointMasker.Execute(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::rendering
|
76
vtkm/rendering/MapperGlyphBase.h
Normal file
76
vtkm/rendering/MapperGlyphBase.h
Normal file
@ -0,0 +1,76 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_MapperGlyphBase_h
|
||||
#define vtk_m_rendering_MapperGlyphBase_h
|
||||
|
||||
#include <vtkm/cont/ColorTable.h>
|
||||
#include <vtkm/rendering/Camera.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
class CanvasRayTracer;
|
||||
|
||||
class VTKM_RENDERING_EXPORT MapperGlyphBase : public Mapper
|
||||
{
|
||||
public:
|
||||
MapperGlyphBase();
|
||||
|
||||
virtual ~MapperGlyphBase();
|
||||
|
||||
void SetCanvas(vtkm::rendering::Canvas* canvas) override;
|
||||
virtual vtkm::rendering::Canvas* GetCanvas() const override;
|
||||
|
||||
virtual bool GetUseCells() const;
|
||||
virtual void SetUseCells();
|
||||
virtual bool GetUseNodes() const;
|
||||
virtual void SetUseNodes();
|
||||
|
||||
virtual bool GetUseStride() const;
|
||||
virtual void SetUseStride(bool on);
|
||||
virtual vtkm::Id GetStride() const;
|
||||
virtual void SetStride(vtkm::Id stride);
|
||||
|
||||
virtual vtkm::Float32 GetBaseSize() const;
|
||||
virtual void SetBaseSize(vtkm::Float32 size);
|
||||
virtual bool GetScaleByValue() const;
|
||||
virtual void SetScaleByValue(bool on);
|
||||
virtual vtkm::Float32 GetScaleDelta() const;
|
||||
virtual void SetScaleDelta(vtkm::Float32 delta);
|
||||
|
||||
virtual void SetCompositeBackground(bool on);
|
||||
|
||||
protected:
|
||||
virtual vtkm::cont::DataSet FilterPoints(const vtkm::cont::UnknownCellSet& cellSet,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField) const;
|
||||
|
||||
|
||||
vtkm::rendering::CanvasRayTracer* Canvas;
|
||||
bool CompositeBackground;
|
||||
|
||||
bool UseNodes;
|
||||
|
||||
bool UseStride;
|
||||
vtkm::Id Stride;
|
||||
|
||||
bool ScaleByValue;
|
||||
vtkm::Float32 BaseSize;
|
||||
vtkm::Float32 ScaleDelta;
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
|
||||
#endif //vtk_m_rendering_MapperGlyphBase_h
|
494
vtkm/rendering/MapperGlyphScalar.cxx
Normal file
494
vtkm/rendering/MapperGlyphScalar.cxx
Normal file
@ -0,0 +1,494 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/rendering/MapperGlyphScalar.h>
|
||||
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphExtractor.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphIntersector.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/RayOperations.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracer.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace
|
||||
{
|
||||
// Packed frame buffer value with color set as black and depth as 1.0f
|
||||
constexpr vtkm::Int64 ClearValue = 0x3F800000000000FF;
|
||||
|
||||
union PackedValue {
|
||||
struct PackedFloats
|
||||
{
|
||||
vtkm::Float32 Color;
|
||||
vtkm::Float32 Depth;
|
||||
} Floats;
|
||||
struct PackedInts
|
||||
{
|
||||
vtkm::UInt32 Color;
|
||||
vtkm::UInt32 Depth;
|
||||
} Ints;
|
||||
vtkm::Int64 Raw;
|
||||
}; // union PackedValue
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::UInt32 ScaleColorComponent(vtkm::Float32 c)
|
||||
{
|
||||
vtkm::Int32 t = vtkm::Int32(c * 256.0f);
|
||||
return vtkm::UInt32(t < 0 ? 0 : (t > 255 ? 255 : t));
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::UInt32 PackColor(vtkm::Float32 r, vtkm::Float32 g, vtkm::Float32 b, vtkm::Float32 a);
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::UInt32 PackColor(const vtkm::Vec4f_32& color)
|
||||
{
|
||||
return PackColor(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::UInt32 PackColor(vtkm::Float32 r, vtkm::Float32 g, vtkm::Float32 b, vtkm::Float32 a)
|
||||
{
|
||||
vtkm::UInt32 packed = (ScaleColorComponent(r) << 24);
|
||||
packed |= (ScaleColorComponent(g) << 16);
|
||||
packed |= (ScaleColorComponent(b) << 8);
|
||||
packed |= ScaleColorComponent(a);
|
||||
return packed;
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
void UnpackColor(vtkm::UInt32 color,
|
||||
vtkm::Float32& r,
|
||||
vtkm::Float32& g,
|
||||
vtkm::Float32& b,
|
||||
vtkm::Float32& a);
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
void UnpackColor(vtkm::UInt32 packedColor, vtkm::Vec4f_32& color)
|
||||
{
|
||||
UnpackColor(packedColor, color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
void UnpackColor(vtkm::UInt32 color,
|
||||
vtkm::Float32& r,
|
||||
vtkm::Float32& g,
|
||||
vtkm::Float32& b,
|
||||
vtkm::Float32& a)
|
||||
{
|
||||
r = vtkm::Float32((color & 0xFF000000) >> 24) / 255.0f;
|
||||
g = vtkm::Float32((color & 0x00FF0000) >> 16) / 255.0f;
|
||||
b = vtkm::Float32((color & 0x0000FF00) >> 8) / 255.0f;
|
||||
a = vtkm::Float32((color & 0x000000FF)) / 255.0f;
|
||||
}
|
||||
|
||||
class PackIntoFrameBuffer : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(FieldIn, FieldIn, FieldOut);
|
||||
using ExecutionSignature = void(_1, _2, _3);
|
||||
|
||||
VTKM_CONT
|
||||
PackIntoFrameBuffer() {}
|
||||
|
||||
VTKM_EXEC
|
||||
void operator()(const vtkm::Vec4f_32& color,
|
||||
const vtkm::Float32& depth,
|
||||
vtkm::Int64& outValue) const
|
||||
{
|
||||
PackedValue packed;
|
||||
packed.Ints.Color = PackColor(color);
|
||||
packed.Floats.Depth = depth;
|
||||
outValue = packed.Raw;
|
||||
}
|
||||
}; //class PackIntoFrameBuffer
|
||||
|
||||
class UnpackFromFrameBuffer : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
UnpackFromFrameBuffer() {}
|
||||
|
||||
using ControlSignature = void(FieldIn, WholeArrayOut, WholeArrayOut);
|
||||
using ExecutionSignature = void(_1, _2, _3, WorkIndex);
|
||||
|
||||
template <typename ColorBufferPortal, typename DepthBufferPortal>
|
||||
VTKM_EXEC void operator()(const vtkm::Int64& packedValue,
|
||||
ColorBufferPortal& colorBuffer,
|
||||
DepthBufferPortal& depthBuffer,
|
||||
const vtkm::Id& index) const
|
||||
{
|
||||
PackedValue packed;
|
||||
packed.Raw = packedValue;
|
||||
float depth = packed.Floats.Depth;
|
||||
if (depth <= depthBuffer.Get(index))
|
||||
{
|
||||
vtkm::Vec4f_32 color;
|
||||
UnpackColor(packed.Ints.Color, color);
|
||||
colorBuffer.Set(index, color);
|
||||
depthBuffer.Set(index, depth);
|
||||
}
|
||||
}
|
||||
}; // class UnpackFromFrameBuffer
|
||||
|
||||
class GetNormalizedScalars : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(FieldIn pointIds, FieldOut normalizedScalars, WholeArrayIn field);
|
||||
using ExecutionSignature = void(_1, _2, _3);
|
||||
|
||||
VTKM_CONT GetNormalizedScalars(vtkm::Float32 minScalar, vtkm::Float32 maxScalar)
|
||||
: MinScalar(minScalar)
|
||||
{
|
||||
if (minScalar >= maxScalar)
|
||||
{
|
||||
this->InverseScalarDelta = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->InverseScalarDelta = 1.0f / (maxScalar - minScalar);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
vtkm::Float32& normalizedScalar,
|
||||
const FieldPortalType& field) const
|
||||
{
|
||||
normalizedScalar = static_cast<vtkm::Float32>(field.Get(pointId));
|
||||
normalizedScalar = (normalizedScalar - this->MinScalar) * this->InverseScalarDelta;
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::Float32 MinScalar;
|
||||
vtkm::Float32 InverseScalarDelta;
|
||||
}; // class GetNormalizedScalars
|
||||
|
||||
class BillboardGlyphPlotter : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(FieldIn pointIds,
|
||||
FieldIn sizes,
|
||||
FieldIn normalizedScalar,
|
||||
WholeArrayIn coords,
|
||||
WholeArrayIn colorMap,
|
||||
AtomicArrayInOut frameBuffer);
|
||||
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
|
||||
|
||||
VTKM_CONT
|
||||
BillboardGlyphPlotter(const vtkm::Matrix<vtkm::Float32, 4, 4>& worldToProjection,
|
||||
vtkm::Id width,
|
||||
vtkm::Id height,
|
||||
vtkm::Float32 projectionOffset)
|
||||
: WorldToProjection(worldToProjection)
|
||||
, Width(width)
|
||||
, Height(height)
|
||||
, ProjectionOffset(projectionOffset)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename CoordinatesPortal, typename ColorMapPortal, typename FrameBuffer>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
const vtkm::Float32& size,
|
||||
const vtkm::Float32& normalizedScalar,
|
||||
const CoordinatesPortal& coordsPortal,
|
||||
const ColorMapPortal& colorMap,
|
||||
FrameBuffer& frameBuffer) const
|
||||
{
|
||||
vtkm::Vec3f_32 point = static_cast<vtkm::Vec3f_32>(coordsPortal.Get(pointId));
|
||||
point = this->TransformWorldToViewport(point);
|
||||
vtkm::Vec4f_32 color = this->GetColor(normalizedScalar, colorMap);
|
||||
|
||||
vtkm::Float32 halfSize = size / 2.0f;
|
||||
vtkm::Id x1 = static_cast<vtkm::Id>(vtkm::Round(point[0] - halfSize));
|
||||
vtkm::Id x2 = static_cast<vtkm::Id>(vtkm::Round(point[0] + halfSize));
|
||||
vtkm::Id y1 = static_cast<vtkm::Id>(vtkm::Round(point[1] - halfSize));
|
||||
vtkm::Id y2 = static_cast<vtkm::Id>(vtkm::Round(point[1] + halfSize));
|
||||
vtkm::Float32 depth = point[2];
|
||||
|
||||
for (vtkm::Id x = x1; x <= x2; ++x)
|
||||
{
|
||||
for (vtkm::Id y = y1; y <= y2; ++y)
|
||||
{
|
||||
this->SetColor(x, y, depth, color, frameBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
VTKM_EXEC
|
||||
vtkm::Vec3f_32 TransformWorldToViewport(const vtkm::Vec3f_32& point) const
|
||||
{
|
||||
vtkm::Vec4f_32 temp(point[0], point[1], point[2], 1.0f);
|
||||
vtkm::Vec3f_32 result;
|
||||
temp = vtkm::MatrixMultiply(this->WorldToProjection, temp);
|
||||
for (vtkm::IdComponent i = 0; i < 3; ++i)
|
||||
{
|
||||
result[i] = temp[i] / temp[3];
|
||||
}
|
||||
result[0] = (result[0] * 0.5f + 0.5f) * vtkm::Float32(this->Width);
|
||||
result[1] = (result[1] * 0.5f + 0.5f) * vtkm::Float32(this->Height);
|
||||
result[2] = result[2] * 0.5f + 0.5f;
|
||||
// Offset the point to a bit towards the camera. This is to ensure that the front faces of
|
||||
// the wireframe wins the z-depth check against the surface render, and is in addition to the
|
||||
// existing camera space offset.
|
||||
result[2] -= this->ProjectionOffset;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename ColorMapPortal>
|
||||
VTKM_EXEC vtkm::Vec4f_32 GetColor(vtkm::Float32 normalizedScalar,
|
||||
const ColorMapPortal& colorMap) const
|
||||
{
|
||||
vtkm::Id colorMapSize = colorMap.GetNumberOfValues() - 1;
|
||||
vtkm::Id colorIdx = static_cast<vtkm::Id>(normalizedScalar * colorMapSize);
|
||||
colorIdx = vtkm::Min(colorMapSize, vtkm::Max(vtkm::Id(0), colorIdx));
|
||||
return colorMap.Get(colorIdx);
|
||||
}
|
||||
|
||||
template <typename FrameBuffer>
|
||||
VTKM_EXEC void SetColor(vtkm::Id x,
|
||||
vtkm::Id y,
|
||||
vtkm::Float32 depth,
|
||||
const vtkm::Vec4f_32& color,
|
||||
FrameBuffer& frameBuffer) const
|
||||
{
|
||||
if (x < 0 || x >= this->Width || y < 0 || y >= this->Height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::Id index = y * this->Width + x;
|
||||
PackedValue current, next;
|
||||
current.Raw = ClearValue;
|
||||
next.Floats.Depth = depth;
|
||||
|
||||
vtkm::Vec4f_32 currentColor;
|
||||
do
|
||||
{
|
||||
UnpackColor(current.Ints.Color, currentColor);
|
||||
next.Ints.Color = PackColor(color);
|
||||
frameBuffer.CompareExchange(index, ¤t.Raw, next.Raw);
|
||||
} while (current.Floats.Depth > next.Floats.Depth);
|
||||
}
|
||||
|
||||
const vtkm::Matrix<vtkm::Float32, 4, 4> WorldToProjection;
|
||||
const vtkm::Id Width;
|
||||
const vtkm::Id Height;
|
||||
const vtkm::Float32 ProjectionOffset;
|
||||
}; // class BillboardGlyphPlotter
|
||||
|
||||
}
|
||||
|
||||
MapperGlyphScalar::MapperGlyphScalar()
|
||||
: MapperGlyphBase()
|
||||
, GlyphType(vtkm::rendering::GlyphType::Sphere)
|
||||
{
|
||||
}
|
||||
|
||||
MapperGlyphScalar::~MapperGlyphScalar() {}
|
||||
|
||||
vtkm::rendering::GlyphType MapperGlyphScalar::GetGlyphType() const
|
||||
{
|
||||
return this->GlyphType;
|
||||
}
|
||||
|
||||
void MapperGlyphScalar::SetGlyphType(vtkm::rendering::GlyphType glyphType)
|
||||
{
|
||||
if (!(glyphType == vtkm::rendering::GlyphType::Axes ||
|
||||
glyphType == vtkm::rendering::GlyphType::Cube ||
|
||||
glyphType == vtkm::rendering::GlyphType::Quad ||
|
||||
glyphType == vtkm::rendering::GlyphType::Sphere))
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphScalar: bad glyph type");
|
||||
}
|
||||
|
||||
this->GlyphType = glyphType;
|
||||
}
|
||||
|
||||
void MapperGlyphScalar::RenderCells(const vtkm::cont::UnknownCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
|
||||
vtkm::rendering::raytracing::RayTracer tracer;
|
||||
tracer.Clear();
|
||||
|
||||
logger->OpenLogEntry("mapper_glyph_scalar");
|
||||
vtkm::cont::Timer tot_timer;
|
||||
tot_timer.Start();
|
||||
vtkm::cont::Timer timer;
|
||||
|
||||
vtkm::Bounds coordBounds = coords.GetBounds();
|
||||
vtkm::Float32 baseSize = this->BaseSize;
|
||||
if (baseSize == -1.f)
|
||||
{
|
||||
// set a default size
|
||||
vtkm::Float64 lx = coordBounds.X.Length();
|
||||
vtkm::Float64 ly = coordBounds.Y.Length();
|
||||
vtkm::Float64 lz = coordBounds.Z.Length();
|
||||
vtkm::Float64 mag = vtkm::Sqrt(lx * lx + ly * ly + lz * lz);
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Quad)
|
||||
{
|
||||
baseSize = 20.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// same as used in vtk ospray
|
||||
constexpr vtkm::Float64 heuristic = 500.;
|
||||
baseSize = static_cast<vtkm::Float32>(mag / heuristic);
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::rendering::raytracing::GlyphExtractor glyphExtractor;
|
||||
|
||||
vtkm::cont::DataSet processedDataSet = this->FilterPoints(cellset, coords, scalarField);
|
||||
vtkm::cont::UnknownCellSet processedCellSet = processedDataSet.GetCellSet();
|
||||
vtkm::cont::CoordinateSystem processedCoords = processedDataSet.GetCoordinateSystem();
|
||||
vtkm::cont::Field processedField = processedDataSet.GetField(0);
|
||||
|
||||
if (this->ScaleByValue)
|
||||
{
|
||||
vtkm::Float32 minSize = baseSize - baseSize * this->ScaleDelta;
|
||||
vtkm::Float32 maxSize = baseSize + baseSize * this->ScaleDelta;
|
||||
if (this->UseNodes)
|
||||
{
|
||||
glyphExtractor.ExtractCoordinates(processedCoords, processedField, minSize, maxSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyphExtractor.ExtractCells(processedCellSet, processedField, minSize, maxSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->UseNodes)
|
||||
{
|
||||
glyphExtractor.ExtractCoordinates(processedCoords, baseSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyphExtractor.ExtractCells(processedCellSet, baseSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Quad)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointIds = glyphExtractor.GetPointIds();
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> sizes = glyphExtractor.GetSizes();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> normalizedScalars;
|
||||
vtkm::Float32 rangeMin = static_cast<vtkm::Float32>(scalarRange.Min);
|
||||
vtkm::Float32 rangeMax = static_cast<vtkm::Float32>(scalarRange.Max);
|
||||
vtkm::cont::Invoker invoker;
|
||||
invoker(GetNormalizedScalars{ rangeMin, rangeMax },
|
||||
pointIds,
|
||||
normalizedScalars,
|
||||
vtkm::rendering::raytracing::GetScalarFieldArray(scalarField));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Int64> frameBuffer;
|
||||
invoker(PackIntoFrameBuffer{},
|
||||
this->Canvas->GetColorBuffer(),
|
||||
this->Canvas->GetDepthBuffer(),
|
||||
frameBuffer);
|
||||
|
||||
vtkm::Range clippingRange = camera.GetClippingRange();
|
||||
vtkm::Float64 offset1 = (clippingRange.Max - clippingRange.Min) / 1.0e4;
|
||||
vtkm::Float64 offset2 = clippingRange.Min / 2.0;
|
||||
vtkm::Float32 offset = static_cast<vtkm::Float32>(vtkm::Min(offset1, offset2));
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> modelMatrix;
|
||||
vtkm::MatrixIdentity(modelMatrix);
|
||||
modelMatrix[2][3] = offset;
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> worldToCamera =
|
||||
vtkm::MatrixMultiply(modelMatrix, camera.CreateViewMatrix());
|
||||
vtkm::Matrix<vtkm::Float32, 4, 4> worldToProjection = vtkm::MatrixMultiply(
|
||||
camera.CreateProjectionMatrix(this->Canvas->GetWidth(), this->Canvas->GetHeight()),
|
||||
worldToCamera);
|
||||
vtkm::Float32 projectionOffset =
|
||||
vtkm::Max(0.03f / static_cast<vtkm::Float32>(camera.GetClippingRange().Length()), 1e-4f);
|
||||
invoker(
|
||||
BillboardGlyphPlotter{
|
||||
worldToProjection, this->Canvas->GetWidth(), this->Canvas->GetHeight(), projectionOffset },
|
||||
pointIds,
|
||||
sizes,
|
||||
normalizedScalars,
|
||||
coords,
|
||||
this->ColorMap,
|
||||
frameBuffer);
|
||||
|
||||
timer.Start();
|
||||
invoker(UnpackFromFrameBuffer{},
|
||||
frameBuffer,
|
||||
this->Canvas->GetColorBuffer(),
|
||||
this->Canvas->GetDepthBuffer());
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::Bounds shapeBounds;
|
||||
if (glyphExtractor.GetNumberOfGlyphs() > 0)
|
||||
{
|
||||
auto glyphIntersector = std::make_shared<raytracing::GlyphIntersector>(this->GlyphType);
|
||||
glyphIntersector->SetData(
|
||||
processedCoords, glyphExtractor.GetPointIds(), glyphExtractor.GetSizes());
|
||||
tracer.AddShapeIntersector(glyphIntersector);
|
||||
shapeBounds.Include(glyphIntersector->GetShapeBounds());
|
||||
}
|
||||
|
||||
//
|
||||
// Create rays
|
||||
//
|
||||
vtkm::Int32 width = (vtkm::Int32)this->Canvas->GetWidth();
|
||||
vtkm::Int32 height = (vtkm::Int32)this->Canvas->GetHeight();
|
||||
|
||||
vtkm::rendering::raytracing::Camera RayCamera;
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
|
||||
|
||||
RayCamera.SetParameters(camera, width, height);
|
||||
|
||||
RayCamera.CreateRays(Rays, shapeBounds);
|
||||
Rays.Buffers.at(0).InitConst(0.f);
|
||||
raytracing::RayOperations::MapCanvasToRays(Rays, camera, *this->Canvas);
|
||||
|
||||
tracer.SetField(processedField, scalarRange);
|
||||
tracer.GetCamera() = RayCamera;
|
||||
tracer.SetColorMap(this->ColorMap);
|
||||
tracer.Render(Rays);
|
||||
|
||||
timer.Start();
|
||||
this->Canvas->WriteToCanvas(Rays, Rays.Buffers.at(0).Buffer, camera);
|
||||
}
|
||||
|
||||
if (this->CompositeBackground)
|
||||
{
|
||||
this->Canvas->BlendBackground();
|
||||
}
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("write_to_canvas", time);
|
||||
time = tot_timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
|
||||
vtkm::rendering::Mapper* MapperGlyphScalar::NewCopy() const
|
||||
{
|
||||
return new vtkm::rendering::MapperGlyphScalar(*this);
|
||||
}
|
||||
}
|
||||
} // vtkm::rendering
|
46
vtkm/rendering/MapperGlyphScalar.h
Normal file
46
vtkm/rendering/MapperGlyphScalar.h
Normal file
@ -0,0 +1,46 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_MapperGlyphScalar_h
|
||||
#define vtk_m_rendering_MapperGlyphScalar_h
|
||||
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/MapperGlyphBase.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
class VTKM_RENDERING_EXPORT MapperGlyphScalar : public vtkm::rendering::MapperGlyphBase
|
||||
{
|
||||
public:
|
||||
MapperGlyphScalar();
|
||||
|
||||
~MapperGlyphScalar();
|
||||
|
||||
vtkm::rendering::GlyphType GetGlyphType() const;
|
||||
void SetGlyphType(vtkm::rendering::GlyphType glyphType);
|
||||
|
||||
void RenderCells(const vtkm::cont::UnknownCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::cont::ColorTable& colorTable,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange) override;
|
||||
|
||||
vtkm::rendering::Mapper* NewCopy() const override;
|
||||
|
||||
protected:
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
|
||||
#endif //vtk_m_rendering_MapperGlyphScalar_h
|
174
vtkm/rendering/MapperGlyphVector.cxx
Normal file
174
vtkm/rendering/MapperGlyphVector.cxx
Normal file
@ -0,0 +1,174 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/rendering/MapperGlyphVector.h>
|
||||
|
||||
#include <vtkm/cont/Timer.h>
|
||||
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/raytracing/Camera.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphExtractorVector.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphIntersectorVector.h>
|
||||
#include <vtkm/rendering/raytracing/Logger.h>
|
||||
#include <vtkm/rendering/raytracing/RayOperations.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracer.h>
|
||||
#include <vtkm/rendering/raytracing/SphereExtractor.h>
|
||||
#include <vtkm/rendering/raytracing/SphereIntersector.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
MapperGlyphVector::MapperGlyphVector()
|
||||
: MapperGlyphBase()
|
||||
, GlyphType(vtkm::rendering::GlyphType::Arrow)
|
||||
{
|
||||
}
|
||||
|
||||
MapperGlyphVector::~MapperGlyphVector() {}
|
||||
|
||||
vtkm::rendering::GlyphType MapperGlyphVector::GetGlyphType() const
|
||||
{
|
||||
return this->GlyphType;
|
||||
}
|
||||
|
||||
void MapperGlyphVector::SetGlyphType(vtkm::rendering::GlyphType glyphType)
|
||||
{
|
||||
if (!(glyphType == vtkm::rendering::GlyphType::Arrow))
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("MapperGlyphVector: bad glyph type");
|
||||
}
|
||||
|
||||
this->GlyphType = glyphType;
|
||||
}
|
||||
|
||||
void MapperGlyphVector::RenderCells(const vtkm::cont::UnknownCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::cont::ColorTable& vtkmNotUsed(colorTable),
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& vtkmNotUsed(fieldRange))
|
||||
{
|
||||
raytracing::Logger* logger = raytracing::Logger::GetInstance();
|
||||
|
||||
vtkm::rendering::raytracing::RayTracer tracer;
|
||||
tracer.Clear();
|
||||
|
||||
logger->OpenLogEntry("mapper_glyph_vector");
|
||||
vtkm::cont::Timer tot_timer;
|
||||
tot_timer.Start();
|
||||
vtkm::cont::Timer timer;
|
||||
|
||||
vtkm::Bounds coordBounds = coords.GetBounds();
|
||||
vtkm::Float32 baseSize = this->BaseSize;
|
||||
if (baseSize == -1.f)
|
||||
{
|
||||
// set a default size
|
||||
vtkm::Float64 lx = coordBounds.X.Length();
|
||||
vtkm::Float64 ly = coordBounds.Y.Length();
|
||||
vtkm::Float64 lz = coordBounds.Z.Length();
|
||||
vtkm::Float64 mag = vtkm::Sqrt(lx * lx + ly * ly + lz * lz);
|
||||
// same as used in vtk ospray
|
||||
constexpr vtkm::Float64 heuristic = 500.;
|
||||
baseSize = static_cast<vtkm::Float32>(mag / heuristic);
|
||||
}
|
||||
|
||||
vtkm::rendering::raytracing::GlyphExtractorVector glyphExtractor;
|
||||
|
||||
vtkm::cont::DataSet processedDataSet = this->FilterPoints(cellset, coords, field);
|
||||
vtkm::cont::UnknownCellSet processedCellSet = processedDataSet.GetCellSet();
|
||||
vtkm::cont::CoordinateSystem processedCoords = processedDataSet.GetCoordinateSystem();
|
||||
vtkm::cont::Field processedField = processedDataSet.GetField(0);
|
||||
|
||||
if (this->ScaleByValue)
|
||||
{
|
||||
vtkm::Float32 minSize = baseSize - baseSize * this->ScaleDelta;
|
||||
vtkm::Float32 maxSize = baseSize + baseSize * this->ScaleDelta;
|
||||
if (this->UseNodes)
|
||||
{
|
||||
glyphExtractor.ExtractCoordinates(processedCoords, processedField, minSize, maxSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyphExtractor.ExtractCells(processedCellSet, processedField, minSize, maxSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->UseNodes)
|
||||
{
|
||||
glyphExtractor.ExtractCoordinates(processedCoords, processedField, baseSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyphExtractor.ExtractCells(processedCellSet, processedField, baseSize);
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::Bounds shapeBounds;
|
||||
if (glyphExtractor.GetNumberOfGlyphs() > 0)
|
||||
{
|
||||
auto glyphIntersector = std::make_shared<raytracing::GlyphIntersectorVector>(this->GlyphType);
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Arrow)
|
||||
{
|
||||
vtkm::Float32 arrowBodyRadius = 0.08f * baseSize;
|
||||
vtkm::Float32 arrowHeadRadius = 0.16f * baseSize;
|
||||
glyphIntersector->SetArrowRadii(arrowBodyRadius, arrowHeadRadius);
|
||||
}
|
||||
glyphIntersector->SetData(
|
||||
processedCoords, glyphExtractor.GetPointIds(), glyphExtractor.GetSizes());
|
||||
|
||||
tracer.AddShapeIntersector(glyphIntersector);
|
||||
shapeBounds.Include(glyphIntersector->GetShapeBounds());
|
||||
}
|
||||
|
||||
//
|
||||
// Create rays
|
||||
//
|
||||
vtkm::Int32 width = (vtkm::Int32)this->Canvas->GetWidth();
|
||||
vtkm::Int32 height = (vtkm::Int32)this->Canvas->GetHeight();
|
||||
|
||||
vtkm::rendering::raytracing::Camera RayCamera;
|
||||
vtkm::rendering::raytracing::Ray<vtkm::Float32> Rays;
|
||||
|
||||
RayCamera.SetParameters(camera, width, height);
|
||||
|
||||
RayCamera.CreateRays(Rays, shapeBounds);
|
||||
Rays.Buffers.at(0).InitConst(0.f);
|
||||
raytracing::RayOperations::MapCanvasToRays(Rays, camera, *this->Canvas);
|
||||
|
||||
auto magnitudeField = glyphExtractor.GetMagnitudeField();
|
||||
auto magnitudeFieldRange = magnitudeField.GetRange().ReadPortal().Get(0);
|
||||
tracer.SetField(magnitudeField, magnitudeFieldRange);
|
||||
tracer.GetCamera() = RayCamera;
|
||||
tracer.SetColorMap(this->ColorMap);
|
||||
tracer.Render(Rays);
|
||||
|
||||
timer.Start();
|
||||
this->Canvas->WriteToCanvas(Rays, Rays.Buffers.at(0).Buffer, camera);
|
||||
|
||||
if (this->CompositeBackground)
|
||||
{
|
||||
this->Canvas->BlendBackground();
|
||||
}
|
||||
|
||||
vtkm::Float64 time = timer.GetElapsedTime();
|
||||
logger->AddLogData("write_to_canvas", time);
|
||||
time = tot_timer.GetElapsedTime();
|
||||
logger->CloseLogEntry(time);
|
||||
}
|
||||
|
||||
vtkm::rendering::Mapper* MapperGlyphVector::NewCopy() const
|
||||
{
|
||||
return new vtkm::rendering::MapperGlyphVector(*this);
|
||||
}
|
||||
}
|
||||
} // vtkm::rendering
|
46
vtkm/rendering/MapperGlyphVector.h
Normal file
46
vtkm/rendering/MapperGlyphVector.h
Normal file
@ -0,0 +1,46 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_MapperGlyphVector_h
|
||||
#define vtk_m_rendering_MapperGlyphVector_h
|
||||
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/MapperGlyphBase.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
|
||||
class VTKM_RENDERING_EXPORT MapperGlyphVector : public vtkm::rendering::MapperGlyphBase
|
||||
{
|
||||
public:
|
||||
MapperGlyphVector();
|
||||
|
||||
~MapperGlyphVector();
|
||||
|
||||
vtkm::rendering::GlyphType GetGlyphType() const;
|
||||
void SetGlyphType(vtkm::rendering::GlyphType glyphType);
|
||||
|
||||
void RenderCells(const vtkm::cont::UnknownCellSet& cellset,
|
||||
const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& scalarField,
|
||||
const vtkm::cont::ColorTable& colorTable,
|
||||
const vtkm::rendering::Camera& camera,
|
||||
const vtkm::Range& scalarRange) override;
|
||||
|
||||
vtkm::rendering::Mapper* NewCopy() const override;
|
||||
|
||||
protected:
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
};
|
||||
}
|
||||
} //namespace vtkm::rendering
|
||||
|
||||
#endif //vtk_m_rendering_MapperGlyphVector_h
|
@ -20,6 +20,10 @@ set(headers
|
||||
ConnectivityTracer.h
|
||||
CylinderExtractor.h
|
||||
CylinderIntersector.h
|
||||
GlyphExtractor.h
|
||||
GlyphExtractorVector.h
|
||||
GlyphIntersector.h
|
||||
GlyphIntersectorVector.h
|
||||
Logger.h
|
||||
MeshConnectivityBuilder.h
|
||||
MeshConnectivityContainers.h
|
||||
|
223
vtkm/rendering/raytracing/GlyphExtractor.cxx
Normal file
223
vtkm/rendering/raytracing/GlyphExtractor.cxx
Normal file
@ -0,0 +1,223 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphExtractor.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class CountPoints : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CountPoints() {}
|
||||
typedef void ControlSignature(CellSetIn cellset, FieldOut);
|
||||
typedef void ExecutionSignature(CellShape, _2);
|
||||
|
||||
template <typename ShapeType>
|
||||
VTKM_EXEC void operator()(ShapeType shape, vtkm::Id& points) const
|
||||
{
|
||||
points = (shape.Id == vtkm::CELL_SHAPE_VERTEX) ? 1 : 0;
|
||||
}
|
||||
}; // class CountPoints
|
||||
|
||||
class Pointify : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Pointify() {}
|
||||
typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
|
||||
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
|
||||
|
||||
template <typename ShapeType, typename VecType, typename OutputPortal>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
|
||||
ShapeType shape,
|
||||
const VecType& vtkmNotUsed(cellIndices),
|
||||
const vtkm::Id& cellId,
|
||||
OutputPortal& outputIndices) const
|
||||
{
|
||||
if (shape.Id == vtkm::CELL_SHAPE_VERTEX)
|
||||
{
|
||||
outputIndices.Set(pointOffset, cellId);
|
||||
}
|
||||
}
|
||||
}; //class Pointify
|
||||
|
||||
class GetFieldSize : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
// vtkm::Float64 is used to handle field values that are very small or very large
|
||||
// and could loose precision if vtkm::Float32 is used.
|
||||
vtkm::Float64 MinSize;
|
||||
vtkm::Float64 SizeDelta;
|
||||
vtkm::Float64 MinValue;
|
||||
vtkm::Float64 InverseDelta;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GetFieldSize(vtkm::Float64 minSize, vtkm::Float64 maxSize, vtkm::Range scalarRange)
|
||||
: MinSize(minSize)
|
||||
, SizeDelta(maxSize - minSize)
|
||||
, MinValue(scalarRange.Min)
|
||||
{
|
||||
vtkm::Float64 delta = scalarRange.Max - scalarRange.Min;
|
||||
if (delta != 0.)
|
||||
InverseDelta = 1. / (delta);
|
||||
else
|
||||
InverseDelta = 0.; // just map scalar to 0;
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn, FieldOut, WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
|
||||
template <typename ScalarPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
vtkm::Float32& size,
|
||||
const ScalarPortalType& scalars) const
|
||||
{
|
||||
vtkm::Float64 scalar = vtkm::Float64(scalars.Get(pointId));
|
||||
vtkm::Float64 t = (scalar - this->MinValue) * this->InverseDelta;
|
||||
size = static_cast<vtkm::Float32>(this->MinSize + t * this->SizeDelta);
|
||||
}
|
||||
|
||||
}; //class GetFieldSize
|
||||
|
||||
} //namespace
|
||||
|
||||
GlyphExtractor::GlyphExtractor() = default;
|
||||
|
||||
void GlyphExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::Float32 size)
|
||||
{
|
||||
this->SetPointIdsFromCoords(coords);
|
||||
this->SetUniformSize(size);
|
||||
}
|
||||
|
||||
void GlyphExtractor::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize)
|
||||
{
|
||||
this->SetPointIdsFromCoords(coords);
|
||||
this->SetVaryingSize(minSize, maxSize, field);
|
||||
}
|
||||
|
||||
void GlyphExtractor::ExtractCells(const vtkm::cont::UnknownCellSet& cells, const vtkm::Float32 size)
|
||||
{
|
||||
this->SetPointIdsFromCells(cells);
|
||||
this->SetUniformSize(size);
|
||||
}
|
||||
void GlyphExtractor::ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize)
|
||||
{
|
||||
this->SetPointIdsFromCells(cells);
|
||||
this->SetVaryingSize(minSize, maxSize, field);
|
||||
}
|
||||
|
||||
void GlyphExtractor::SetUniformSize(const vtkm::Float32 size)
|
||||
{
|
||||
const vtkm::Id numValues = this->PointIds.GetNumberOfValues();
|
||||
Sizes.AllocateAndFill(numValues, size);
|
||||
}
|
||||
|
||||
void GlyphExtractor::SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords)
|
||||
{
|
||||
vtkm::Id size = coords.GetNumberOfPoints();
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(size), this->PointIds);
|
||||
}
|
||||
|
||||
void GlyphExtractor::SetPointIdsFromCells(const vtkm::cont::UnknownCellSet& cells)
|
||||
{
|
||||
using SingleType = vtkm::cont::CellSetSingleType<>;
|
||||
vtkm::Id numCells = cells.GetNumberOfCells();
|
||||
if (numCells == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//
|
||||
// look for points in the cell set
|
||||
//
|
||||
if (cells.CanConvert<vtkm::cont::CellSetExplicit<>>())
|
||||
{
|
||||
auto cellsExplicit = cells.AsCellSet<vtkm::cont::CellSetExplicit<>>();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> points;
|
||||
vtkm::worklet::DispatcherMapTopology<CountPoints>(CountPoints()).Invoke(cellsExplicit, points);
|
||||
|
||||
vtkm::Id totalPoints = 0;
|
||||
totalPoints = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
|
||||
vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets);
|
||||
PointIds.Allocate(totalPoints);
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<Pointify>(Pointify())
|
||||
.Invoke(cellsExplicit, cellOffsets, this->PointIds);
|
||||
}
|
||||
else if (cells.CanConvert<SingleType>())
|
||||
{
|
||||
SingleType pointCells = cells.AsCellSet<SingleType>();
|
||||
vtkm::UInt8 shape_id = pointCells.GetCellShape(0);
|
||||
if (shape_id == vtkm::CELL_SHAPE_VERTEX)
|
||||
{
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(numCells), this->PointIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphExtractor::SetVaryingSize(const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize,
|
||||
const vtkm::cont::Field& field)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray = field.GetRange();
|
||||
if (rangeArray.GetNumberOfValues() != 1)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue("Glyph Extractor: scalar field must have one component");
|
||||
}
|
||||
|
||||
vtkm::Range range = rangeArray.ReadPortal().Get(0);
|
||||
|
||||
Sizes.Allocate(this->PointIds.GetNumberOfValues());
|
||||
vtkm::worklet::DispatcherMapField<GetFieldSize>(GetFieldSize(minSize, maxSize, range))
|
||||
.Invoke(this->PointIds, this->Sizes, vtkm::rendering::raytracing::GetScalarFieldArray(field));
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> GlyphExtractor::GetPointIds()
|
||||
{
|
||||
return this->PointIds;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> GlyphExtractor::GetSizes()
|
||||
{
|
||||
return this->Sizes;
|
||||
}
|
||||
|
||||
vtkm::Id GlyphExtractor::GetNumberOfGlyphs() const
|
||||
{
|
||||
return this->PointIds.GetNumberOfValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
74
vtkm/rendering/raytracing/GlyphExtractor.h
Normal file
74
vtkm/rendering/raytracing/GlyphExtractor.h
Normal file
@ -0,0 +1,74 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Glyph_Extractor_h
|
||||
#define vtk_m_rendering_raytracing_Glyph_Extractor_h
|
||||
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class GlyphExtractor
|
||||
{
|
||||
public:
|
||||
GlyphExtractor();
|
||||
|
||||
//
|
||||
// Extract all nodes using a constant size
|
||||
//
|
||||
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords, const vtkm::Float32 size);
|
||||
|
||||
//
|
||||
// Set size based on scalar field values. Each is interpolated from min to max
|
||||
//
|
||||
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize);
|
||||
|
||||
//
|
||||
// Extract all vertex shapes with constant size
|
||||
//
|
||||
void ExtractCells(const vtkm::cont::UnknownCellSet& cells, vtkm::Float32 size);
|
||||
|
||||
//
|
||||
// Extract all vertex elements with size based on scalar values
|
||||
//
|
||||
void ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize);
|
||||
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> GetPointIds();
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> GetSizes();
|
||||
|
||||
vtkm::Id GetNumberOfGlyphs() const;
|
||||
|
||||
protected:
|
||||
void SetUniformSize(const vtkm::Float32 size);
|
||||
void SetVaryingSize(const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize,
|
||||
const vtkm::cont::Field& field);
|
||||
|
||||
void SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords);
|
||||
void SetPointIdsFromCells(const vtkm::cont::UnknownCellSet& cells);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> Sizes;
|
||||
}; // class GlyphExtractor
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif //vtk_m_rendering_raytracing_Glyph_Extractor_h
|
352
vtkm/rendering/raytracing/GlyphExtractorVector.cxx
Normal file
352
vtkm/rendering/raytracing/GlyphExtractorVector.cxx
Normal file
@ -0,0 +1,352 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphExtractorVector.h>
|
||||
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class CountPoints : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CountPoints() {}
|
||||
typedef void ControlSignature(CellSetIn cellset, FieldOut);
|
||||
typedef void ExecutionSignature(CellShape, _2);
|
||||
|
||||
template <typename ShapeType>
|
||||
VTKM_EXEC void operator()(ShapeType shape, vtkm::Id& points) const
|
||||
{
|
||||
points = (shape.Id == vtkm::CELL_SHAPE_VERTEX) ? 1 : 0;
|
||||
}
|
||||
}; // class CountPoints
|
||||
|
||||
class Pointify : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
Pointify() {}
|
||||
typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
|
||||
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
|
||||
|
||||
template <typename ShapeType, typename VecType, typename OutputPortal>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
|
||||
ShapeType shape,
|
||||
const VecType& vtkmNotUsed(cellIndices),
|
||||
const vtkm::Id& cellId,
|
||||
OutputPortal& outputIndices) const
|
||||
{
|
||||
if (shape.Id == vtkm::CELL_SHAPE_VERTEX)
|
||||
{
|
||||
outputIndices.Set(pointOffset, cellId);
|
||||
}
|
||||
}
|
||||
}; //class Pointify
|
||||
|
||||
struct MinFunctor
|
||||
{
|
||||
template <typename VecType>
|
||||
VTKM_EXEC VecType operator()(const VecType& x, const VecType& y) const
|
||||
{
|
||||
return (vtkm::MagnitudeSquared(y) < vtkm::MagnitudeSquared(x)) ? y : x;
|
||||
}
|
||||
};
|
||||
|
||||
struct MaxFunctor
|
||||
{
|
||||
template <typename VecType>
|
||||
VTKM_EXEC VecType operator()(const VecType& x, const VecType& y) const
|
||||
{
|
||||
return (vtkm::MagnitudeSquared(x) < vtkm::MagnitudeSquared(y)) ? y : x;
|
||||
}
|
||||
};
|
||||
|
||||
class GetFieldSize : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
protected:
|
||||
vtkm::Float64 MinSize;
|
||||
vtkm::Float64 SizeDelta;
|
||||
vtkm::Float64 MinValueMagnitude;
|
||||
vtkm::Float64 InverseDelta;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GetFieldSize(vtkm::Float64 minSize,
|
||||
vtkm::Float64 maxSize,
|
||||
vtkm::Vec3f_64 minValue,
|
||||
vtkm::Vec3f_64 maxValue)
|
||||
: MinSize(minSize)
|
||||
, SizeDelta(maxSize - minSize)
|
||||
{
|
||||
MinValueMagnitude = vtkm::Magnitude(minValue);
|
||||
vtkm::Float64 minMag = vtkm::Magnitude(minValue);
|
||||
vtkm::Float64 maxMag = vtkm::Magnitude(maxValue);
|
||||
vtkm::Float64 delta = maxMag - minMag;
|
||||
if (delta != 0.)
|
||||
InverseDelta = 1. / (delta);
|
||||
else
|
||||
InverseDelta = 0.; // just map scalar to 0;
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn, FieldOut, WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
|
||||
template <typename FieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
vtkm::Vec3f_32& size,
|
||||
const FieldPortalType& field) const
|
||||
{
|
||||
using ValueType = typename FieldPortalType::ValueType;
|
||||
|
||||
ValueType fieldVal = field.Get(pointId);
|
||||
vtkm::Float64 fieldValMag = vtkm::Magnitude(fieldVal);
|
||||
vtkm::Normalize(fieldVal);
|
||||
vtkm::Float64 t = (fieldValMag - MinValueMagnitude) * InverseDelta;
|
||||
vtkm::Float64 sizeMag = MinSize + t * SizeDelta;
|
||||
vtkm::Vec3f_64 tempSize = fieldVal * sizeMag;
|
||||
|
||||
size[0] = static_cast<vtkm::Float32>(tempSize[0]);
|
||||
size[1] = static_cast<vtkm::Float32>(tempSize[1]);
|
||||
size[2] = static_cast<vtkm::Float32>(tempSize[2]);
|
||||
}
|
||||
|
||||
}; //class GetFieldSize
|
||||
|
||||
class FieldMagnitude : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
FieldMagnitude() {}
|
||||
|
||||
typedef void ControlSignature(FieldIn, WholeArrayIn, WholeArrayInOut);
|
||||
typedef void ExecutionSignature(_1, _2, _3);
|
||||
|
||||
template <typename FieldPortalType, typename MagnitudeFieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
const FieldPortalType& field,
|
||||
MagnitudeFieldPortalType& magnitudeField) const
|
||||
{
|
||||
using FieldValueType = typename FieldPortalType::ValueType;
|
||||
|
||||
FieldValueType fieldVal = field.Get(pointId);
|
||||
vtkm::Float32 fieldValMag = static_cast<vtkm::Float32>(vtkm::Magnitude(fieldVal));
|
||||
magnitudeField.Set(pointId, fieldValMag);
|
||||
}
|
||||
}; //class FieldMagnitude
|
||||
|
||||
class UniformFieldMagnitude : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(FieldIn, FieldOut, WholeArrayIn);
|
||||
using ExecutionSignature = void(_1, _2, _3);
|
||||
|
||||
VTKM_CONT
|
||||
UniformFieldMagnitude(vtkm::Float32 uniformMagnitude)
|
||||
: UniformMagnitude(uniformMagnitude)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename FieldPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
vtkm::Vec3f_32& size,
|
||||
const FieldPortalType& field) const
|
||||
{
|
||||
vtkm::Vec3f_32 fieldVal = static_cast<vtkm::Vec3f_32>(field.Get(pointId));
|
||||
size = vtkm::Normal(fieldVal) * this->UniformMagnitude;
|
||||
}
|
||||
|
||||
vtkm::Float32 UniformMagnitude;
|
||||
}; //class UniformFieldMagnitude
|
||||
|
||||
} //namespace
|
||||
|
||||
GlyphExtractorVector::GlyphExtractorVector() = default;
|
||||
|
||||
void GlyphExtractorVector::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 size)
|
||||
{
|
||||
this->SetPointIdsFromCoords(coords);
|
||||
this->SetUniformSize(size, field);
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize)
|
||||
{
|
||||
this->SetPointIdsFromCoords(coords);
|
||||
this->SetVaryingSize(minSize, maxSize, field);
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 size)
|
||||
{
|
||||
this->SetPointIdsFromCells(cells);
|
||||
this->SetUniformSize(size, field);
|
||||
}
|
||||
void GlyphExtractorVector::ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize)
|
||||
{
|
||||
this->SetPointIdsFromCells(cells);
|
||||
this->SetVaryingSize(minSize, maxSize, field);
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::SetUniformSize(const vtkm::Float32 size, const vtkm::cont::Field& field)
|
||||
{
|
||||
this->ExtractMagnitudeField(field);
|
||||
|
||||
this->Sizes.Allocate(this->PointIds.GetNumberOfValues());
|
||||
vtkm::cont::Invoker invoker;
|
||||
invoker(UniformFieldMagnitude(size),
|
||||
this->PointIds,
|
||||
this->Sizes,
|
||||
vtkm::rendering::raytracing::GetVec3FieldArray(field));
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::ExtractMagnitudeField(const vtkm::cont::Field& field)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> magnitudeArray;
|
||||
magnitudeArray.Allocate(this->PointIds.GetNumberOfValues());
|
||||
vtkm::worklet::DispatcherMapField<FieldMagnitude>(FieldMagnitude())
|
||||
.Invoke(this->PointIds, vtkm::rendering::raytracing::GetVec3FieldArray(field), magnitudeArray);
|
||||
this->MagnitudeField = vtkm::cont::Field(field);
|
||||
this->MagnitudeField.SetData(magnitudeArray);
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords)
|
||||
{
|
||||
vtkm::Id size = coords.GetNumberOfPoints();
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(size), this->PointIds);
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::SetPointIdsFromCells(const vtkm::cont::UnknownCellSet& cells)
|
||||
{
|
||||
using SingleType = vtkm::cont::CellSetSingleType<>;
|
||||
vtkm::Id numCells = cells.GetNumberOfCells();
|
||||
if (numCells == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//
|
||||
// look for points in the cell set
|
||||
//
|
||||
if (cells.CanConvert<vtkm::cont::CellSetExplicit<>>())
|
||||
{
|
||||
auto cellsExplicit = cells.AsCellSet<vtkm::cont::CellSetExplicit<>>();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> points;
|
||||
vtkm::worklet::DispatcherMapTopology<CountPoints>(CountPoints()).Invoke(cellsExplicit, points);
|
||||
|
||||
vtkm::Id totalPoints = 0;
|
||||
totalPoints = vtkm::cont::Algorithm::Reduce(points, vtkm::Id(0));
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
|
||||
vtkm::cont::Algorithm::ScanExclusive(points, cellOffsets);
|
||||
PointIds.Allocate(totalPoints);
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<Pointify>(Pointify())
|
||||
.Invoke(cellsExplicit, cellOffsets, this->PointIds);
|
||||
}
|
||||
else if (cells.CanConvert<SingleType>())
|
||||
{
|
||||
SingleType pointCells = cells.AsCellSet<SingleType>();
|
||||
vtkm::UInt8 shape_id = pointCells.GetCellShape(0);
|
||||
if (shape_id == vtkm::CELL_SHAPE_VERTEX)
|
||||
{
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(numCells), this->PointIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphExtractorVector::SetVaryingSize(const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize,
|
||||
const vtkm::cont::Field& field)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rangeArray = field.GetRange();
|
||||
if (rangeArray.GetNumberOfValues() != 3)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"Glyph Extractor Vector: vector field must have three components");
|
||||
}
|
||||
|
||||
using Vec3f_32Handle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
|
||||
using Vec3f_64Handle = vtkm::cont::ArrayHandle<vtkm::Vec3f_64>;
|
||||
vtkm::cont::UnknownArrayHandle fieldUnknownHandle = field.GetData();
|
||||
vtkm::Vec3f_32 minFieldValue, maxFieldValue;
|
||||
|
||||
if (fieldUnknownHandle.CanConvert<Vec3f_64Handle>())
|
||||
{
|
||||
Vec3f_64Handle fieldArray;
|
||||
field.GetData().AsArrayHandle(fieldArray);
|
||||
vtkm::Vec3f_64 initVal = vtkm::cont::ArrayGetValue(0, fieldArray);
|
||||
minFieldValue =
|
||||
static_cast<vtkm::Vec3f_32>(vtkm::cont::Algorithm::Reduce(fieldArray, initVal, MinFunctor()));
|
||||
maxFieldValue =
|
||||
static_cast<vtkm::Vec3f_32>(vtkm::cont::Algorithm::Reduce(fieldArray, initVal, MaxFunctor()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec3f_32Handle fieldArray;
|
||||
field.GetData().AsArrayHandle(fieldArray);
|
||||
vtkm::Vec3f_32 initVal = vtkm::cont::ArrayGetValue(0, fieldArray);
|
||||
minFieldValue =
|
||||
static_cast<vtkm::Vec3f_32>(vtkm::cont::Algorithm::Reduce(fieldArray, initVal, MinFunctor()));
|
||||
maxFieldValue =
|
||||
static_cast<vtkm::Vec3f_32>(vtkm::cont::Algorithm::Reduce(fieldArray, initVal, MaxFunctor()));
|
||||
}
|
||||
|
||||
this->ExtractMagnitudeField(field);
|
||||
|
||||
this->Sizes.Allocate(this->PointIds.GetNumberOfValues());
|
||||
vtkm::worklet::DispatcherMapField<GetFieldSize>(
|
||||
GetFieldSize(minSize, maxSize, minFieldValue, maxFieldValue))
|
||||
.Invoke(this->PointIds, this->Sizes, vtkm::rendering::raytracing::GetVec3FieldArray(field));
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> GlyphExtractorVector::GetPointIds()
|
||||
{
|
||||
return this->PointIds;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> GlyphExtractorVector::GetSizes()
|
||||
{
|
||||
return this->Sizes;
|
||||
}
|
||||
|
||||
vtkm::cont::Field GlyphExtractorVector::GetMagnitudeField()
|
||||
{
|
||||
return this->MagnitudeField;
|
||||
}
|
||||
|
||||
vtkm::Id GlyphExtractorVector::GetNumberOfGlyphs() const
|
||||
{
|
||||
return this->PointIds.GetNumberOfValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
83
vtkm/rendering/raytracing/GlyphExtractorVector.h
Normal file
83
vtkm/rendering/raytracing/GlyphExtractorVector.h
Normal file
@ -0,0 +1,83 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Glyph_Extractor_Vector_h
|
||||
#define vtk_m_rendering_raytracing_Glyph_Extractor_Vector_h
|
||||
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class GlyphExtractorVector
|
||||
{
|
||||
public:
|
||||
GlyphExtractorVector();
|
||||
|
||||
//
|
||||
// Extract all nodes using a constant size
|
||||
//
|
||||
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 size);
|
||||
|
||||
//
|
||||
// Set size based on scalar field values. Each is interpolated from min to max
|
||||
//
|
||||
void ExtractCoordinates(const vtkm::cont::CoordinateSystem& coords,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize);
|
||||
|
||||
//
|
||||
// Extract all vertex shapes with constant size
|
||||
//
|
||||
void ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
vtkm::Float32 size);
|
||||
|
||||
//
|
||||
// Extract all vertex elements with size based on scalar values
|
||||
//
|
||||
void ExtractCells(const vtkm::cont::UnknownCellSet& cells,
|
||||
const vtkm::cont::Field& field,
|
||||
const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize);
|
||||
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> GetPointIds();
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> GetSizes();
|
||||
vtkm::cont::Field GetMagnitudeField();
|
||||
|
||||
vtkm::Id GetNumberOfGlyphs() const;
|
||||
|
||||
protected:
|
||||
void SetUniformSize(const vtkm::Float32 size, const vtkm::cont::Field& field);
|
||||
void SetVaryingSize(const vtkm::Float32 minSize,
|
||||
const vtkm::Float32 maxSize,
|
||||
const vtkm::cont::Field& field);
|
||||
|
||||
void SetPointIdsFromCoords(const vtkm::cont::CoordinateSystem& coords);
|
||||
void SetPointIdsFromCells(const vtkm::cont::UnknownCellSet& cells);
|
||||
|
||||
void ExtractMagnitudeField(const vtkm::cont::Field& field);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> Sizes;
|
||||
vtkm::cont::Field MagnitudeField;
|
||||
|
||||
}; // class GlyphExtractorVector
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif //vtk_m_rendering_raytracing_Glyph_Extractor_Vector_h
|
637
vtkm/rendering/raytracing/GlyphIntersector.cxx
Normal file
637
vtkm/rendering/raytracing/GlyphIntersector.cxx
Normal file
@ -0,0 +1,637 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/rendering/raytracing/BVHTraverser.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphIntersector.h>
|
||||
#include <vtkm/rendering/raytracing/RayOperations.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
|
||||
// This line is at the end to prevent warnings when building for CUDA
|
||||
#include <vtkm/Swap.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class FindGlyphAABBs : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
FindGlyphAABBs() {}
|
||||
typedef void ControlSignature(FieldIn,
|
||||
FieldIn,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8, _9);
|
||||
template <typename PointPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
const vtkm::Float32& size,
|
||||
vtkm::Float32& xmin,
|
||||
vtkm::Float32& ymin,
|
||||
vtkm::Float32& zmin,
|
||||
vtkm::Float32& xmax,
|
||||
vtkm::Float32& ymax,
|
||||
vtkm::Float32& zmax,
|
||||
const PointPortalType& points) const
|
||||
{
|
||||
vtkm::Vec3f_32 point;
|
||||
point = static_cast<vtkm::Vec3f_32>(points.Get(pointId));
|
||||
vtkm::Float32 absSize = vtkm::Abs(size);
|
||||
|
||||
xmin = point[0] - absSize;
|
||||
xmax = point[0] + absSize;
|
||||
ymin = point[1] - absSize;
|
||||
ymax = point[1] + absSize;
|
||||
zmin = point[2] - absSize;
|
||||
zmax = point[2] + absSize;
|
||||
}
|
||||
}; //class FindGlyphAABBs
|
||||
|
||||
template <typename Device>
|
||||
class GlyphLeafIntersector
|
||||
{
|
||||
public:
|
||||
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using IdArrayPortal = typename IdHandle::ReadPortalType;
|
||||
using FloatHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
|
||||
using VecHandle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>>;
|
||||
using FloatPortal = typename FloatHandle::ReadPortalType;
|
||||
using VecPortal = typename VecHandle::ReadPortalType;
|
||||
IdArrayPortal PointIds;
|
||||
FloatPortal Sizes;
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
|
||||
GlyphLeafIntersector() {}
|
||||
|
||||
GlyphLeafIntersector(const IdHandle& pointIds,
|
||||
const FloatHandle& sizes,
|
||||
vtkm::rendering::GlyphType glyphType,
|
||||
vtkm::cont::Token& token)
|
||||
: PointIds(pointIds.PrepareForInput(Device(), token))
|
||||
, Sizes(sizes.PrepareForInput(Device(), token))
|
||||
, GlyphType(glyphType)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename PointPortalType, typename LeafPortalType, typename Precision>
|
||||
VTKM_EXEC inline void IntersectLeaf(const vtkm::Int32& currentNode,
|
||||
const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const PointPortalType& points,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& minU,
|
||||
Precision& minV,
|
||||
LeafPortalType leafs,
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
const vtkm::Id glyphCount = leafs.Get(currentNode);
|
||||
|
||||
for (vtkm::Id i = 1; i <= glyphCount; ++i)
|
||||
{
|
||||
const vtkm::Id idx = leafs.Get(currentNode + i);
|
||||
vtkm::Id pointIndex = PointIds.Get(idx);
|
||||
Precision size = Sizes.Get(idx);
|
||||
vtkm::Vec<Precision, 3> point = vtkm::Vec<Precision, 3>(points.Get(pointIndex));
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Sphere)
|
||||
{
|
||||
this->IntersectSphere(
|
||||
origin, dir, point, size, pointIndex, hitIndex, closestDistance, minU, minV, minDistance);
|
||||
}
|
||||
else if (this->GlyphType == vtkm::rendering::GlyphType::Cube)
|
||||
{
|
||||
this->IntersectCube(
|
||||
origin, dir, point, size, pointIndex, hitIndex, closestDistance, minU, minV, minDistance);
|
||||
}
|
||||
else if (this->GlyphType == vtkm::rendering::GlyphType::Axes)
|
||||
{
|
||||
this->IntersectAxes(
|
||||
origin, dir, point, size, pointIndex, hitIndex, closestDistance, minU, minV, minDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void IntersectSphere(const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& size,
|
||||
const vtkm::Id& pointIndex,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& vtkmNotUsed(minU),
|
||||
Precision& vtkmNotUsed(minV),
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> l = point - origin;
|
||||
Precision dot1 = vtkm::dot(l, dir);
|
||||
if (dot1 >= 0)
|
||||
{
|
||||
Precision d = vtkm::dot(l, l) - dot1 * dot1;
|
||||
Precision r2 = size * size;
|
||||
if (d <= r2)
|
||||
{
|
||||
Precision tch = vtkm::Sqrt(r2 - d);
|
||||
Precision t0 = dot1 - tch;
|
||||
|
||||
if (t0 < closestDistance && t0 > minDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void IntersectCube(const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const vtkm ::Vec<Precision, 3>& point,
|
||||
const Precision& size,
|
||||
const vtkm::Id& pointIndex,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& vtkmNotUsed(minU),
|
||||
Precision& vtkmNotUsed(minV),
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
Precision xmin, xmax, ymin, ymax, zmin, zmax;
|
||||
this->CalculateAABB(point, size, xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
|
||||
Precision tmin = (xmin - origin[0]) / dir[0];
|
||||
Precision tmax = (xmax - origin[0]) / dir[0];
|
||||
|
||||
if (tmin > tmax)
|
||||
vtkm::Swap(tmin, tmax);
|
||||
|
||||
Precision tymin = (ymin - origin[1]) / dir[1];
|
||||
Precision tymax = (ymax - origin[1]) / dir[1];
|
||||
if (tymin > tymax)
|
||||
vtkm::Swap(tymin, tymax);
|
||||
|
||||
if ((tmin > tymax) || (tymin > tmax))
|
||||
return;
|
||||
|
||||
if (tymin > tmin)
|
||||
tmin = tymin;
|
||||
|
||||
if (tymax < tmax)
|
||||
tmax = tymax;
|
||||
|
||||
Precision tzmin = (zmin - origin[2]) / dir[2];
|
||||
Precision tzmax = (zmax - origin[2]) / dir[2];
|
||||
|
||||
if (tzmin > tzmax)
|
||||
vtkm::Swap(tzmin, tzmax);
|
||||
|
||||
if ((tmin > tzmax) || (tzmin > tmax))
|
||||
return;
|
||||
|
||||
if (tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
|
||||
if (tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
|
||||
if (tmin < closestDistance && tmin > minDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = tmin;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void IntersectAxes(const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& size,
|
||||
const vtkm::Id& pointIndex,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& vtkmNotUsed(minU),
|
||||
Precision& vtkmNotUsed(minV),
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
Precision xmin, xmax, ymin, ymax, zmin, zmax;
|
||||
this->CalculateAABB(point, size, xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
|
||||
Precision t = (point[0] - origin[0]) / dir[0];
|
||||
vtkm::Vec<Precision, 3> intersection = origin + t * dir;
|
||||
|
||||
if ((intersection[1] >= ymin && intersection[1] <= ymax) &&
|
||||
(intersection[2] >= zmin && intersection[2] <= zmax))
|
||||
{
|
||||
if (t < closestDistance && t > minDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = (point[1] - origin[1]) / dir[1];
|
||||
intersection = origin + t * dir;
|
||||
if ((intersection[0] >= xmin && intersection[0] <= xmax) &&
|
||||
(intersection[2] >= zmin && intersection[2] <= zmax))
|
||||
{
|
||||
if (t < closestDistance && t > minDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
}
|
||||
}
|
||||
|
||||
t = (point[2] - origin[2]) / dir[2];
|
||||
intersection = origin + t * dir;
|
||||
if ((intersection[0] >= xmin && intersection[0] <= xmax) &&
|
||||
(intersection[1] >= ymin && intersection[1] <= ymax))
|
||||
{
|
||||
if (t < closestDistance && t > minDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC void CalculateAABB(const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& size,
|
||||
Precision& xmin,
|
||||
Precision& ymin,
|
||||
Precision& zmin,
|
||||
Precision& xmax,
|
||||
Precision& ymax,
|
||||
Precision& zmax) const
|
||||
{
|
||||
Precision absSize = vtkm::Abs(size);
|
||||
xmin = point[0] - absSize;
|
||||
xmax = point[0] + absSize;
|
||||
ymin = point[1] - absSize;
|
||||
ymax = point[1] + absSize;
|
||||
zmin = point[2] - absSize;
|
||||
zmax = point[2] + absSize;
|
||||
}
|
||||
};
|
||||
|
||||
class GlyphLeafWrapper : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
protected:
|
||||
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using FloatHandle = vtkm::cont::ArrayHandle<vtkm::Float32>;
|
||||
using VecHandle = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>>;
|
||||
IdHandle PointIds;
|
||||
FloatHandle Sizes;
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
|
||||
public:
|
||||
GlyphLeafWrapper(IdHandle& pointIds, FloatHandle sizes, vtkm::rendering::GlyphType glyphType)
|
||||
: PointIds(pointIds)
|
||||
, Sizes(sizes)
|
||||
, GlyphType(glyphType)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT GlyphLeafIntersector<Device> PrepareForExecution(Device, vtkm::cont::Token& token) const
|
||||
{
|
||||
return GlyphLeafIntersector<Device>(this->PointIds, this->Sizes, this->GlyphType, token);
|
||||
}
|
||||
}; // class GlyphLeafWrapper
|
||||
|
||||
class CalculateGlyphNormals : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CalculateGlyphNormals(vtkm::rendering::GlyphType glyphType)
|
||||
: GlyphType(glyphType)
|
||||
{
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn,
|
||||
FieldIn,
|
||||
FieldIn,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
WholeArrayIn,
|
||||
WholeArrayIn,
|
||||
WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8, _9);
|
||||
|
||||
template <typename Precision,
|
||||
typename PointPortalType,
|
||||
typename IndicesPortalType,
|
||||
typename SizesPortalType>
|
||||
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
|
||||
const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& intersection,
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ,
|
||||
const PointPortalType& points,
|
||||
const IndicesPortalType& indicesPortal,
|
||||
const SizesPortalType& sizesPortal) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Id pointId = indicesPortal.Get(hitIndex);
|
||||
vtkm::Vec<Precision, 3> point = points.Get(pointId);
|
||||
Precision size = sizesPortal.Get(hitIndex);
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Sphere)
|
||||
{
|
||||
this->CalculateNormalForSphere(rayDir, intersection, point, size, normalX, normalY, normalZ);
|
||||
}
|
||||
else if (this->GlyphType == vtkm::rendering::GlyphType::Cube)
|
||||
{
|
||||
this->CalculateNormalForCube(rayDir, intersection, point, size, normalX, normalY, normalZ);
|
||||
}
|
||||
else if (this->GlyphType == vtkm::rendering::GlyphType::Axes)
|
||||
{
|
||||
this->CalculateNormalForAxes(rayDir, intersection, point, size, normalX, normalY, normalZ);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void CalculateNormalForSphere(const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& intersection,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& vtkmNotUsed(size),
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> normal = intersection - point;
|
||||
vtkm::Normalize(normal);
|
||||
|
||||
// Flip normal if it is pointing the wrong way
|
||||
if (vtkm::Dot(normal, rayDir) > 0.0f)
|
||||
{
|
||||
normal = -normal;
|
||||
}
|
||||
|
||||
normalX = normal[0];
|
||||
normalY = normal[1];
|
||||
normalZ = normal[2];
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void CalculateNormalForCube(const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& intersection,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& size,
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> lp = intersection - point;
|
||||
|
||||
// Localize the intersection point to the surface of the cube.
|
||||
// One of the components will be 1 or -1 based on the face it lies on
|
||||
lp = lp * (1.0f / size);
|
||||
|
||||
Precision eps = 1e-4f;
|
||||
vtkm::Vec<Precision, 3> normal{ 0.0f, 0.0f, 0.0f };
|
||||
normal[0] = (vtkm::Abs(vtkm::Abs(lp[0]) - 1.0f) <= eps) ? lp[0] : 0.0f;
|
||||
normal[1] = (vtkm::Abs(vtkm::Abs(lp[1]) - 1.0f) <= eps) ? lp[1] : 0.0f;
|
||||
normal[2] = (vtkm::Abs(vtkm::Abs(lp[2]) - 1.0f) <= eps) ? lp[2] : 0.0f;
|
||||
vtkm::Normalize(normal);
|
||||
|
||||
// Flip normal if it is pointing the wrong way
|
||||
if (vtkm::Dot(normal, rayDir) > 0.0f)
|
||||
{
|
||||
normal = -normal;
|
||||
}
|
||||
|
||||
normalX = normal[0];
|
||||
normalY = normal[1];
|
||||
normalZ = normal[2];
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void CalculateNormalForAxes(const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& intersection,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const Precision& vtkmNotUsed(size),
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> normal{ 0.0f, 0.0f, 0.0f };
|
||||
|
||||
if (this->ApproxEquals(point[0], intersection[0]))
|
||||
{
|
||||
normal[0] = 1.0f;
|
||||
}
|
||||
else if (this->ApproxEquals(point[1], intersection[1]))
|
||||
{
|
||||
normal[1] = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
normal[2] = 1.0f;
|
||||
}
|
||||
|
||||
// Flip normal if it is pointing the wrong way
|
||||
if (vtkm::Dot(normal, rayDir) > 0.0f)
|
||||
{
|
||||
normal = -normal;
|
||||
}
|
||||
|
||||
normalX = normal[0];
|
||||
normalY = normal[1];
|
||||
normalZ = normal[2];
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline Precision ApproxEquals(Precision x, Precision y, Precision eps = 1e-5f) const
|
||||
{
|
||||
return vtkm::Abs(x - y) <= eps;
|
||||
}
|
||||
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
}; //class CalculateGlyphNormals
|
||||
|
||||
template <typename Precision>
|
||||
class GetScalars : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
Precision MinScalar;
|
||||
Precision InvDeltaScalar;
|
||||
bool Normalize;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GetScalars(const vtkm::Float32& minScalar, const vtkm::Float32& maxScalar)
|
||||
: MinScalar(minScalar)
|
||||
{
|
||||
Normalize = true;
|
||||
if (minScalar >= maxScalar)
|
||||
{
|
||||
// support the scalar renderer
|
||||
Normalize = false;
|
||||
this->InvDeltaScalar = Precision(0.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Make sure the we don't divide by zero on
|
||||
//something like an iso-surface
|
||||
this->InvDeltaScalar = 1.f / (maxScalar - this->MinScalar);
|
||||
}
|
||||
}
|
||||
typedef void ControlSignature(FieldIn, FieldOut, WholeArrayIn, WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4);
|
||||
template <typename ScalarPortalType, typename IndicesPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
|
||||
Precision& scalar,
|
||||
const ScalarPortalType& scalars,
|
||||
const IndicesPortalType& indicesPortal) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Id pointId = indicesPortal.Get(hitIndex);
|
||||
|
||||
scalar = Precision(scalars.Get(pointId));
|
||||
if (Normalize)
|
||||
{
|
||||
scalar = (scalar - this->MinScalar) * this->InvDeltaScalar;
|
||||
}
|
||||
}
|
||||
}; //class GetScalars
|
||||
}
|
||||
|
||||
GlyphIntersector::GlyphIntersector(vtkm::rendering::GlyphType glyphType)
|
||||
: ShapeIntersector()
|
||||
{
|
||||
this->SetGlyphType(glyphType);
|
||||
}
|
||||
|
||||
GlyphIntersector::~GlyphIntersector() {}
|
||||
|
||||
void GlyphIntersector::SetGlyphType(vtkm::rendering::GlyphType glyphType)
|
||||
{
|
||||
this->GlyphType = glyphType;
|
||||
}
|
||||
|
||||
void GlyphIntersector::SetData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> sizes)
|
||||
{
|
||||
this->PointIds = pointIds;
|
||||
this->Sizes = sizes;
|
||||
this->CoordsHandle = coords;
|
||||
AABBs AABB;
|
||||
vtkm::worklet::DispatcherMapField<detail::FindGlyphAABBs>(detail::FindGlyphAABBs())
|
||||
.Invoke(PointIds,
|
||||
Sizes,
|
||||
AABB.xmins,
|
||||
AABB.ymins,
|
||||
AABB.zmins,
|
||||
AABB.xmaxs,
|
||||
AABB.ymaxs,
|
||||
AABB.zmaxs,
|
||||
CoordsHandle);
|
||||
|
||||
this->SetAABBs(AABB);
|
||||
}
|
||||
|
||||
void GlyphIntersector::IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex)
|
||||
{
|
||||
IntersectRaysImp(rays, returnCellIndex);
|
||||
}
|
||||
|
||||
void GlyphIntersector::IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex)
|
||||
{
|
||||
IntersectRaysImp(rays, returnCellIndex);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void GlyphIntersector::IntersectRaysImp(Ray<Precision>& rays, bool vtkmNotUsed(returnCellIndex))
|
||||
{
|
||||
detail::GlyphLeafWrapper leafIntersector(this->PointIds, Sizes, this->GlyphType);
|
||||
|
||||
BVHTraverser traverser;
|
||||
traverser.IntersectRays(rays, this->BVH, leafIntersector, this->CoordsHandle);
|
||||
|
||||
RayOperations::UpdateRayStatus(rays);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void GlyphIntersector::IntersectionDataImp(Ray<Precision>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
ShapeIntersector::IntersectionPoint(rays);
|
||||
|
||||
const bool isSupportedField = scalarField.IsFieldCell() || scalarField.IsFieldPoint();
|
||||
if (!isSupportedField)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"GlyphIntersector: Field not accociated with a cell set or field");
|
||||
}
|
||||
|
||||
vtkm::worklet::DispatcherMapField<detail::CalculateGlyphNormals>(
|
||||
detail::CalculateGlyphNormals(this->GlyphType))
|
||||
.Invoke(rays.HitIdx,
|
||||
rays.Dir,
|
||||
rays.Intersection,
|
||||
rays.NormalX,
|
||||
rays.NormalY,
|
||||
rays.NormalZ,
|
||||
CoordsHandle,
|
||||
PointIds,
|
||||
Sizes);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<detail::GetScalars<Precision>>(
|
||||
detail::GetScalars<Precision>(vtkm::Float32(scalarRange.Min), vtkm::Float32(scalarRange.Max)))
|
||||
.Invoke(rays.HitIdx,
|
||||
rays.Scalar,
|
||||
vtkm::rendering::raytracing::GetScalarFieldArray(scalarField),
|
||||
PointIds);
|
||||
}
|
||||
|
||||
void GlyphIntersector::IntersectionData(Ray<vtkm::Float32>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
IntersectionDataImp(rays, scalarField, scalarRange);
|
||||
}
|
||||
|
||||
void GlyphIntersector::IntersectionData(Ray<vtkm::Float64>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange)
|
||||
{
|
||||
IntersectionDataImp(rays, scalarField, scalarRange);
|
||||
}
|
||||
|
||||
vtkm::Id GlyphIntersector::GetNumberOfShapes() const
|
||||
{
|
||||
return PointIds.GetNumberOfValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
69
vtkm/rendering/raytracing/GlyphIntersector.h
Normal file
69
vtkm/rendering/raytracing/GlyphIntersector.h
Normal file
@ -0,0 +1,69 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Glyph_Intersector_h
|
||||
#define vtk_m_rendering_raytracing_Glyph_Intersector_h
|
||||
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/raytracing/ShapeIntersector.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class GlyphIntersector : public ShapeIntersector
|
||||
{
|
||||
public:
|
||||
GlyphIntersector(vtkm::rendering::GlyphType glyphType);
|
||||
virtual ~GlyphIntersector() override;
|
||||
|
||||
void SetGlyphType(vtkm::rendering::GlyphType glyphType);
|
||||
|
||||
void SetData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> sizes);
|
||||
|
||||
void IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex = false) override;
|
||||
|
||||
|
||||
void IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex = false) override;
|
||||
|
||||
template <typename Precision>
|
||||
void IntersectRaysImp(Ray<Precision>& rays, bool returnCellIndex);
|
||||
|
||||
|
||||
template <typename Precision>
|
||||
void IntersectionDataImp(Ray<Precision>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange);
|
||||
|
||||
void IntersectionData(Ray<vtkm::Float32>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange) override;
|
||||
|
||||
void IntersectionData(Ray<vtkm::Float64>& rays,
|
||||
const vtkm::cont::Field scalarField,
|
||||
const vtkm::Range& scalarRange) override;
|
||||
|
||||
vtkm::Id GetNumberOfShapes() const override;
|
||||
|
||||
protected:
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> Sizes;
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
|
||||
}; // class GlyphIntersector
|
||||
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif //vtk_m_rendering_raytracing_Glyph_Intersector_h
|
721
vtkm/rendering/raytracing/GlyphIntersectorVector.cxx
Normal file
721
vtkm/rendering/raytracing/GlyphIntersectorVector.cxx
Normal file
@ -0,0 +1,721 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/rendering/raytracing/BVHTraverser.h>
|
||||
#include <vtkm/rendering/raytracing/GlyphIntersectorVector.h>
|
||||
#include <vtkm/rendering/raytracing/RayOperations.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
|
||||
// This line is at the end to prevent warnings when building for CUDA
|
||||
#include <vtkm/Swap.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
static constexpr vtkm::Float32 ARROW_BODY_SIZE = 0.75f;
|
||||
|
||||
class FindGlyphVectorAABBs : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
vtkm::Float32 ArrowBodyRadius;
|
||||
vtkm::Float32 ArrowHeadRadius;
|
||||
|
||||
public:
|
||||
using ControlSignature = void(FieldIn,
|
||||
FieldIn,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
WholeArrayIn);
|
||||
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6, _7, _8, _9);
|
||||
|
||||
VTKM_CONT
|
||||
FindGlyphVectorAABBs(vtkm::rendering::GlyphType glyphType,
|
||||
vtkm::Float32 bodyRadius,
|
||||
vtkm::Float32 headRadius)
|
||||
: GlyphType(glyphType)
|
||||
, ArrowBodyRadius(bodyRadius)
|
||||
, ArrowHeadRadius(headRadius)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename PointPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& pointId,
|
||||
const vtkm::Vec3f_32& size,
|
||||
vtkm::Float32& xmin,
|
||||
vtkm::Float32& ymin,
|
||||
vtkm::Float32& zmin,
|
||||
vtkm::Float32& xmax,
|
||||
vtkm::Float32& ymax,
|
||||
vtkm::Float32& zmax,
|
||||
const PointPortalType& points) const
|
||||
{
|
||||
vtkm::Vec3f_32 point = static_cast<vtkm::Vec3f_32>(points.Get(pointId));
|
||||
xmin = point[0];
|
||||
xmax = point[0];
|
||||
ymin = point[1];
|
||||
ymax = point[1];
|
||||
zmin = point[2];
|
||||
zmax = point[2];
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Arrow)
|
||||
{
|
||||
this->CalculateArrowAABB(point, size, xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
}
|
||||
}
|
||||
|
||||
VTKM_EXEC inline void CalculateArrowAABB(const vtkm::Vec3f_32& point,
|
||||
const vtkm::Vec3f_32& size,
|
||||
vtkm::Float32& xmin,
|
||||
vtkm::Float32& ymin,
|
||||
vtkm::Float32& zmin,
|
||||
vtkm::Float32& xmax,
|
||||
vtkm::Float32& ymax,
|
||||
vtkm::Float32& zmax) const
|
||||
{
|
||||
vtkm::Vec3f_32 body_pa = point;
|
||||
vtkm::Vec3f_32 body_pb = body_pa + ARROW_BODY_SIZE * size;
|
||||
vtkm::Vec3f_32 head_pa = body_pb;
|
||||
vtkm::Vec3f_32 head_pb = point + size;
|
||||
|
||||
this->CylinderAABB(body_pa, body_pb, this->ArrowBodyRadius, xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
this->ConeAABB(
|
||||
head_pa, head_pb, this->ArrowHeadRadius, 0.0f, xmin, ymin, zmin, xmax, ymax, zmax);
|
||||
}
|
||||
|
||||
VTKM_EXEC inline void CylinderAABB(const vtkm::Vec3f_32& pa,
|
||||
const vtkm::Vec3f_32& pb,
|
||||
const vtkm::Float32& ra,
|
||||
vtkm::Float32& xmin,
|
||||
vtkm::Float32& ymin,
|
||||
vtkm::Float32& zmin,
|
||||
vtkm::Float32& xmax,
|
||||
vtkm::Float32& ymax,
|
||||
vtkm::Float32& zmax) const
|
||||
{
|
||||
vtkm::Vec3f_32 a = pb - pa;
|
||||
vtkm::Vec3f_32 e_prime = a * a / vtkm::Dot(a, a);
|
||||
vtkm::Vec3f_32 e = ra * vtkm::Sqrt(1.0f - e_prime);
|
||||
|
||||
vtkm::Vec3f_32 pa1 = pa - e;
|
||||
vtkm::Vec3f_32 pa2 = pa + e;
|
||||
vtkm::Vec3f_32 pb1 = pb - e;
|
||||
vtkm::Vec3f_32 pb2 = pb + e;
|
||||
|
||||
xmin = vtkm::Min(xmin, vtkm::Min(pa1[0], pb1[0]));
|
||||
ymin = vtkm::Min(ymin, vtkm::Min(pa1[1], pb1[1]));
|
||||
zmin = vtkm::Min(zmin, vtkm::Min(pa1[2], pb1[2]));
|
||||
xmax = vtkm::Max(xmax, vtkm::Max(pa2[0], pb2[0]));
|
||||
ymax = vtkm::Max(ymax, vtkm::Max(pa2[1], pb2[1]));
|
||||
zmax = vtkm::Max(zmax, vtkm::Max(pa2[2], pb2[2]));
|
||||
}
|
||||
|
||||
VTKM_EXEC inline void ConeAABB(const vtkm::Vec3f_32& pa,
|
||||
const vtkm::Vec3f_32& pb,
|
||||
const vtkm::Float32& ra,
|
||||
const vtkm::Float32& rb,
|
||||
vtkm::Float32& xmin,
|
||||
vtkm::Float32& ymin,
|
||||
vtkm::Float32& zmin,
|
||||
vtkm::Float32& xmax,
|
||||
vtkm::Float32& ymax,
|
||||
vtkm::Float32& zmax) const
|
||||
{
|
||||
vtkm::Vec3f_32 a = pb - pa;
|
||||
vtkm::Vec3f_32 e_prime = a * a / vtkm::Dot(a, a);
|
||||
vtkm::Vec3f_32 e = vtkm::Sqrt(1.0f - e_prime);
|
||||
|
||||
vtkm::Vec3f_32 pa1 = pa - e * ra;
|
||||
vtkm::Vec3f_32 pa2 = pa + e * ra;
|
||||
vtkm::Vec3f_32 pb1 = pb - e * rb;
|
||||
vtkm::Vec3f_32 pb2 = pb + e * rb;
|
||||
|
||||
xmin = vtkm::Min(xmin, vtkm::Min(pa1[0], pb1[0]));
|
||||
ymin = vtkm::Min(ymin, vtkm::Min(pa1[1], pb1[1]));
|
||||
zmin = vtkm::Min(zmin, vtkm::Min(pa1[2], pb1[2]));
|
||||
xmax = vtkm::Max(xmax, vtkm::Max(pa2[0], pb2[0]));
|
||||
ymax = vtkm::Max(ymax, vtkm::Max(pa2[1], pb2[1]));
|
||||
zmax = vtkm::Max(zmax, vtkm::Max(pa2[2], pb2[2]));
|
||||
}
|
||||
}; //class FindGlyphVectorAABBs
|
||||
|
||||
template <typename Device>
|
||||
class GlyphVectorLeafIntersector
|
||||
{
|
||||
public:
|
||||
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using IdArrayPortal = typename IdHandle::ReadPortalType;
|
||||
using Vec3f_32Handle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
|
||||
using Vec3f_32Portal = typename Vec3f_32Handle::ReadPortalType;
|
||||
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
IdArrayPortal PointIds;
|
||||
Vec3f_32Portal Sizes;
|
||||
vtkm::Float32 ArrowBodyRadius;
|
||||
vtkm::Float32 ArrowHeadRadius;
|
||||
|
||||
GlyphVectorLeafIntersector() = default;
|
||||
|
||||
GlyphVectorLeafIntersector(vtkm::rendering::GlyphType glyphType,
|
||||
const IdHandle& pointIds,
|
||||
const Vec3f_32Handle& sizes,
|
||||
vtkm::Float32 bodyRadius,
|
||||
vtkm::Float32 headRadius,
|
||||
vtkm::cont::Token& token)
|
||||
: GlyphType(glyphType)
|
||||
, PointIds(pointIds.PrepareForInput(Device(), token))
|
||||
, Sizes(sizes.PrepareForInput(Device(), token))
|
||||
, ArrowBodyRadius(bodyRadius)
|
||||
, ArrowHeadRadius(headRadius)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename PointPortalType, typename LeafPortalType, typename Precision>
|
||||
VTKM_EXEC inline void IntersectLeaf(const vtkm::Int32& currentNode,
|
||||
const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const PointPortalType& points,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& minU,
|
||||
Precision& minV,
|
||||
LeafPortalType leafs,
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
const vtkm::Id glyphCount = leafs.Get(currentNode);
|
||||
|
||||
for (vtkm::Id i = 1; i <= glyphCount; ++i)
|
||||
{
|
||||
const vtkm::Id idx = leafs.Get(currentNode + i);
|
||||
vtkm::Id pointIndex = PointIds.Get(idx);
|
||||
vtkm::Vec<Precision, 3> size = Sizes.Get(idx);
|
||||
vtkm::Vec<Precision, 3> point = vtkm::Vec<Precision, 3>(points.Get(pointIndex));
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Arrow)
|
||||
{
|
||||
this->IntersectArrow(
|
||||
origin, dir, point, size, pointIndex, hitIndex, closestDistance, minU, minV, minDistance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void IntersectArrow(const vtkm::Vec<Precision, 3>& origin,
|
||||
const vtkm::Vec<Precision, 3>& dir,
|
||||
const vtkm::Vec<Precision, 3>& point,
|
||||
const vtkm::Vec<Precision, 3>& size,
|
||||
const vtkm::Id& pointIndex,
|
||||
vtkm::Id& hitIndex,
|
||||
Precision& closestDistance,
|
||||
Precision& minU,
|
||||
Precision& minV,
|
||||
const Precision& minDistance) const
|
||||
{
|
||||
using Vec2 = vtkm::Vec<Precision, 2>;
|
||||
using Vec3 = vtkm::Vec<Precision, 3>;
|
||||
using Vec4 = vtkm::Vec<Precision, 4>;
|
||||
|
||||
Vec3 body_pa = point;
|
||||
Vec3 body_pb = body_pa + ARROW_BODY_SIZE * size;
|
||||
Vec3 head_pa = body_pb;
|
||||
Vec3 head_pb = point + size;
|
||||
|
||||
Vec4 bodyIntersection =
|
||||
this->IntersectCylinder(origin, dir, body_pa, body_pb, Precision(this->ArrowBodyRadius));
|
||||
Vec4 headIntersection = this->IntersectCone(
|
||||
origin, dir, head_pa, head_pb, Precision(this->ArrowHeadRadius), Precision(0.0f));
|
||||
|
||||
bool bodyHit = bodyIntersection[0] >= minDistance;
|
||||
bool headHit = headIntersection[0] >= minDistance;
|
||||
if (bodyHit && !headHit)
|
||||
{
|
||||
Precision t = bodyIntersection[0];
|
||||
if (t < closestDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
minU = bodyIntersection[1];
|
||||
minV = bodyIntersection[2];
|
||||
}
|
||||
}
|
||||
else if (!bodyHit && headHit)
|
||||
{
|
||||
Precision t = headIntersection[0];
|
||||
if (t < closestDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
minU = headIntersection[1];
|
||||
minV = headIntersection[2];
|
||||
}
|
||||
}
|
||||
else if (bodyHit || headHit)
|
||||
{
|
||||
Precision t1 = bodyIntersection[0];
|
||||
Precision t2 = headIntersection[0];
|
||||
|
||||
Precision t = t1;
|
||||
Vec2 partialNormal = { bodyIntersection[1], bodyIntersection[2] };
|
||||
if (t2 < t)
|
||||
{
|
||||
t = t2;
|
||||
partialNormal[0] = headIntersection[1];
|
||||
partialNormal[1] = headIntersection[2];
|
||||
}
|
||||
|
||||
if (t < closestDistance)
|
||||
{
|
||||
hitIndex = pointIndex;
|
||||
closestDistance = t;
|
||||
minU = partialNormal[0];
|
||||
minV = partialNormal[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC vtkm::Vec4f_32 IntersectCylinder(const vtkm::Vec<Precision, 3>& ro,
|
||||
const vtkm::Vec<Precision, 3>& rd,
|
||||
const vtkm::Vec<Precision, 3>& pa,
|
||||
const vtkm::Vec<Precision, 3>& pb,
|
||||
const Precision& ra) const
|
||||
{
|
||||
using Vec3 = vtkm::Vec<Precision, 3>;
|
||||
using Vec4 = vtkm::Vec<Precision, 4>;
|
||||
|
||||
const Vec4 NO_HIT{ -1.0f, -1.0f, -1.0f, -1.0f };
|
||||
|
||||
Vec3 cc = 0.5f * (pa + pb);
|
||||
Precision ch = vtkm::Magnitude(pb - pa);
|
||||
Vec3 ca = (pb - pa) / ch;
|
||||
ch *= 0.5f;
|
||||
|
||||
Vec3 oc = ro - cc;
|
||||
|
||||
Precision card = vtkm::Dot(ca, rd);
|
||||
Precision caoc = vtkm::Dot(ca, oc);
|
||||
|
||||
Precision a = 1.0f - card * card;
|
||||
Precision b = vtkm::Dot(oc, rd) - caoc * card;
|
||||
Precision c = vtkm::Dot(oc, oc) - caoc * caoc - ra * ra;
|
||||
Precision h = b * b - a * c;
|
||||
if (h < 0.0f)
|
||||
{
|
||||
return NO_HIT;
|
||||
}
|
||||
|
||||
h = vtkm::Sqrt(h);
|
||||
Precision t1 = (-b - h) / a;
|
||||
/* Precision t2 = (-b + h) / a; // exit point */
|
||||
|
||||
Precision y = caoc + t1 * card;
|
||||
|
||||
// body
|
||||
if (vtkm::Abs(y) < ch)
|
||||
{
|
||||
vtkm::Vec3f_32 normal = vtkm::Normal(oc + t1 * rd - ca * y);
|
||||
return vtkm::Vec4f_32(static_cast<vtkm::Float32>(t1), normal[0], normal[1], normal[2]);
|
||||
}
|
||||
|
||||
// bottom cap
|
||||
Precision sy = -1;
|
||||
Precision tp = (sy * ch - caoc) / card;
|
||||
if (vtkm::Abs(b + a * tp) < h)
|
||||
{
|
||||
vtkm::Vec3f_32 normal = vtkm::Normal(ca * sy);
|
||||
return vtkm::Vec4f_32(static_cast<vtkm::Float32>(tp), normal[0], normal[1], normal[2]);
|
||||
}
|
||||
|
||||
// top cap
|
||||
sy = 1;
|
||||
tp = (sy * ch - caoc) / card;
|
||||
if (vtkm::Abs(b + a * tp) < h)
|
||||
{
|
||||
vtkm::Vec3f_32 normal = vtkm::Normal(ca * sy);
|
||||
return vtkm::Vec4f_32(static_cast<vtkm::Float32>(tp), normal[0], normal[1], normal[2]);
|
||||
}
|
||||
|
||||
return NO_HIT;
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC vtkm::Vec4f_32 IntersectCone(const vtkm::Vec<Precision, 3>& ro,
|
||||
const vtkm::Vec<Precision, 3>& rd,
|
||||
const vtkm::Vec<Precision, 3>& pa,
|
||||
const vtkm::Vec<Precision, 3>& pb,
|
||||
const Precision& ra,
|
||||
const Precision& rb) const
|
||||
{
|
||||
using Vec3 = vtkm::Vec<Precision, 3>;
|
||||
using Vec4 = vtkm::Vec<Precision, 4>;
|
||||
|
||||
const Vec4 NO_HIT{ -1.0f, -1.0f, -1.0f, -1.0f };
|
||||
|
||||
Vec3 ba = pb - pa;
|
||||
Vec3 oa = ro - pa;
|
||||
Vec3 ob = ro - pb;
|
||||
|
||||
Precision m0 = vtkm::Dot(ba, ba);
|
||||
Precision m1 = vtkm::Dot(oa, ba);
|
||||
Precision m2 = vtkm::Dot(ob, ba);
|
||||
Precision m3 = vtkm::Dot(rd, ba);
|
||||
|
||||
//caps
|
||||
if (m1 < 0.0)
|
||||
{
|
||||
Vec3 m11 = oa * m3 - rd * m1;
|
||||
Precision m12 = ra * ra * m3 * m3;
|
||||
if (vtkm::Dot(m11, m11) < m12)
|
||||
{
|
||||
Precision t = -m1 / m3;
|
||||
Vec3 normal = -ba * 1.0f / vtkm::Sqrt(m0);
|
||||
return Vec4(t, normal[0], normal[1], normal[2]);
|
||||
}
|
||||
}
|
||||
else if (m2 > 0.0)
|
||||
{
|
||||
Vec3 m21 = ob * m3 - rd * m2;
|
||||
Precision m22 = rb * rb * m3 * m3;
|
||||
if (vtkm::Dot(m21, m21) < m22)
|
||||
{
|
||||
Precision t = -m2 / m3;
|
||||
Vec3 normal = ba * 1.0f / vtkm::Sqrt(m0);
|
||||
return Vec4(t, normal[0], normal[1], normal[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
Precision rr = ra - rb;
|
||||
Precision hy = m0 + rr * rr;
|
||||
Precision m4 = vtkm::Dot(rd, oa);
|
||||
Precision m5 = vtkm::Dot(oa, oa);
|
||||
|
||||
Precision k2 = m0 * m0 - m3 * m3 * hy;
|
||||
Precision k1 = m0 * m0 * m4 - m1 * m3 * hy + m0 * ra * (rr * m3 * 1.0f);
|
||||
Precision k0 = m0 * m0 * m5 - m1 * m1 * hy + m0 * ra * (rr * m1 * 2.0f - m0 * ra);
|
||||
|
||||
Precision h = k1 * k1 - k2 * k0;
|
||||
if (h < 0.0)
|
||||
{
|
||||
return NO_HIT;
|
||||
}
|
||||
|
||||
Precision t = (-k1 - sqrt(h)) / k2;
|
||||
Precision y = m1 + t * m3;
|
||||
|
||||
if (y > 0.0 && y < m0)
|
||||
{
|
||||
Vec3 normal = vtkm::Normal(m0 * (m0 * (oa + t * rd) + rr * ba * ra) - ba * hy * y);
|
||||
return Vec4(t, normal[0], normal[1], normal[2]);
|
||||
}
|
||||
|
||||
return NO_HIT;
|
||||
}
|
||||
};
|
||||
|
||||
class GlyphVectorLeafWrapper : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
protected:
|
||||
using IdHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using Vec3f_32Handle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
IdHandle PointIds;
|
||||
Vec3f_32Handle Sizes;
|
||||
vtkm::Float32 ArrowBodyRadius;
|
||||
vtkm::Float32 ArrowHeadRadius;
|
||||
|
||||
public:
|
||||
GlyphVectorLeafWrapper(vtkm::rendering::GlyphType glyphType,
|
||||
IdHandle& pointIds,
|
||||
Vec3f_32Handle& sizes,
|
||||
vtkm::Float32 bodyRadius,
|
||||
vtkm::Float32 headRadius)
|
||||
: GlyphType(glyphType)
|
||||
, PointIds(pointIds)
|
||||
, Sizes(sizes)
|
||||
, ArrowBodyRadius(bodyRadius)
|
||||
, ArrowHeadRadius(headRadius)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Device>
|
||||
VTKM_CONT GlyphVectorLeafIntersector<Device> PrepareForExecution(Device,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
return GlyphVectorLeafIntersector<Device>(this->GlyphType,
|
||||
this->PointIds,
|
||||
this->Sizes,
|
||||
this->ArrowBodyRadius,
|
||||
this->ArrowHeadRadius,
|
||||
token);
|
||||
}
|
||||
};
|
||||
|
||||
class CalculateGlyphVectorNormals : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CalculateGlyphVectorNormals(vtkm::rendering::GlyphType glyphType)
|
||||
: GlyphType(glyphType)
|
||||
{
|
||||
}
|
||||
|
||||
typedef void ControlSignature(FieldIn,
|
||||
FieldIn,
|
||||
FieldIn,
|
||||
FieldIn,
|
||||
FieldIn,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
FieldOut,
|
||||
WholeArrayIn,
|
||||
WholeArrayIn,
|
||||
WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11);
|
||||
|
||||
template <typename Precision,
|
||||
typename PointPortalType,
|
||||
typename IndicesPortalType,
|
||||
typename SizesPortalType>
|
||||
VTKM_EXEC inline void operator()(const vtkm::Id& hitIndex,
|
||||
const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& intersection,
|
||||
const Precision& u,
|
||||
const Precision& v,
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ,
|
||||
const PointPortalType& vtkmNotUsed(points),
|
||||
const IndicesPortalType& vtkmNotUsed(indicesPortal),
|
||||
const SizesPortalType& vtkmNotUsed(sizesPortal)) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
if (this->GlyphType == vtkm::rendering::GlyphType::Arrow)
|
||||
{
|
||||
this->CalculateArrowNormal(rayDir, intersection, u, v, normalX, normalY, normalZ);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
VTKM_EXEC inline void CalculateArrowNormal(
|
||||
const vtkm::Vec<Precision, 3>& rayDir,
|
||||
const vtkm::Vec<Precision, 3>& vtkmNotUsed(intersection),
|
||||
const Precision& u,
|
||||
const Precision& v,
|
||||
Precision& normalX,
|
||||
Precision& normalY,
|
||||
Precision& normalZ) const
|
||||
{
|
||||
vtkm::Vec<Precision, 3> normal;
|
||||
normal[0] = u;
|
||||
normal[1] = v;
|
||||
normal[2] = 1.0f - (normalX * normalX) - (normalY * normalY);
|
||||
|
||||
if (vtkm::Dot(normal, rayDir) > 0.0f)
|
||||
{
|
||||
normal = -normal;
|
||||
}
|
||||
|
||||
normalX = normal[0];
|
||||
normalY = normal[1];
|
||||
normalZ = normal[2];
|
||||
}
|
||||
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
}; //class CalculateGlyphVectorNormals
|
||||
|
||||
template <typename Precision>
|
||||
class GetScalars : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
private:
|
||||
Precision MinScalar;
|
||||
Precision InvDeltaScalar;
|
||||
bool Normalize;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
GetScalars(const vtkm::Float32& minScalar, const vtkm::Float32& maxScalar)
|
||||
: MinScalar(minScalar)
|
||||
{
|
||||
Normalize = true;
|
||||
if (minScalar >= maxScalar)
|
||||
{
|
||||
// support the scalar renderer
|
||||
Normalize = false;
|
||||
this->InvDeltaScalar = Precision(0.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Make sure the we don't divide by zero on
|
||||
//something like an iso-surface
|
||||
this->InvDeltaScalar = 1.f / (maxScalar - this->MinScalar);
|
||||
}
|
||||
}
|
||||
typedef void ControlSignature(FieldIn, FieldOut, WholeArrayIn, WholeArrayIn);
|
||||
typedef void ExecutionSignature(_1, _2, _3, _4);
|
||||
template <typename FieldPortalType, typename IndicesPortalType>
|
||||
VTKM_EXEC void operator()(const vtkm::Id& hitIndex,
|
||||
Precision& scalar,
|
||||
const FieldPortalType& scalars,
|
||||
const IndicesPortalType& indicesPortal) const
|
||||
{
|
||||
if (hitIndex < 0)
|
||||
return;
|
||||
|
||||
vtkm::Id pointId = indicesPortal.Get(hitIndex);
|
||||
|
||||
scalar = Precision(scalars.Get(pointId));
|
||||
if (Normalize)
|
||||
{
|
||||
scalar = (scalar - this->MinScalar) * this->InvDeltaScalar;
|
||||
}
|
||||
}
|
||||
}; //class GetScalar
|
||||
|
||||
} // namespace
|
||||
|
||||
GlyphIntersectorVector::GlyphIntersectorVector(vtkm::rendering::GlyphType glyphType)
|
||||
: ShapeIntersector()
|
||||
, ArrowBodyRadius(0.004f)
|
||||
, ArrowHeadRadius(0.008f)
|
||||
{
|
||||
this->SetGlyphType(glyphType);
|
||||
}
|
||||
|
||||
GlyphIntersectorVector::~GlyphIntersectorVector() {}
|
||||
|
||||
void GlyphIntersectorVector::SetGlyphType(vtkm::rendering::GlyphType glyphType)
|
||||
{
|
||||
this->GlyphType = glyphType;
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::SetData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> sizes)
|
||||
{
|
||||
this->PointIds = pointIds;
|
||||
this->Sizes = sizes;
|
||||
this->CoordsHandle = coords;
|
||||
AABBs AABB;
|
||||
vtkm::cont::Invoker invoker;
|
||||
invoker(
|
||||
detail::FindGlyphVectorAABBs{ this->GlyphType, this->ArrowBodyRadius, this->ArrowHeadRadius },
|
||||
PointIds,
|
||||
Sizes,
|
||||
AABB.xmins,
|
||||
AABB.ymins,
|
||||
AABB.zmins,
|
||||
AABB.xmaxs,
|
||||
AABB.ymaxs,
|
||||
AABB.zmaxs,
|
||||
CoordsHandle);
|
||||
|
||||
this->SetAABBs(AABB);
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex)
|
||||
{
|
||||
IntersectRaysImp(rays, returnCellIndex);
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex)
|
||||
{
|
||||
IntersectRaysImp(rays, returnCellIndex);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void GlyphIntersectorVector::IntersectRaysImp(Ray<Precision>& rays,
|
||||
bool vtkmNotUsed(returnCellIndex))
|
||||
{
|
||||
detail::GlyphVectorLeafWrapper leafIntersector(
|
||||
this->GlyphType, this->PointIds, this->Sizes, this->ArrowBodyRadius, this->ArrowHeadRadius);
|
||||
|
||||
BVHTraverser traverser;
|
||||
traverser.IntersectRays(rays, this->BVH, leafIntersector, this->CoordsHandle);
|
||||
|
||||
RayOperations::UpdateRayStatus(rays);
|
||||
}
|
||||
|
||||
template <typename Precision>
|
||||
void GlyphIntersectorVector::IntersectionDataImp(Ray<Precision>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range)
|
||||
{
|
||||
ShapeIntersector::IntersectionPoint(rays);
|
||||
|
||||
const bool isSupportedField = field.IsFieldCell() || field.IsFieldPoint();
|
||||
if (!isSupportedField)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadValue(
|
||||
"GlyphIntersectorVector: Field not accociated with a cell set or field");
|
||||
}
|
||||
|
||||
vtkm::worklet::DispatcherMapField<detail::CalculateGlyphVectorNormals>(
|
||||
detail::CalculateGlyphVectorNormals(this->GlyphType))
|
||||
.Invoke(rays.HitIdx,
|
||||
rays.Dir,
|
||||
rays.Intersection,
|
||||
rays.U,
|
||||
rays.V,
|
||||
rays.NormalX,
|
||||
rays.NormalY,
|
||||
rays.NormalZ,
|
||||
CoordsHandle,
|
||||
PointIds,
|
||||
Sizes);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<detail::GetScalars<Precision>>(
|
||||
detail::GetScalars<Precision>(vtkm::Float32(range.Min), vtkm::Float32(range.Max)))
|
||||
.Invoke(
|
||||
rays.HitIdx, rays.Scalar, vtkm::rendering::raytracing::GetScalarFieldArray(field), PointIds);
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::IntersectionData(Ray<vtkm::Float32>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range)
|
||||
{
|
||||
IntersectionDataImp(rays, field, range);
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::IntersectionData(Ray<vtkm::Float64>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range)
|
||||
{
|
||||
IntersectionDataImp(rays, field, range);
|
||||
}
|
||||
|
||||
vtkm::Id GlyphIntersectorVector::GetNumberOfShapes() const
|
||||
{
|
||||
return PointIds.GetNumberOfValues();
|
||||
}
|
||||
|
||||
void GlyphIntersectorVector::SetArrowRadii(vtkm::Float32 bodyRadius, vtkm::Float32 headRadius)
|
||||
{
|
||||
this->ArrowHeadRadius = headRadius;
|
||||
this->ArrowBodyRadius = bodyRadius;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
74
vtkm/rendering/raytracing/GlyphIntersectorVector.h
Normal file
74
vtkm/rendering/raytracing/GlyphIntersectorVector.h
Normal file
@ -0,0 +1,74 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_rendering_raytracing_Glyph_Intersector_Vector_h
|
||||
#define vtk_m_rendering_raytracing_Glyph_Intersector_Vector_h
|
||||
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/raytracing/ShapeIntersector.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace rendering
|
||||
{
|
||||
namespace raytracing
|
||||
{
|
||||
|
||||
class GlyphIntersectorVector : public ShapeIntersector
|
||||
{
|
||||
public:
|
||||
GlyphIntersectorVector(vtkm::rendering::GlyphType glyphType);
|
||||
virtual ~GlyphIntersectorVector() override;
|
||||
|
||||
void SetGlyphType(vtkm::rendering::GlyphType glyphType);
|
||||
|
||||
void SetData(const vtkm::cont::CoordinateSystem& coords,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointIds,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float32, 3>> sizes);
|
||||
|
||||
void IntersectRays(Ray<vtkm::Float32>& rays, bool returnCellIndex = false) override;
|
||||
|
||||
|
||||
void IntersectRays(Ray<vtkm::Float64>& rays, bool returnCellIndex = false) override;
|
||||
|
||||
template <typename Precision>
|
||||
void IntersectRaysImp(Ray<Precision>& rays, bool returnCellIndex);
|
||||
|
||||
|
||||
template <typename Precision>
|
||||
void IntersectionDataImp(Ray<Precision>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range);
|
||||
|
||||
void IntersectionData(Ray<vtkm::Float32>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range) override;
|
||||
|
||||
void IntersectionData(Ray<vtkm::Float64>& rays,
|
||||
const vtkm::cont::Field field,
|
||||
const vtkm::Range& range) override;
|
||||
|
||||
vtkm::Id GetNumberOfShapes() const override;
|
||||
|
||||
void SetArrowRadii(vtkm::Float32 bodyRadius, vtkm::Float32 headRadius);
|
||||
|
||||
protected:
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PointIds;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> Sizes;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> Normals;
|
||||
vtkm::rendering::GlyphType GlyphType;
|
||||
|
||||
vtkm::Float32 ArrowBodyRadius;
|
||||
vtkm::Float32 ArrowHeadRadius;
|
||||
}; // class GlyphIntersectorVector
|
||||
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
#endif //vtk_m_rendering_raytracing_Glyph_Intersector_Vector_h
|
@ -144,6 +144,12 @@ GetScalarFieldArray(const vtkm::cont::Field& field)
|
||||
{
|
||||
return field.GetData().ResetTypes(ScalarRenderingTypes{}, VTKM_DEFAULT_STORAGE_LIST{});
|
||||
}
|
||||
|
||||
VTKM_CONT inline vtkm::cont::UncertainArrayHandle<Vec3RenderingTypes, VTKM_DEFAULT_STORAGE_LIST>
|
||||
GetVec3FieldArray(const vtkm::cont::Field& field)
|
||||
{
|
||||
return field.GetData().ResetTypes(Vec3RenderingTypes{}, VTKM_DEFAULT_STORAGE_LIST{});
|
||||
}
|
||||
}
|
||||
}
|
||||
} //namespace vtkm::rendering::raytracing
|
||||
|
@ -26,6 +26,8 @@ set(unit_tests
|
||||
UnitTestMapperWireframer.cxx
|
||||
UnitTestMapperVolume.cxx
|
||||
UnitTestScalarRenderer.cxx
|
||||
UnitTestMapperGlyphScalar.cxx
|
||||
UnitTestMapperGlyphVector.cxx
|
||||
)
|
||||
|
||||
set(library_sources
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/MapperConnectivity.h>
|
||||
#include <vtkm/rendering/MapperCylinder.h>
|
||||
#include <vtkm/rendering/MapperGlyphScalar.h>
|
||||
#include <vtkm/rendering/MapperGlyphVector.h>
|
||||
#include <vtkm/rendering/MapperPoint.h>
|
||||
#include <vtkm/rendering/MapperQuad.h>
|
||||
#include <vtkm/rendering/MapperRayTracer.h>
|
||||
@ -116,6 +118,38 @@ void SetupMapper(vtkm::rendering::MapperPoint& mapper,
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMapper(vtkm::rendering::MapperGlyphScalar& mapper,
|
||||
const vtkm::rendering::testing::RenderTestOptions& options)
|
||||
{
|
||||
mapper.SetGlyphType(options.GlyphType);
|
||||
mapper.SetScaleByValue(options.UseVariableRadius);
|
||||
if (options.Radius >= 0)
|
||||
{
|
||||
mapper.SetBaseSize(options.Radius);
|
||||
}
|
||||
mapper.SetScaleDelta(0.5);
|
||||
if (options.RenderCells)
|
||||
{
|
||||
mapper.SetUseCells();
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMapper(vtkm::rendering::MapperGlyphVector& mapper,
|
||||
const vtkm::rendering::testing::RenderTestOptions& options)
|
||||
{
|
||||
mapper.SetGlyphType(options.GlyphType);
|
||||
mapper.SetScaleByValue(options.UseVariableRadius);
|
||||
if (options.Radius >= 0)
|
||||
{
|
||||
mapper.SetBaseSize(options.Radius);
|
||||
}
|
||||
mapper.SetScaleDelta(0.5);
|
||||
if (options.RenderCells)
|
||||
{
|
||||
mapper.SetUseCells();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MapperType>
|
||||
std::unique_ptr<vtkm::rendering::Mapper> MakeMapper(
|
||||
const vtkm::rendering::testing::RenderTestOptions& options)
|
||||
@ -222,6 +256,12 @@ void DoRenderTest(vtkm::rendering::CanvasRayTracer& canvas,
|
||||
case vtkm::rendering::testing::MapperType::Wireframer:
|
||||
mapper = MakeMapper<vtkm::rendering::MapperWireframer>(options);
|
||||
break;
|
||||
case vtkm::rendering::testing::MapperType::GlyphScalar:
|
||||
mapper = MakeMapper<vtkm::rendering::MapperGlyphScalar>(options);
|
||||
break;
|
||||
case vtkm::rendering::testing::MapperType::GlyphVector:
|
||||
mapper = MakeMapper<vtkm::rendering::MapperGlyphVector>(options);
|
||||
break;
|
||||
}
|
||||
DoRenderTest(canvas, *mapper, dataSetsFields, outputFile, options);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <vtkm/rendering/Camera.h>
|
||||
#include <vtkm/rendering/Canvas.h>
|
||||
#include <vtkm/rendering/Color.h>
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/Mapper.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/TextAnnotationScreen.h>
|
||||
@ -49,7 +50,9 @@ enum struct MapperType
|
||||
Point,
|
||||
Quad,
|
||||
Volume,
|
||||
Wireframer
|
||||
Wireframer,
|
||||
GlyphScalar,
|
||||
GlyphVector
|
||||
};
|
||||
|
||||
struct RenderTestOptions
|
||||
@ -102,7 +105,8 @@ struct RenderTestOptions
|
||||
// use the best available device for rendering.
|
||||
bool AllowAnyDevice = true;
|
||||
|
||||
// Special options for some glyph-like mappers
|
||||
// Special options for some glyph and glyph-like mappers
|
||||
vtkm::rendering::GlyphType GlyphType = vtkm::rendering::GlyphType::Cube;
|
||||
bool UseVariableRadius = false;
|
||||
vtkm::Float32 Radius = -1.0f;
|
||||
vtkm::Float32 RadiusDelta = 0.5f;
|
||||
|
81
vtkm/rendering/testing/UnitTestMapperGlyphScalar.cxx
Normal file
81
vtkm/rendering/testing/UnitTestMapperGlyphScalar.cxx
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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/rendering/Actor.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/View3D.h>
|
||||
#include <vtkm/rendering/testing/RenderTest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void RenderTests()
|
||||
{
|
||||
vtkm::cont::testing::MakeTestDataSet maker;
|
||||
|
||||
vtkm::rendering::testing::RenderTestOptions options;
|
||||
options.Mapper = vtkm::rendering::testing::MapperType::GlyphScalar;
|
||||
options.AllowAnyDevice = false;
|
||||
options.ColorTable = vtkm::cont::ColorTable::Preset::Inferno;
|
||||
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Cube;
|
||||
vtkm::rendering::testing::RenderTest(
|
||||
maker.Make3DUniformDataSet1(), "pointvar", "rendering/glyph_scalar/regular3D.png", options);
|
||||
|
||||
options.UseVariableRadius = true;
|
||||
options.RadiusDelta = 4.0f;
|
||||
options.Radius = 0.25f;
|
||||
vtkm::rendering::testing::RenderTest(maker.Make3DUniformDataSet1(),
|
||||
"pointvar",
|
||||
"rendering/glyph_scalar/variable_regular3D.png",
|
||||
options);
|
||||
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Sphere;
|
||||
vtkm::rendering::testing::RenderTest(maker.Make3DUniformDataSet3({ 7 }),
|
||||
"pointvar",
|
||||
"rendering/glyph_scalar/variable_spheres_regular3D.png",
|
||||
options);
|
||||
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Axes;
|
||||
vtkm::rendering::testing::RenderTest(maker.Make3DUniformDataSet3({ 7 }),
|
||||
"pointvar",
|
||||
"rendering/glyph_scalar/variable_axes_regular3D.png",
|
||||
options);
|
||||
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Quad;
|
||||
options.Radius = 5.0f;
|
||||
options.RadiusDelta = 0.75f;
|
||||
vtkm::rendering::testing::RenderTest(maker.Make3DUniformDataSet3({ 7 }),
|
||||
"pointvar",
|
||||
"rendering/glyph_scalar/variable_quads_regular3D.png",
|
||||
options);
|
||||
|
||||
// restore defaults
|
||||
options.RadiusDelta = 0.5f;
|
||||
options.UseVariableRadius = false;
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Cube;
|
||||
|
||||
options.RenderCells = true;
|
||||
options.Radius = 1.f;
|
||||
vtkm::rendering::testing::RenderTest(
|
||||
maker.Make3DExplicitDataSet7(), "cellvar", "rendering/glyph_scalar/cells.png", options);
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
||||
int UnitTestMapperGlyphScalar(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(RenderTests, argc, argv);
|
||||
}
|
49
vtkm/rendering/testing/UnitTestMapperGlyphVector.cxx
Normal file
49
vtkm/rendering/testing/UnitTestMapperGlyphVector.cxx
Normal file
@ -0,0 +1,49 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/rendering/Actor.h>
|
||||
#include <vtkm/rendering/CanvasRayTracer.h>
|
||||
#include <vtkm/rendering/GlyphType.h>
|
||||
#include <vtkm/rendering/MapperPoint.h>
|
||||
#include <vtkm/rendering/Scene.h>
|
||||
#include <vtkm/rendering/View3D.h>
|
||||
#include <vtkm/rendering/testing/RenderTest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void RenderTests()
|
||||
{
|
||||
vtkm::cont::testing::MakeTestDataSet maker;
|
||||
|
||||
vtkm::rendering::testing::RenderTestOptions options;
|
||||
options.Mapper = vtkm::rendering::testing::MapperType::GlyphVector;
|
||||
options.AllowAnyDevice = false;
|
||||
options.ColorTable = vtkm::cont::ColorTable::Preset::Inferno;
|
||||
options.GlyphType = vtkm::rendering::GlyphType::Arrow;
|
||||
options.UseVariableRadius = true;
|
||||
options.RadiusDelta = 4.0f;
|
||||
options.Radius = 0.02f;
|
||||
|
||||
vtkm::rendering::testing::RenderTest(maker.Make3DExplicitDataSetCowNose(),
|
||||
"point_vectors",
|
||||
"rendering/glyph_vector/points_arrows_cownose.png",
|
||||
options);
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
||||
int UnitTestMapperGlyphVector(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(RenderTests, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user