vtk-m/vtkm/interop/anari/ANARIScene.h
2023-08-30 15:52:48 -05:00

177 lines
5.5 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.
//============================================================================
#ifndef vtk_m_interop_anari_ANARIScene_h
#define vtk_m_interop_anari_ANARIScene_h
#include <vtkm/interop/anari/ANARIMapper.h>
// std
#include <string>
#include <type_traits>
namespace vtkm
{
namespace interop
{
namespace anari
{
/// @brief Object which manages a collection of mappers representing a single scene.
///
/// This object is a container of named mappers which will automatically keep
/// an `ANARIWorld` up to date which contains any `ANARISurface` or
/// `ANARIVolume` objects coming from the contained mappers. While applications
/// are free to do this work themselves, it is very convenient and useful to
/// let `ANARIScene` do the work of keeping an `ANARIWorld` up to date for you.
///
/// Mappers in `ANARIScene` can also be selectively hidden for quick scene
/// updates. A hidden mapper's geometry/volume are just skipped when updating
/// the list of object handles in the world.
///
/// NOTE: This object will not create any lights in the scene, so the
/// `ANARIWorld` used by the application is expected to have application-managed
/// `ANARILight` objects added to it when desired.
///
/// NOTE: Unlike `ANARIMapper` and `ANARIActor`, `ANARIScene` is not C++
/// copyable or movable.
struct VTKM_ANARI_EXPORT ANARIScene
{
/// @brief Constructor
///
ANARIScene(anari_cpp::Device device);
/// @brief Destructor
///
~ANARIScene();
ANARIScene(const ANARIScene&) = delete;
ANARIScene(ANARIScene&&) = delete;
ANARIScene& operator=(const ANARIScene&) = delete;
ANARIScene& operator=(ANARIScene&&) = delete;
/// @brief Add a mapper to the scene.
/// @tparam ANARIMapperType Any subclass of `ANARIMapper`.
///
/// NOTE: This will replace any mapper that has the same name.
template <typename ANARIMapperType>
ANARIMapperType& AddMapper(const ANARIMapperType& mapper, bool visible = true);
/// @brief Add a mapper to the scene.
/// @tparam ANARIMapperType Any subclass of `ANARIMapper`.
///
/// NOTE: Replace the i'th mapper with a new instance.
/// NOTE: It is undefined behavior to use this to put 2 or more mappers in the
/// scene with the same name.
template <typename ANARIMapperType>
void ReplaceMapper(const ANARIMapperType& newMapper, vtkm::IdComponent id, bool visible);
/// @brief Get number of mappers in this scene.
///
vtkm::IdComponent GetNumberOfMappers() const;
/// @brief Ask whether a mapper has the passed in name or not.
///
bool HasMapperWithName(const char* name) const;
/// @brief Get the index to the mapper with the given name.
///
vtkm::IdComponent GetMapperIndexByName(const char* name);
/// @brief Get the associated mapper by index.
///
ANARIMapper& GetMapper(vtkm::IdComponent id);
/// @brief Get the associated mapper by name.
///
ANARIMapper& GetMapper(const char* name);
/// @brief Get the associated mapper by name.
///
bool GetMapperVisible(vtkm::IdComponent id) const;
void SetMapperVisible(vtkm::IdComponent id, bool shown);
/// @brief Remove mapper by index.
///
void RemoveMapper(vtkm::IdComponent id);
/// @brief Remove mapper by name.
///
void RemoveMapper(const char* name);
/// @brief Clear out this scene of all mappers.
void RemoveAllMappers();
/// @brief Get the `ANARIDevice` handle this scene is talking to.
///
/// NOTE: This handle is not retained, so applications should not release it.
anari_cpp::Device GetDevice() const;
/// @brief Get the `ANARIWorld` handle this scene is working on.
///
/// NOTE: This handle is not retained, so applications should not release it.
anari_cpp::World GetANARIWorld();
private:
void UpdateWorld();
anari_cpp::Device Device{ nullptr };
anari_cpp::World World{ nullptr };
struct SceneMapper
{
std::unique_ptr<ANARIMapper> Mapper;
bool Show{ true };
};
std::vector<SceneMapper> Mappers;
};
// Inlined definitions ////////////////////////////////////////////////////////
template <typename ANARIMapperType>
inline ANARIMapperType& ANARIScene::AddMapper(const ANARIMapperType& mapper, bool visible)
{
static_assert(std::is_base_of<ANARIMapper, ANARIMapperType>::value,
"Only ANARIMapper types can be added to ANARIScene");
auto* name = mapper.GetName();
if (HasMapperWithName(name))
{
auto idx = GetMapperIndexByName(name);
ReplaceMapper(mapper, idx, visible);
return (ANARIMapperType&)GetMapper(idx);
}
else
{
this->Mappers.push_back({ std::make_unique<ANARIMapperType>(mapper), visible });
UpdateWorld();
return (ANARIMapperType&)GetMapper(GetNumberOfMappers() - 1);
}
}
template <typename ANARIMapperType>
inline void ANARIScene::ReplaceMapper(const ANARIMapperType& newMapper,
vtkm::IdComponent id,
bool visible)
{
static_assert(std::is_base_of<ANARIMapper, ANARIMapperType>::value,
"Only ANARIMapper types can be added to ANARIScene");
const bool wasVisible = GetMapperVisible(id);
Mappers[id] = { std::make_unique<ANARIMapperType>(newMapper), visible };
if (wasVisible || visible)
UpdateWorld();
}
} // namespace anari
} // namespace interop
} // namespace vtkm
#endif