Allow external cellsets to be used by TriangleWinding worklet.
This commit is contained in:
parent
19344416da
commit
b3df7da222
@ -23,8 +23,16 @@
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleGroupVec.h>
|
||||
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
||||
#include <vtkm/cont/ArrayRangeCompute.h>
|
||||
#include <vtkm/cont/CellSetExplicit.h>
|
||||
#include <vtkm/cont/CellSetSingleType.h>
|
||||
#include <vtkm/cont/DynamicCellSet.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/MaskIndices.h>
|
||||
@ -48,6 +56,7 @@ namespace worklet
|
||||
class TriangleWinding
|
||||
{
|
||||
public:
|
||||
// Used by Explicit and SingleType specializations
|
||||
struct WorkletWindToCellNormals : public WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn cellNormals, FieldInOut cellPoints, WholeArrayIn coords);
|
||||
@ -82,10 +91,170 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Used by generic implementations:
|
||||
struct WorkletGetCellShapesAndSizes : public WorkletVisitCellsWithPoints
|
||||
{
|
||||
using ControlSignature = void(CellSetIn cells, FieldOutCell shapes, FieldOutCell sizes);
|
||||
using ExecutionSignature = void(CellShape, PointCount, _2, _3);
|
||||
|
||||
template <typename CellShapeTag>
|
||||
VTKM_EXEC void operator()(const CellShapeTag cellShapeIn,
|
||||
const vtkm::IdComponent cellSizeIn,
|
||||
vtkm::UInt8& cellShapeOut,
|
||||
vtkm::IdComponent& cellSizeOut) const
|
||||
{
|
||||
cellSizeOut = cellSizeIn;
|
||||
cellShapeOut = cellShapeIn.Id;
|
||||
}
|
||||
};
|
||||
|
||||
struct WorkletWindToCellNormalsGeneric : public WorkletVisitCellsWithPoints
|
||||
{
|
||||
using ControlSignature = void(CellSetIn cellsIn,
|
||||
WholeArrayIn coords,
|
||||
FieldInCell cellNormals,
|
||||
FieldOutCell cellsOut);
|
||||
using ExecutionSignature = void(PointIndices, _2, _3, _4);
|
||||
|
||||
template <typename InputIds, typename Coords, typename Normal, typename OutputIds>
|
||||
VTKM_EXEC void operator()(const InputIds& inputIds,
|
||||
const Coords& coords,
|
||||
const Normal& normal,
|
||||
OutputIds& outputIds) const
|
||||
{
|
||||
VTKM_ASSERT(inputIds.GetNumberOfComponents() == outputIds.GetNumberOfComponents());
|
||||
|
||||
// We only care about triangles:
|
||||
if (inputIds.GetNumberOfComponents() != 3)
|
||||
{
|
||||
// Just passthrough non-triangles
|
||||
// Cannot just assign here, must do a manual component-wise copy to
|
||||
// support VecFromPortal:
|
||||
for (vtkm::IdComponent i = 0; i < inputIds.GetNumberOfComponents(); ++i)
|
||||
{
|
||||
outputIds[i] = inputIds[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const Normal p0 = coords.Get(inputIds[0]);
|
||||
const Normal p1 = coords.Get(inputIds[1]);
|
||||
const Normal p2 = coords.Get(inputIds[2]);
|
||||
const Normal v01 = p1 - p0;
|
||||
const Normal v02 = p2 - p0;
|
||||
const Normal triangleNormal = vtkm::Cross(v01, v02);
|
||||
if (vtkm::Dot(normal, triangleNormal) < 0)
|
||||
{ // Reorder triangle:
|
||||
outputIds[0] = inputIds[0];
|
||||
outputIds[1] = inputIds[2];
|
||||
outputIds[2] = inputIds[1];
|
||||
}
|
||||
else
|
||||
{ // passthrough:
|
||||
outputIds[0] = inputIds[0];
|
||||
outputIds[1] = inputIds[1];
|
||||
outputIds[2] = inputIds[2];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Launcher
|
||||
{
|
||||
vtkm::cont::DynamicCellSet Result;
|
||||
|
||||
// Generic handler:
|
||||
template <typename CellSetType,
|
||||
typename PointComponentType,
|
||||
typename PointStorageType,
|
||||
typename CellNormalComponentType,
|
||||
typename CellNormalStorageType>
|
||||
VTKM_CONT void operator()(
|
||||
const CellSetType& cellSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& coords,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<CellNormalComponentType, 3>, CellNormalStorageType>&
|
||||
cellNormals,
|
||||
...)
|
||||
{
|
||||
const auto numCells = cellSet.GetNumberOfCells();
|
||||
if (numCells == 0)
|
||||
{
|
||||
this->Result = cellSet;
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::cont::Invoker invoker;
|
||||
|
||||
// Get each cell's size:
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
||||
vtkm::cont::ArrayHandle<vtkm::UInt8> cellShapes;
|
||||
{
|
||||
WorkletGetCellShapesAndSizes worklet;
|
||||
invoker(worklet, cellSet, cellShapes, numIndices);
|
||||
}
|
||||
|
||||
// Check to see if we can use CellSetSingleType:
|
||||
vtkm::IdComponent cellSize = 0; // 0 if heterogeneous, >0 if homogeneous
|
||||
vtkm::UInt8 cellShape = 0; // only valid if homogeneous
|
||||
{
|
||||
auto rangeHandleSizes = vtkm::cont::ArrayRangeCompute(numIndices);
|
||||
auto rangeHandleShapes = vtkm::cont::ArrayRangeCompute(cellShapes);
|
||||
|
||||
cellShapes.ReleaseResourcesExecution();
|
||||
|
||||
auto rangeSizes = rangeHandleSizes.GetPortalConstControl().Get(0);
|
||||
auto rangeShapes = rangeHandleShapes.GetPortalConstControl().Get(0);
|
||||
|
||||
const bool sameSize = vtkm::Abs(rangeSizes.Max - rangeSizes.Min) < 0.5;
|
||||
const bool sameShape = vtkm::Abs(rangeShapes.Max - rangeShapes.Min) < 0.5;
|
||||
|
||||
if (sameSize && sameShape)
|
||||
{
|
||||
cellSize = static_cast<vtkm::IdComponent>(rangeSizes.Min + 0.5);
|
||||
cellShape = static_cast<vtkm::UInt8>(rangeShapes.Min + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
if (cellSize > 0)
|
||||
{ // Single cell type:
|
||||
// don't need these anymore:
|
||||
numIndices.ReleaseResources();
|
||||
cellShapes.ReleaseResources();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> conn;
|
||||
conn.Allocate(cellSize * numCells);
|
||||
|
||||
auto offsets = vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, cellSize, numCells);
|
||||
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
|
||||
|
||||
WorkletWindToCellNormalsGeneric worklet;
|
||||
invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
|
||||
|
||||
vtkm::cont::CellSetSingleType<> outCells;
|
||||
outCells.Fill(cellSet.GetNumberOfPoints(), cellShape, cellSize, conn);
|
||||
this->Result = outCells;
|
||||
}
|
||||
else
|
||||
{ // Multiple cell types:
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> offsets;
|
||||
vtkm::Id connSize;
|
||||
vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connSize);
|
||||
numIndices.ReleaseResourcesExecution();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> conn;
|
||||
conn.Allocate(connSize);
|
||||
|
||||
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
|
||||
|
||||
WorkletWindToCellNormalsGeneric worklet;
|
||||
invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
|
||||
|
||||
vtkm::cont::CellSetExplicit<> outCells;
|
||||
outCells.Fill(cellSet.GetNumberOfPoints(), cellShapes, numIndices, conn, offsets);
|
||||
this->Result = outCells;
|
||||
}
|
||||
}
|
||||
|
||||
// Specialization for CellSetExplicit
|
||||
template <typename S,
|
||||
typename N,
|
||||
typename C,
|
||||
@ -98,10 +267,18 @@ public:
|
||||
const vtkm::cont::CellSetExplicit<S, N, C, O>& cellSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& coords,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<CellNormalComponentType, 3>, CellNormalStorageType>&
|
||||
cellNormals)
|
||||
cellNormals,
|
||||
int)
|
||||
{
|
||||
using WindToCellNormals = vtkm::worklet::DispatcherMapField<WorkletWindToCellNormals>;
|
||||
|
||||
const auto numCells = cellSet.GetNumberOfCells();
|
||||
if (numCells == 0)
|
||||
{
|
||||
this->Result = cellSet;
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> conn;
|
||||
{
|
||||
const auto& connIn = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
|
||||
@ -126,6 +303,7 @@ public:
|
||||
this->Result = newCells;
|
||||
}
|
||||
|
||||
// Specialization for CellSetSingleType
|
||||
template <typename C,
|
||||
typename PointComponentType,
|
||||
typename PointStorageType,
|
||||
@ -135,10 +313,18 @@ public:
|
||||
const vtkm::cont::CellSetSingleType<C>& cellSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& coords,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Vec<CellNormalComponentType, 3>, CellNormalStorageType>&
|
||||
cellNormals)
|
||||
cellNormals,
|
||||
int)
|
||||
{
|
||||
using WindToCellNormals = vtkm::worklet::DispatcherMapField<WorkletWindToCellNormals>;
|
||||
|
||||
const auto numCells = cellSet.GetNumberOfCells();
|
||||
if (numCells == 0)
|
||||
{
|
||||
this->Result = cellSet;
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> conn;
|
||||
{
|
||||
const auto& connIn = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
|
||||
@ -175,7 +361,10 @@ public:
|
||||
cellNormals)
|
||||
{
|
||||
Launcher launcher;
|
||||
vtkm::cont::CastAndCall(cellSet, launcher, coords, cellNormals);
|
||||
// The last arg is just to help with overload resolution on the templated
|
||||
// Launcher::operator() method, so that the more specialized impls are
|
||||
// preferred over the generic one.
|
||||
vtkm::cont::CastAndCall(cellSet, launcher, coords, cellNormals, 0);
|
||||
return launcher.Result;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user