Skip to content

Commit

Permalink
Merge pull request #1069 from dlyr/renderParameters-variableSet
Browse files Browse the repository at this point in the history
make RenderParameters inherit from VariableSet and remove duplicated code.
  • Loading branch information
dlyr authored Oct 10, 2024
2 parents 4af50c3 + 13dbb0a commit 5db51f5
Show file tree
Hide file tree
Showing 38 changed files with 1,024 additions and 1,068 deletions.
6 changes: 3 additions & 3 deletions doc/developer/material.md
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ public:
void updateGL() override {
// Method called before drawing each frame in Rendering::updateRenderObjectsInternal.
// The name of the parameter corresponds to the shader's uniform name.
m_renderParameters.addParameter( "aColorUniform", m_colorParameter );
m_renderParameters.addParameter( "aScalarUniform", m_scalarParameter );
m_renderParameters.setVariable( "aColorUniform", m_colorParameter );
m_renderParameters.setVariable( "aScalarUniform", m_scalarParameter );
}
void setOrComputeTheParameterValues() {
Expand Down Expand Up @@ -652,7 +652,7 @@ renderTechnique.setConfiguration( myConfig, DefaultRenderingPasses::LIGHTING_OPA
// 5. Create and associate the parameter provider with the RenderTechnique
auto parameterProvider = std::make_shared<MyParameterProvider>();
parameterProvider->setOrComputeTheParameterValues();
renderTechnique.setParametersProvider(parameterProvider);
renderTechnique.setVariablesProvider(parameterProvider);
// 6. Associate the render technique with a geometry in a Ra::Engine::Rendering::RenderObject
std::shared_ptr<Ra::Engine::Data::Mesh> mesh( new Ra::Engine::Data::Mesh( "my mesh" ) );
Expand Down
49 changes: 26 additions & 23 deletions examples/ParameterEditing/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Include Radium base application and its simple Gui

#include <Core/Containers/VariableSet.hpp>
#include <Core/Containers/VariableSetEnumManagement.hpp>
#include <Core/Utils/TypesUtils.hpp>
#include <Engine/Data/RenderParameters.hpp>
#include <Gui/ParameterSetEditor/ParameterSetEditor.hpp>
Expand Down Expand Up @@ -177,9 +179,9 @@ int main( int argc, char* argv[] ) {
QDialog dialog( nullptr );
dialog.setWindowTitle( "ParameterSet editing example" );
auto layout = new QVBoxLayout( dialog.window() );
ParameterSetEditor editor( "Demonstration parameter set", dialog.window() );
VariableSetEditor editor( "Demonstration parameter set", dialog.window() );

editor.showUnspecified( true );
editor.setShowUnspecified( true );
layout->addWidget( &editor );
//! [Creating the editing dialog]

Expand All @@ -192,29 +194,30 @@ int main( int argc, char* argv[] ) {

//! [filling the parameter set to edit ]
RenderParameters parameters;
parameters.addEnumConverter( "enum", valuesEnumConverter );
parameters.addParameter( "bool", false );
parameters.addParameter( "enum", Values::VALUE_1 );
parameters.addParameter( "int", int( 0 ) );
parameters.addParameter( "int_constrained", int( 0 ) );
parameters.addParameter( "uint", (unsigned int)( 10 ) );
parameters.addParameter( "uint_constrained", (unsigned int)( 5 ) );
parameters.addParameter( "Scalar", 0_ra );
parameters.addParameter( "Scalar_constrained", 0.5_ra );
parameters.addParameter( "Scalar_half_constrained", 0_ra );
parameters.addParameter( "Scalar_multiconstrained", 0.5_ra );
parameters.addParameter( "Color", Ra::Core::Utils::Color::Magenta() );
parameters.addParameter( "Vec2", Ra::Core::Vector2 { 1_ra, 0_ra } );
parameters.addParameter( "Vec3", Ra::Core::Vector3 { 1_ra, 1_ra, 1_ra } );
parameters.addParameter(
using namespace Ra::Core::VariableSetEnumManagement;
addEnumConverter( parameters, "enum", valuesEnumConverter );
parameters.setVariable( "bool", false );
parameters.setVariable( "enum", Values::VALUE_1 );
parameters.setVariable( "int", int( 0 ) );
parameters.setVariable( "int_constrained", int( 0 ) );
parameters.setVariable( "uint", (unsigned int)( 10 ) );
parameters.setVariable( "uint_constrained", (unsigned int)( 5 ) );
parameters.setVariable( "Scalar", 0_ra );
parameters.setVariable( "Scalar_constrained", 0.5_ra );
parameters.setVariable( "Scalar_half_constrained", 0_ra );
parameters.setVariable( "Scalar_multiconstrained", 0.5_ra );
parameters.setVariable( "Color", Ra::Core::Utils::Color::Magenta() );
parameters.setVariable( "Vec2", Ra::Core::Vector2 { 1_ra, 0_ra } );
parameters.setVariable( "Vec3", Ra::Core::Vector3 { 1_ra, 1_ra, 1_ra } );
parameters.setVariable(
"Matrix3",
Ra::Core::Matrix3 { { 0_ra, 0_ra, 0_ra }, { 1_ra, 1_ra, 1_ra }, { 2_ra, 2_ra, 2_ra } } );
parameters.addParameter( "std::vector<int>", std::vector<int> { 0, 1, 2 } );
parameters.setVariable( "std::vector<int>", std::vector<int> { 0, 1, 2 } );

RenderParameters embedded;
embedded.addParameter( "embedded.int value", 1 );
embedded.addParameter( "embedded.scalar value", 1_ra );
parameters.addParameter( "embedded", embedded );
embedded.setVariable( "embedded.int value", 1 );
embedded.setVariable( "embedded.scalar value", 1_ra );
parameters.setVariable( "embedded", embedded );
//! [filling the parameter set to edit ]

//! [Printing several parameters before editing ]
Expand All @@ -223,14 +226,14 @@ int main( int argc, char* argv[] ) {
//! [Printing several parameters before editing ]

//! [Filling the editor with the parameter set ]
editor.setupFromParameters( parameters, parameterSet_metadata );
editor.setupUi( parameters, parameterSet_metadata );
auto printParameter = [&parameters]( const std::string& p ) {
std::cout << "Parameter " << p << " was modified. New value is ";
parameters.visit( ParameterPrinter {},
[p]( const std::string& name ) { return p == name; } );
std::cout << "\n";
};
QObject::connect( &editor, &ParameterSetEditor::parameterModified, printParameter );
QObject::connect( &editor, &VariableSetEditor::parameterModified, printParameter );
dialog.show();
//! [Filling the editor with the parameter set ]

Expand Down
4 changes: 2 additions & 2 deletions examples/RawShaderMaterial/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ class MyParameterProvider : public Ra::Engine::Data::ShaderParameterProvider
// Method called before drawing each frame in Renderer::updateRenderObjectsInternal.
// The name of the parameter corresponds to the shader's uniform name.
auto& renderParameters = getParameters();
renderParameters.addParameter( "aColorUniform", m_colorParameter );
renderParameters.addParameter( "aScalarUniform", m_scalarParameter );
renderParameters.setVariable( "aColorUniform", m_colorParameter );
renderParameters.setVariable( "aScalarUniform", m_scalarParameter );
}
void setOrComputeTheParameterValues() {
// client side computation of the parameters, e.g.
Expand Down
6 changes: 3 additions & 3 deletions examples/TexturedQuad/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Include Radium base application and its simple Gui
#include "Engine/Data/BlinnPhongMaterial.hpp"
#include "Engine/Data/LambertianMaterial.hpp"
#include "Engine/Data/SimpleMaterial.hpp"
#include <Engine/Data/BlinnPhongMaterial.hpp>
#include <Engine/Data/LambertianMaterial.hpp>
#include <Engine/Data/SimpleMaterial.hpp>
#include <Gui/BaseApplication.hpp>
#include <Gui/RadiumWindow/SimpleWindowFactory.hpp>

Expand Down
26 changes: 18 additions & 8 deletions src/Core/Containers/VariableSet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,17 @@ class RA_CORE_API VariableSet
/// \pre The element \b name must exists with type \b T. If not verified (assert in debug mode)
/// std::bad_any_cast exception could be thrown by the underlying management of type erasure
template <typename T>
auto getVariable( const std::string& name ) const -> T&;
auto getVariable( const std::string& name ) const -> const T&;
template <typename T>
auto getVariable( const std::string& name ) -> T&;

/// \brief get the handle on the variable with the given name
/// \tparam T the type of the variable
/// \param name the name of a variable
/// \return an handle which can be de-referenced to obtain a std::pair<const std::string, T>
/// representing the name and the value of the variable.
template <typename T>
auto getVariableHandle( const std::string& name ) const -> VariableHandle<T>;
auto getVariableHandle( const std::string& name ) const -> const VariableHandle<T>;

/// \brief Test the validity of a handle
/// \tparam H Type of the handle. Expected to be VariableHandle<T> for some variable type T
Expand All @@ -186,7 +188,7 @@ class RA_CORE_API VariableSet
/// \return a pair with the variable handle and a bool : true if the variable value was reset,
/// false if the variable value was set.
template <typename T>
auto insertOrAssignVariable( const std::string& name, const T& value )
auto setVariable( const std::string& name, const T& value )
-> std::pair<VariableHandle<T>, bool>;

/// \brief Remove a variable, i.e. a name->value association
Expand Down Expand Up @@ -613,13 +615,17 @@ auto VariableSet::insertVariable( const std::string& name, const T& value )
}

template <typename T>
auto VariableSet::getVariable( const std::string& name ) const -> T& {
assert( existsVariable<T>( name ) );
auto VariableSet::getVariable( const std::string& name ) -> T& {
return const_cast<T&>( const_cast<const VariableSet*>( this )->getVariable<T>( name ) );
}

template <typename T>
auto VariableSet::getVariable( const std::string& name ) const -> const T& {
return getVariableHandle<T>( name )->second;
}

template <typename T>
auto VariableSet::getVariableHandle( const std::string& name ) const -> VariableHandle<T> {
auto VariableSet::getVariableHandle( const std::string& name ) const -> const VariableHandle<T> {
assert( existsVariableType<T>() );
return getVariableStorage<T>().find( name );
}
Expand All @@ -631,12 +637,13 @@ bool VariableSet::isHandleValid( const H& handle ) const {
}

template <typename T>
auto VariableSet::insertOrAssignVariable( const std::string& name, const T& value )
auto VariableSet::setVariable( const std::string& name, const T& value )
-> std::pair<VariableHandle<T>, bool> {
auto typeAccess = existsVariableType<T>();
// If it is the first parameter of the given type, first register the type
if ( !typeAccess ) { typeAccess = addVariableType<T>(); }
// insert the parameter.

return ( *typeAccess )->insert_or_assign( name, value );
}

Expand All @@ -662,6 +669,7 @@ bool VariableSet::deleteVariable( H& handle ) {
template <typename T>
auto VariableSet::existsVariable( const std::string& name ) const
-> Utils::optional<VariableHandle<T>> {

if ( auto typeAccess = existsVariableType<T>(); typeAccess ) {
auto itr = ( *typeAccess )->find( name );
if ( itr != ( *typeAccess )->cend() ) { return itr; }
Expand Down Expand Up @@ -775,6 +783,8 @@ size_t VariableSet::numberOf() const {
return 0;
}

/* --------------- Visitors */

template <typename P>
void VariableSet::visitDynamic( DynamicVisitorBase& visitor, P&& params ) const {
for ( const auto& [type, index] : m_typeIndexToVtableIndex ) {
Expand All @@ -799,7 +809,7 @@ void VariableSet::visitImplHelper( F& visitor ) const {
"Static visitors must provide a function with profile "
"void( const std::string& name, [const ]T[&] value) for each "
"declared visitable type T" );
if ( auto variables = existsVariableType<T>(); variables ) {
if ( auto variables = existsVariableType<T>() ) {
for ( auto& element : *( variables.value() ) ) {
visitor( element.first, element.second );
}
Expand Down
24 changes: 24 additions & 0 deletions src/Core/Containers/VariableSetEnumManagement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <Core/Containers/VariableSetEnumManagement.hpp>

namespace Ra {
namespace Core {
namespace VariableSetEnumManagement {

void setEnumVariable( VariableSet& vs, const std::string& name, const std::string& value ) {
auto converterFunc = vs.existsVariable<
std::function<void( Core::VariableSet&, const std::string&, const std::string& )>>( name );
if ( converterFunc ) { ( *converterFunc )->second( vs, name, value ); }
else {
LOG( Core::Utils::logWARNING ) << "VariableSet: try to set enum value from string without "
"converter, ignored. Variable name: ["
<< name << "], value: [" << value << "]";
}
}

void setEnumVariable( VariableSet& vs, const std::string& name, const char* value ) {
setEnumVariable( vs, name, std::string( value ) );
}

} // namespace VariableSetEnumManagement
} // namespace Core
} // namespace Ra
135 changes: 135 additions & 0 deletions src/Core/Containers/VariableSetEnumManagement.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#pragma once

#include <Core/Containers/VariableSet.hpp>
#include <Core/Utils/EnumConverter.hpp>

#include <string>

/// hepler function to manage enum as underlying types in VariableSet
namespace Ra {
namespace Core {
namespace VariableSetEnumManagement {

/**
* \brief Associate a converter for enumerated type to the given variable name
* \tparam EnumBaseType The enum base type to manage (\see Ra::Core::Utils::EnumConverter)
* \param name
* \param converter
*/
template <typename EnumBaseType>
void addEnumConverter( VariableSet& vs,
const std::string& name,
std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>> converter );

/**
* \brief Search for a converter associated with an enumeration variable
* \tparam EnumBaseType The enum base type to manage (\see Ra::Core::Utils::EnumConverter)
* \param name the name of the parameter
* \return an optional containing the converter or false if no converter is found.
*/
template <typename EnumBaseType>
Core::Utils::optional<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>
getEnumConverter( const VariableSet& vs, const std::string& name );

/**
* \brief Return the string associated to the actual value of an enumeration variable
* \tparam Enum The enum type (\see Ra::Core::Utils::EnumConverter)
* \param name The name of the enum variable
* \param value The value to convert
* \return
*/
template <typename Enum, typename std::enable_if<std::is_enum<Enum> {}, bool>::type = true>
std::string getEnumString( const VariableSet& vs, const std::string& name, Enum value );

/**
* \brief (overload) Return the string associated to the actual value of a n enumeration
* variable, from a value with underlying_type<Enum>. \tparam EnumBaseType The underlying enum
* type (\see Ra::Core::Utils::EnumConverter) \param name The name of the enum variable \param
* value The value to convert \return
*/
template <typename EnumBaseType>
std::string
getEnumString( const VariableSet& vs,
const std::string& name,
EnumBaseType value,
typename std::enable_if<!std::is_enum<EnumBaseType> {}, bool>::type = true );

/**
* \brief set the value of the given enumeration variable, according to a string representation
* of an enum. \note If there is no EnumConverter associated with the variable name, the string
* is registered in the RenderParameter set. \param name Name of the variable \param value value
* of the variable
*/
void RA_CORE_API setEnumVariable( VariableSet& vs,
const std::string& name,
const std::string& value );

void RA_CORE_API setEnumVariable( VariableSet& vs, const std::string& name, const char* value );

template <typename T>
void setEnumVariable( VariableSet& vs, const std::string& name, T value ) {
auto v = static_cast<typename std::underlying_type<T>::type>( value );
vs.setVariable( name, v );
}

template <typename T>
auto getEnumVariable( const VariableSet& vs, const std::string& name ) -> const T& {
static_assert( std::is_enum<T>::value );
return reinterpret_cast<const T&>(
vs.getVariable<typename std::underlying_type<T>::type>( name ) );
}

template <typename T>
auto getEnumVariable( VariableSet& vs, const std::string& name ) -> T& {
return const_cast<T&>( getEnumVariable<T>( const_cast<const VariableSet&>( vs ), name ) );
}

template <typename EnumBaseType>
void addEnumConverter( VariableSet& vs,
const std::string& name,
std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>> converter ) {

// typed converter
auto converterHandle = vs.setVariable( name, converter );

// string string converter/setter for setEnumVariable
std::function<void( Core::VariableSet&, const std::string&, const std::string& )>
convertingFunction = [converter_ = converterHandle.first]( Core::VariableSet& vs_,
const std::string& name_,
const std::string& value_ ) {
vs_.setVariable( name_, converter_->second->getEnumerator( value_ ) );
};
vs.setVariable( name, convertingFunction );
}

template <typename EnumBaseType>
Core::Utils::optional<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>
getEnumConverter( const VariableSet& vs, const std::string& name ) {
auto storedConverter =
vs.existsVariable<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>( name );
if ( storedConverter ) { return ( *storedConverter )->second; }
return {};
}

template <typename EnumBaseType>
std::string getEnumString( const VariableSet& vs,
const std::string& name,
EnumBaseType value,
typename std::enable_if<!std::is_enum<EnumBaseType> {}, bool>::type ) {
auto storedConverter =
vs.existsVariable<std::shared_ptr<Core::Utils::EnumConverter<EnumBaseType>>>( name );
if ( storedConverter ) { return ( *storedConverter )->second->getEnumerator( value ); }
LOG( Ra::Core::Utils::logWARNING ) << name + " is not a registered Enum with underlying type " +
Ra::Core::Utils::demangleType<EnumBaseType>() + ".";
return "";
}

template <typename Enum, typename std::enable_if<std::is_enum<Enum> {}, bool>::type>
std::string getEnumString( const VariableSet& vs, const std::string& name, Enum value ) {
using EnumBaseType = typename std::underlying_type_t<Enum>;
return getEnumString( vs, name, EnumBaseType( value ) );
}

} // namespace VariableSetEnumManagement
} // namespace Core
} // namespace Ra
Loading

0 comments on commit 5db51f5

Please sign in to comment.