mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add orientation and winding options to SurfaceNormals.
This commit is contained in:
parent
320a5257ad
commit
91e7c4d0b9
18
docs/changelog/orient-normals.md
Normal file
18
docs/changelog/orient-normals.md
Normal file
@ -0,0 +1,18 @@
|
||||
# `SurfaceNormals` filter can now orient normals.
|
||||
|
||||
The `OrientNormals` worklet has been added to the `SurfaceNormals` filter, and
|
||||
is enabled by turning on the `AutoOrientNormals` option. This feature ensures
|
||||
that all normals generated by the filter will point out of the dataset (or
|
||||
inward if the `FlipNormals` option is true). In addition,
|
||||
`SurfaceNormals` now has a `Consistency` option that forces all triangle
|
||||
windings to be consistent with the cell normal direction (the cell points are
|
||||
specified in counter-clockwise order around the normal).
|
||||
|
||||
This functionality is provided by the following new worklets:
|
||||
|
||||
* OrientNormals
|
||||
* RunOrientCellNormals
|
||||
* RunOrientPointNormals
|
||||
* RunOrientPointAndCellNormals
|
||||
* RunFlipNormals
|
||||
* TriangleWinding
|
@ -32,28 +32,64 @@ public:
|
||||
SurfaceNormals();
|
||||
|
||||
/// Set/Get if cell normals should be generated. Default is off.
|
||||
/// @{
|
||||
void SetGenerateCellNormals(bool value) { this->GenerateCellNormals = value; }
|
||||
bool GetGenerateCellNormals() const { return this->GenerateCellNormals; }
|
||||
/// @}
|
||||
|
||||
/// Set/Get if the cell normals should be normalized. Default value is true.
|
||||
/// The intended use case of this flag is for faster, approximate point
|
||||
/// normals generation by skipping the normalization of the face normals.
|
||||
/// Note that when set to false, the result cell normals will not be unit
|
||||
/// length normals and the point normals will be different.
|
||||
/// @{
|
||||
void SetNormalizeCellNormals(bool value) { this->NormalizeCellNormals = value; }
|
||||
bool GetNormalizeCellNormals() const { return this->NormalizeCellNormals; }
|
||||
/// @}
|
||||
|
||||
/// Set/Get if the point normals should be generated. Default is on.
|
||||
/// @{
|
||||
void SetGeneratePointNormals(bool value) { this->GeneratePointNormals = value; }
|
||||
bool GetGeneratePointNormals() const { return this->GeneratePointNormals; }
|
||||
/// @}
|
||||
|
||||
/// Set/Get the name of the cell normals field. Default is "Normals".
|
||||
/// @{
|
||||
void SetCellNormalsName(const std::string& name) { this->CellNormalsName = name; }
|
||||
const std::string& GetCellNormalsName() const { return this->CellNormalsName; }
|
||||
/// @}
|
||||
|
||||
/// Set/Get the name of the point normals field. Default is "Normals".
|
||||
/// @{
|
||||
void SetPointNormalsName(const std::string& name) { this->PointNormalsName = name; }
|
||||
const std::string& GetPointNormalsName() const { return this->PointNormalsName; }
|
||||
/// @}
|
||||
|
||||
/// If true, the normals will be oriented to face outwards from the surface.
|
||||
/// This requires a closed manifold surface or the behavior is undefined.
|
||||
/// This option is expensive but necessary for rendering.
|
||||
/// To make the normals point inward, set FlipNormals to true.
|
||||
/// @{
|
||||
void SetAutoOrientNormals(bool v) { this->AutoOrientNormals = v; }
|
||||
bool GetAutoOrientNormals() const { return this->AutoOrientNormals; }
|
||||
/// @}
|
||||
|
||||
/// Reverse the normals to point inward when AutoOrientNormals is true.
|
||||
/// Default is false.
|
||||
/// @{
|
||||
void SetFlipNormals(bool v) { this->FlipNormals = v; }
|
||||
bool GetFlipNormals() const { return this->FlipNormals; }
|
||||
/// @}
|
||||
|
||||
/// Ensure that polygon winding is consistent with normal orientation.
|
||||
/// Triangles are wound such that their points are counter-clockwise around
|
||||
/// the generated cell normal. Default is true.
|
||||
/// @note This currently only affects triangles.
|
||||
/// @note This is only applied when cell normals are generated.
|
||||
/// @{
|
||||
void SetConsistency(bool v) { this->Consistency = v; }
|
||||
bool GetConsistency() const { return this->Consistency; }
|
||||
/// @}
|
||||
|
||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
||||
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
|
||||
@ -65,6 +101,9 @@ private:
|
||||
bool GenerateCellNormals;
|
||||
bool NormalizeCellNormals;
|
||||
bool GeneratePointNormals;
|
||||
bool AutoOrientNormals;
|
||||
bool FlipNormals;
|
||||
bool Consistency;
|
||||
|
||||
std::string CellNormalsName;
|
||||
std::string PointNormalsName;
|
||||
|
@ -8,9 +8,13 @@
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/filter/SurfaceNormals.h>
|
||||
|
||||
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||
#include <vtkm/filter/internal/CreateResult.h>
|
||||
#include <vtkm/worklet/OrientNormals.h>
|
||||
#include <vtkm/worklet/SurfaceNormals.h>
|
||||
#include <vtkm/worklet/TriangleWinding.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -58,6 +62,9 @@ inline SurfaceNormals::SurfaceNormals()
|
||||
: GenerateCellNormals(false)
|
||||
, NormalizeCellNormals(true)
|
||||
, GeneratePointNormals(true)
|
||||
, AutoOrientNormals(false)
|
||||
, FlipNormals(false)
|
||||
, Consistency(true)
|
||||
{
|
||||
this->SetUseCoordinateSystemAsField(true);
|
||||
}
|
||||
@ -76,19 +83,22 @@ inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
|
||||
throw vtkm::cont::ErrorFilterExecution("No normals selected.");
|
||||
}
|
||||
|
||||
const auto& cellset = input.GetCellSet(this->GetActiveCellSetIndex());
|
||||
const auto cellset =
|
||||
vtkm::filter::ApplyPolicyUnstructured(input.GetCellSet(this->GetActiveCellSetIndex()), policy);
|
||||
const auto& coords = input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()).GetData();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> faceNormals;
|
||||
vtkm::worklet::FacetedSurfaceNormals faceted;
|
||||
faceted.SetNormalize(this->NormalizeCellNormals);
|
||||
faceted.Run(vtkm::filter::ApplyPolicy(cellset, policy), points, faceNormals);
|
||||
faceted.Run(cellset, points, faceNormals);
|
||||
|
||||
vtkm::cont::DataSet result;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> pointNormals;
|
||||
if (this->GeneratePointNormals)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f> pointNormals;
|
||||
vtkm::worklet::SmoothSurfaceNormals smooth;
|
||||
smooth.Run(vtkm::filter::ApplyPolicy(cellset, policy), faceNormals, pointNormals);
|
||||
smooth.Run(cellset, faceNormals, pointNormals);
|
||||
|
||||
|
||||
result = internal::CreateResult(input,
|
||||
pointNormals,
|
||||
@ -111,6 +121,66 @@ inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
|
||||
cellset.GetName());
|
||||
}
|
||||
|
||||
if (this->AutoOrientNormals)
|
||||
{
|
||||
using Orient = vtkm::worklet::OrientNormals;
|
||||
|
||||
if (this->GenerateCellNormals && this->GeneratePointNormals)
|
||||
{
|
||||
Orient::RunPointAndCellNormals(cellset, coords, pointNormals, faceNormals);
|
||||
}
|
||||
else if (this->GenerateCellNormals)
|
||||
{
|
||||
Orient::RunCellNormals(cellset, coords, faceNormals);
|
||||
}
|
||||
else if (this->GeneratePointNormals)
|
||||
{
|
||||
Orient::RunPointNormals(cellset, coords, pointNormals);
|
||||
}
|
||||
|
||||
if (this->FlipNormals)
|
||||
{
|
||||
if (this->GenerateCellNormals)
|
||||
{
|
||||
Orient::RunFlipNormals(faceNormals);
|
||||
}
|
||||
if (this->GeneratePointNormals)
|
||||
{
|
||||
Orient::RunFlipNormals(pointNormals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->Consistency && this->GenerateCellNormals)
|
||||
{
|
||||
auto newCells = vtkm::worklet::TriangleWinding::Run(cellset, coords, faceNormals);
|
||||
|
||||
// Add the new cells into the result:
|
||||
vtkm::cont::DataSet newResult;
|
||||
for (vtkm::Id i = 0; i < result.GetNumberOfCoordinateSystems(); ++i)
|
||||
{
|
||||
newResult.AddCoordinateSystem(result.GetCoordinateSystem(i));
|
||||
}
|
||||
const vtkm::Id activeCells = this->GetActiveCellSetIndex();
|
||||
for (vtkm::Id i = 0; i < result.GetNumberOfCellSets(); ++i)
|
||||
{
|
||||
if (i != activeCells)
|
||||
{
|
||||
newResult.AddCellSet(result.GetCellSet(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
newResult.AddCellSet(newCells);
|
||||
}
|
||||
}
|
||||
for (vtkm::Id i = 0; i < result.GetNumberOfFields(); ++i)
|
||||
{
|
||||
newResult.AddField(result.GetField(i));
|
||||
}
|
||||
|
||||
result = newResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ void TestSurfaceNormals()
|
||||
|
||||
std::cout << "generate both cell and point normals:\n";
|
||||
filter.SetGeneratePointNormals(true);
|
||||
filter.SetAutoOrientNormals(true);
|
||||
result = filter.Execute(ds);
|
||||
VTKM_TEST_ASSERT(result.HasField("Normals", vtkm::cont::Field::Association::POINTS),
|
||||
"Point normals missing.");
|
||||
|
Loading…
Reference in New Issue
Block a user