vtk-m/vtkm/rendering/testlib/RenderTest.cxx
Kenneth Moreland ad1e7b5bdb Add module mechanism
This mechanism sets up CMake variables that allow a user to select which
modules/libraries to create. Dependencies will be tracked down to ensure
that all of a module's dependencies are also enabled.

The modules are also arranged into groups.
Groups allow you to set the enable flag for a group of modules at once.
Thus, if you have several modules that are likely to be used together,
you can create a group for them.

This can be handy in converting user-friendly CMake options (such as
`VTKm_ENABLE_RENDERING`) to the modules that enable that by pointing to
the appropriate group.
2022-10-26 12:51:05 -06:00

309 lines
10 KiB
C++

//============================================================================
// 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/testing/RenderTest.h>
#include <vtkm/rendering/Actor.h>
#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>
#include <vtkm/rendering/MapperVolume.h>
#include <vtkm/rendering/MapperWireframer.h>
#include <vtkm/rendering/TextAnnotationScreen.h>
#include <vtkm/rendering/View1D.h>
#include <vtkm/rendering/View2D.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
namespace
{
using DataSetFieldVector = std::vector<std::pair<vtkm::cont::DataSet, std::string>>;
void SetupView(vtkm::rendering::View3D& view,
const vtkm::Bounds& bounds,
const vtkm::Range&,
const vtkm::rendering::testing::RenderTestOptions& options)
{
vtkm::rendering::Camera camera;
camera.ResetToBounds(bounds, options.DataViewPadding);
camera.Azimuth(options.CameraAzimuth);
camera.Elevation(options.CameraElevation);
view.SetCamera(camera);
}
void SetupView(vtkm::rendering::View2D& view,
const vtkm::Bounds& bounds,
const vtkm::Range&,
const vtkm::rendering::testing::RenderTestOptions& options)
{
vtkm::rendering::Camera camera;
camera.ResetToBounds(bounds, options.DataViewPadding);
camera.SetClippingRange(options.ClippingRange);
camera.SetViewport(options.Viewport);
view.SetCamera(camera);
}
void SetupView(vtkm::rendering::View1D& view,
const vtkm::Bounds& bounds,
const vtkm::Range& fieldRange,
const vtkm::rendering::testing::RenderTestOptions& options)
{
vtkm::rendering::Camera camera;
// In a 1D view, the y bounds are determined by the field that is being x/y plotted.
camera.ResetToBounds({ bounds.X, fieldRange, { 0, 0 } }, options.DataViewPadding);
camera.SetClippingRange(options.ClippingRange);
camera.SetViewport(options.Viewport);
view.SetCamera(camera);
view.SetLogX(options.LogX);
view.SetLogY(options.LogY);
}
template <typename ViewType>
std::unique_ptr<vtkm::rendering::View> MakeView(
vtkm::rendering::Canvas& canvas,
vtkm::rendering::Mapper& mapper,
vtkm::rendering::Scene& scene,
const vtkm::Bounds& bounds,
const vtkm::Range& fieldRange,
const vtkm::rendering::testing::RenderTestOptions& options)
{
ViewType* view = new ViewType(scene, mapper, canvas, options.Background, options.Foreground);
SetupView(*view, bounds, fieldRange, options);
return std::unique_ptr<vtkm::rendering::View>(view);
}
template <typename MapperType>
void SetupMapper(MapperType&, const vtkm::rendering::testing::RenderTestOptions&)
{
}
void SetupMapper(vtkm::rendering::MapperCylinder& mapper,
const vtkm::rendering::testing::RenderTestOptions& options)
{
mapper.UseVariableRadius(options.UseVariableRadius);
if (options.Radius >= 0)
{
mapper.SetRadius(options.Radius);
}
mapper.SetRadiusDelta(0.5);
}
void SetupMapper(vtkm::rendering::MapperPoint& mapper,
const vtkm::rendering::testing::RenderTestOptions& options)
{
mapper.UseVariableRadius(options.UseVariableRadius);
if (options.Radius >= 0)
{
mapper.SetRadius(options.Radius);
}
mapper.SetRadiusDelta(0.5);
if (options.RenderCells)
{
mapper.UseCells();
}
}
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)
{
MapperType* mapper = new MapperType;
SetupMapper(*mapper, options);
return std::unique_ptr<vtkm::rendering::Mapper>(mapper);
}
void DoRenderTest(vtkm::rendering::Canvas& canvas,
vtkm::rendering::Mapper& mapper,
const DataSetFieldVector& dataSetsFields,
const std::string& outputFile,
const vtkm::rendering::testing::RenderTestOptions& options)
{
std::size_t numFields = dataSetsFields.size();
VTKM_TEST_ASSERT(numFields > 0);
vtkm::rendering::Scene scene;
vtkm::Bounds bounds;
vtkm::Range fieldRange;
for (std::size_t dataFieldId = 0; dataFieldId < numFields; ++dataFieldId)
{
vtkm::cont::DataSet dataSet = dataSetsFields[dataFieldId].first;
std::string fieldName = dataSetsFields[dataFieldId].second;
if (options.Colors.empty())
{
scene.AddActor(vtkm::rendering::Actor(dataSet.GetCellSet(),
dataSet.GetCoordinateSystem(),
dataSet.GetField(fieldName),
options.ColorTable));
}
else
{
scene.AddActor(vtkm::rendering::Actor(dataSet.GetCellSet(),
dataSet.GetCoordinateSystem(),
dataSet.GetField(fieldName),
options.Colors[dataFieldId % options.Colors.size()]));
}
bounds.Include(dataSet.GetCoordinateSystem().GetBounds());
fieldRange.Include(dataSet.GetField(fieldName).GetRange().ReadPortal().Get(0));
}
std::unique_ptr<vtkm::rendering::View> viewPointer;
switch (options.ViewDimension)
{
case 1:
viewPointer =
MakeView<vtkm::rendering::View1D>(canvas, mapper, scene, bounds, fieldRange, options);
break;
case 2:
viewPointer =
MakeView<vtkm::rendering::View2D>(canvas, mapper, scene, bounds, fieldRange, options);
break;
case 3:
viewPointer =
MakeView<vtkm::rendering::View3D>(canvas, mapper, scene, bounds, fieldRange, options);
break;
}
vtkm::rendering::View& view = *viewPointer;
view.AddTextAnnotation(std::unique_ptr<vtkm::rendering::TextAnnotationScreen>(
new vtkm::rendering::TextAnnotationScreen(options.Title,
options.Foreground,
options.TitleScale,
options.TitlePosition,
options.TitleAngle)));
view.SetRenderAnnotationsEnabled(options.EnableAnnotations);
VTKM_TEST_ASSERT(test_equal_images(view,
outputFile,
options.AverageRadius,
options.PixelShiftRadius,
options.AllowedPixelErrorRatio,
options.Threshold));
}
void DoRenderTest(vtkm::rendering::CanvasRayTracer& canvas,
const DataSetFieldVector& dataSetsFields,
const std::string& outputFile,
const vtkm::rendering::testing::RenderTestOptions& options)
{
std::unique_ptr<vtkm::rendering::Mapper> mapper;
switch (options.Mapper)
{
case vtkm::rendering::testing::MapperType::RayTracer:
mapper = MakeMapper<vtkm::rendering::MapperRayTracer>(options);
break;
case vtkm::rendering::testing::MapperType::Connectivity:
mapper = MakeMapper<vtkm::rendering::MapperConnectivity>(options);
break;
case vtkm::rendering::testing::MapperType::Cylinder:
mapper = MakeMapper<vtkm::rendering::MapperCylinder>(options);
break;
case vtkm::rendering::testing::MapperType::Point:
mapper = MakeMapper<vtkm::rendering::MapperPoint>(options);
break;
case vtkm::rendering::testing::MapperType::Quad:
mapper = MakeMapper<vtkm::rendering::MapperQuad>(options);
break;
case vtkm::rendering::testing::MapperType::Volume:
mapper = MakeMapper<vtkm::rendering::MapperVolume>(options);
break;
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);
}
} // annonymous namesapce
namespace vtkm
{
namespace rendering
{
namespace testing
{
void RenderTest(const vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const std::string& outputFile,
const RenderTestOptions& options)
{
RenderTest({ { dataSet, fieldName } }, outputFile, options);
}
void RenderTest(const DataSetFieldVector& dataSetsFields,
const std::string& outputFile,
const RenderTestOptions& options)
{
std::unique_ptr<vtkm::cont::ScopedRuntimeDeviceTracker> deviceScope;
if (options.AllowAnyDevice)
{
deviceScope =
std::make_unique<vtkm::cont::ScopedRuntimeDeviceTracker>(vtkm::cont::DeviceAdapterTagAny{});
}
if (options.Canvas != vtkm::rendering::testing::CanvasType::RayTracer)
{
VTKM_TEST_FAIL("Currently only the CanvasRayTracer canvas is supported.");
}
vtkm::rendering::CanvasRayTracer canvas(options.CanvasWidth, options.CanvasHeight);
DoRenderTest(canvas, dataSetsFields, outputFile, options);
}
} // namespace vtkm::rendering::testing
} // namespace vtkm::rendering
} // namespace vtkm