From 9c1b7ccdd986f8b0122564907d7f57ad4e773ec8 Mon Sep 17 00:00:00 2001 From: Cyrille Favreau Date: Thu, 22 Feb 2018 17:37:42 +0100 Subject: [PATCH] Allow use of renderers and cameras defined in external modules (#310) --- brayns/Brayns.cpp | 2 +- brayns/common/camera/Camera.h | 2 +- brayns/common/types.h | 4 +- brayns/parameters/RenderingParameters.cpp | 120 +++++++++++------- brayns/parameters/RenderingParameters.h | 7 +- doc/UserGuide.md | 4 +- plugins/engines/ospray/OSPRayCamera.cpp | 29 +---- plugins/engines/ospray/OSPRayCamera.h | 2 +- plugins/engines/ospray/OSPRayEngine.cpp | 61 +++++++-- plugins/engines/ospray/OSPRayEngine.h | 3 + plugins/engines/ospray/OSPRayRenderer.cpp | 5 +- .../extensions/plugins/jsonSerialization.h | 2 +- tests/brayns.cpp | 7 +- tests/braynsTestData.cpp | 2 +- 14 files changed, 155 insertions(+), 95 deletions(-) diff --git a/brayns/Brayns.cpp b/brayns/Brayns.cpp index 575100464..26332ab35 100644 --- a/brayns/Brayns.cpp +++ b/brayns/Brayns.cpp @@ -970,7 +970,7 @@ struct Brayns::Impl { RenderingParameters& renderParams = _parametersManager.getRenderingParameters(); - renderParams.setRenderer(RendererType::basic); + renderParams.setRenderer(RendererType::default_); } void _particleRenderer() diff --git a/brayns/common/camera/Camera.h b/brayns/common/camera/Camera.h index 17e3a5137..6088b57d5 100644 --- a/brayns/common/camera/Camera.h +++ b/brayns/common/camera/Camera.h @@ -215,7 +215,7 @@ class Camera : public BaseObject */ const ClipPlanes& getClipPlanes() const { return _clipPlanes; } private: - CameraType _type{CameraType::perspective}; + CameraType _type{CameraType::default_}; Vector3f _position; Vector3f _target; Vector3f _up; diff --git a/brayns/common/types.h b/brayns/common/types.h index 7d6f5029f..6843bea0a 100644 --- a/brayns/common/types.h +++ b/brayns/common/types.h @@ -179,7 +179,7 @@ class Statistics; /** Types of renderers */ enum class RendererType { - basic, + default_, proximity, simulation, particle, @@ -332,7 +332,7 @@ enum class ShadingType enum class CameraType { - perspective, + default_, // Perspective stereo, orthographic, panoramic, diff --git a/brayns/parameters/RenderingParameters.cpp b/brayns/parameters/RenderingParameters.cpp index 9faa7bc4a..077da58f7 100644 --- a/brayns/parameters/RenderingParameters.cpp +++ b/brayns/parameters/RenderingParameters.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, EPFL/Blue Brain Project +/* Copyright (c) 2015-2018, EPFL/Blue Brain Project * All rights reserved. Do not distribute without permission. * Responsible Author: Cyrille Favreau * @@ -45,30 +45,34 @@ const std::string PARAM_DETECTION_ON_DIFFERENT_MATERIAL = const std::string PARAM_DETECTION_NEAR_COLOR = "detection-near-color"; const std::string PARAM_DETECTION_FAR_COLOR = "detection-far-color"; const std::string PARAM_EPSILON = "epsilon"; -const std::string PARAM_CAMERA_TYPE = "camera-type"; +const std::string PARAM_CAMERA = "camera"; const std::string PARAM_HEAD_LIGHT = "head-light"; const std::string PARAM_VARIANCE_THRESHOLD = "variance-threshold"; -const std::string ENGINES[2] = {"ospray", "optix"}; -const std::string RENDERERS[7] = {"basic", - "proximity", - "simulation", - "particle", - "geometrynormals", - "shadingnormals", - "scientificvisualization"}; -const std::string RENDERER_NAMES[7] = {"basic", - "proximityrenderer", - "simulationrenderer", - "particlerenderer", - "raycast_Ng", - "raycast_Ns", - "scivis"}; +const std::array ENGINES = {"ospray", "optix"}; +const std::array RENDERERS = {"default", + "proximity", + "simulation", + "particle", + "geometrynormals", + "shadingnormals", + "scientificvisualization"}; -const std::string CAMERA_TYPES[5] = {"perspective", "stereo", "orthographic", - "panoramic", "clipped"}; +const std::array RENDERER_INTERNAL_NAMES = { + "basic", + "proximityrenderer", + "simulationrenderer", + "particlerenderer", + "raycast_Ng", + "raycast_Ns", + "scivis"}; -const std::string SHADING_TYPES[3] = {"none", "diffuse", "electron"}; +const std::array CAMERA_TYPE_NAMES = {"perspective", "stereo", + "orthographic", + "panoramic", "clipped"}; + +const std::array SHADING_TYPES = {"none", "diffuse", + "electron"}; } namespace brayns @@ -76,7 +80,8 @@ namespace brayns RenderingParameters::RenderingParameters() : AbstractParameters("Rendering") , _engine(EngineType::ospray) - , _renderer(RendererType::basic) + , _renderer(RendererType::default_) + , _cameraType(CameraType::default_) , _ambientOcclusionStrength(0.f) , _ambientOcclusionDistance(1.20f) , _shading(ShadingType::diffuse) @@ -90,7 +95,6 @@ RenderingParameters::RenderingParameters() , _detectionNearColor(1.f, 0.f, 0.f) , _detectionFarColor(0.f, 1.f, 0.f) , _epsilon(0.f) - , _cameraType(CameraType::perspective) , _headLight(false) { _parameters.add_options()(PARAM_ENGINE.c_str(), po::value(), @@ -98,7 +102,7 @@ RenderingParameters::RenderingParameters() PARAM_MODULE.c_str(), po::value(), "OSPRay module name [string]")( PARAM_RENDERER.c_str(), po::value(), - "OSPRay active renderer [basic|simulation|proximity|particle]")( + "OSPRay active renderer [default|simulation|proximity|particle]")( PARAM_SPP.c_str(), po::value(), "Number of samples per pixel [int]")( PARAM_ACCUMULATION.c_str(), po::value(), @@ -128,15 +132,23 @@ RenderingParameters::RenderingParameters() PARAM_EPSILON.c_str(), po::value(), "All intersection distances less than the " "epsilon value are ignored by the ray-tracer [float]")( - PARAM_CAMERA_TYPE.c_str(), po::value(), - "Camera type [perspective|stereo|orthographic|panoramic]")( + PARAM_CAMERA.c_str(), po::value(), + "Camera [perspective|stereo|orthographic|panoramic]")( PARAM_HEAD_LIGHT.c_str(), po::value(), "Enable/Disable light source attached to camera origin [bool]")( PARAM_VARIANCE_THRESHOLD.c_str(), po::value(), "Threshold for adaptive accumulation [float]"); - // Add default renderers - _renderers.push_back(RendererType::basic); + initializeDefaultRenderers(); + initializeDefaultCameras(); +} + +void RenderingParameters::initializeDefaultRenderers() +{ + _rendererNames = {RENDERER_INTERNAL_NAMES.begin(), + RENDERER_INTERNAL_NAMES.end()}; + _renderers.clear(); + _renderers.push_back(RendererType::default_); _renderers.push_back(RendererType::simulation); _renderers.push_back(RendererType::particle); _renderers.push_back(RendererType::proximity); @@ -145,6 +157,11 @@ RenderingParameters::RenderingParameters() _renderers.push_back(RendererType::scientificvisualization); } +void RenderingParameters::initializeDefaultCameras() +{ + _cameraTypeNames = {CAMERA_TYPE_NAMES.begin(), CAMERA_TYPE_NAMES.end()}; +} + bool RenderingParameters::_parse(const po::variables_map& vm) { if (vm.count(PARAM_ENGINE)) @@ -159,11 +176,19 @@ bool RenderingParameters::_parse(const po::variables_map& vm) _module = vm[PARAM_MODULE].as(); if (vm.count(PARAM_RENDERER)) { - _renderer = RendererType::basic; - const std::string& renderer = vm[PARAM_RENDERER].as(); - for (size_t i = 0; i < sizeof(RENDERERS) / sizeof(RENDERERS[0]); ++i) - if (renderer == RENDERERS[i]) - _renderer = static_cast(i); + _renderer = RendererType::default_; + const std::string& rendererName = vm[PARAM_RENDERER].as(); + auto it = std::find(_rendererNames.begin(), _rendererNames.end(), + rendererName); + if (it == _rendererNames.end()) + { + BRAYNS_INFO << "'" << rendererName << "' replaces default renderer" + << std::endl; + _rendererNames[0] = rendererName; + } + else + _renderer = static_cast( + std::distance(_rendererNames.begin(), it)); } if (vm.count(PARAM_SPP)) _spp = vm[PARAM_SPP].as(); @@ -212,14 +237,21 @@ bool RenderingParameters::_parse(const po::variables_map& vm) } if (vm.count(PARAM_EPSILON)) _epsilon = vm[PARAM_EPSILON].as(); - if (vm.count(PARAM_CAMERA_TYPE)) + if (vm.count(PARAM_CAMERA)) { - _cameraType = CameraType::perspective; - const std::string& cameraType = vm[PARAM_CAMERA_TYPE].as(); - for (size_t i = 0; i < sizeof(CAMERA_TYPES) / sizeof(CAMERA_TYPES[0]); - ++i) - if (cameraType == CAMERA_TYPES[i]) - _cameraType = static_cast(i); + _cameraType = CameraType::default_; + const std::string& cameraTypeName = vm[PARAM_CAMERA].as(); + auto it = std::find(_cameraTypeNames.begin(), _cameraTypeNames.end(), + cameraTypeName); + if (it == _cameraTypeNames.end()) + { + BRAYNS_INFO << "'" << cameraTypeName << "' replaces default camera" + << std::endl; + _cameraTypeNames[0] = cameraTypeName; + } + else + _cameraType = static_cast( + std::distance(_cameraTypeNames.begin(), it)); } if (vm.count(PARAM_HEAD_LIGHT)) _headLight = vm[PARAM_HEAD_LIGHT].as(); @@ -280,19 +312,13 @@ const std::string& RenderingParameters::getEngineAsString( const std::string& RenderingParameters::getRendererAsString( const RendererType value) const { - return RENDERERS[static_cast(value)]; -} - -const std::string& RenderingParameters::getRendererNameAsString( - const RendererType value) const -{ - return RENDERER_NAMES[static_cast(value)]; + return _rendererNames[static_cast(value)]; } const std::string& RenderingParameters::getCameraTypeAsString( const CameraType value) const { - return CAMERA_TYPES[static_cast(value)]; + return _cameraTypeNames[static_cast(value)]; } const std::string& RenderingParameters::getShadingAsString( diff --git a/brayns/parameters/RenderingParameters.h b/brayns/parameters/RenderingParameters.h index 6128befe0..3e127c68f 100644 --- a/brayns/parameters/RenderingParameters.h +++ b/brayns/parameters/RenderingParameters.h @@ -48,9 +48,9 @@ class RenderingParameters : public AbstractParameters /** OSPRay module */ const std::string& getModule() const { return _module; } /** OSPRay renderer */ + void initializeDefaultRenderers(); RendererType getRenderer() const { return _renderer; } const std::string& getRendererAsString(const RendererType value) const; - const std::string& getRendererNameAsString(const RendererType value) const; void setRenderer(const RendererType renderer) { _updateValue(_renderer, renderer); @@ -166,6 +166,7 @@ class RenderingParameters : public AbstractParameters /** Camera type */ + void initializeDefaultCameras(); CameraType getCameraType() const { return _cameraType; } const std::string& getCameraTypeAsString(const CameraType value) const; @@ -204,6 +205,9 @@ class RenderingParameters : public AbstractParameters std::string _module; RendererType _renderer; RendererTypes _renderers; + strings _rendererNames; + CameraType _cameraType; + strings _cameraTypeNames; float _ambientOcclusionStrength; float _ambientOcclusionDistance; ShadingType _shading; @@ -218,7 +222,6 @@ class RenderingParameters : public AbstractParameters Vector3f _detectionNearColor; Vector3f _detectionFarColor; float _epsilon; - CameraType _cameraType; bool _headLight; bool _dynamicLoadBalancer{false}; float _varianceThreshold{-1.f}; diff --git a/doc/UserGuide.md b/doc/UserGuide.md index 12d362708..2be87fdbd 100644 --- a/doc/UserGuide.md +++ b/doc/UserGuide.md @@ -329,7 +329,7 @@ braynsViewer --epsilon 0.001 ## Camera types -The --camera-type command line argument defines the type of camera to be used +The --camera command line argument defines the type of camera to be used by the renderer. Four cameras are currently supported. - perspective: Perspective camera - stereo: Side-by-side camera @@ -338,7 +338,7 @@ by the renderer. Four cameras are currently supported. - clipped: Perspective camera allowing clipping planes ``` -braynsViewer --camera-type orthographic +braynsViewer --camera orthographic ``` ## Head light diff --git a/plugins/engines/ospray/OSPRayCamera.cpp b/plugins/engines/ospray/OSPRayCamera.cpp index bd50d4284..e61bc2c41 100644 --- a/plugins/engines/ospray/OSPRayCamera.cpp +++ b/plugins/engines/ospray/OSPRayCamera.cpp @@ -21,33 +21,18 @@ #include "OSPRayCamera.h" #include +#include + #include namespace brayns { -OSPRayCamera::OSPRayCamera(const CameraType cameraType) - : Camera(cameraType) +OSPRayCamera::OSPRayCamera(const CameraType& type, const std::string& name) + : Camera(type) + , _camera{ospNewCamera(name.c_str())} { - std::string cameraAsString; - switch (getType()) - { - case CameraType::stereo: - cameraAsString = "stereo"; - break; - case CameraType::orthographic: - cameraAsString = "orthographic"; - break; - case CameraType::panoramic: - cameraAsString = "panoramic"; - break; - case CameraType::clipped: - cameraAsString = "clippedperspective"; - break; - default: - cameraAsString = "perspective"; - break; - } - _camera = ospNewCamera(cameraAsString.c_str()); + if (!_camera) + throw std::runtime_error(name + " is not a registered camera"); } OSPRayCamera::~OSPRayCamera() diff --git a/plugins/engines/ospray/OSPRayCamera.h b/plugins/engines/ospray/OSPRayCamera.h index c2a048406..bb0dfb8c5 100644 --- a/plugins/engines/ospray/OSPRayCamera.h +++ b/plugins/engines/ospray/OSPRayCamera.h @@ -34,7 +34,7 @@ namespace brayns class OSPRayCamera : public brayns::Camera { public: - OSPRayCamera(const CameraType cameraType); + OSPRayCamera(const CameraType& type, const std::string& name); ~OSPRayCamera(); /** diff --git a/plugins/engines/ospray/OSPRayEngine.cpp b/plugins/engines/ospray/OSPRayEngine.cpp index 21a538aee..c269ab037 100644 --- a/plugins/engines/ospray/OSPRayEngine.cpp +++ b/plugins/engines/ospray/OSPRayEngine.cpp @@ -97,18 +97,14 @@ OSPRayEngine::OSPRayEngine(int argc, const char** argv, BRAYNS_INFO << "Initializing renderers" << std::endl; _activeRenderer = rp.getRenderer(); - Renderers renderersForScene; - for (const auto renderer : rp.getRenderers()) - { - const auto& rendererName = rp.getRendererNameAsString(renderer); - _renderers[renderer].reset( - new OSPRayRenderer(rendererName, _parametersManager)); - renderersForScene.push_back(_renderers[renderer]); - } + Renderers renderersForScene = _createRenderers(); BRAYNS_INFO << "Initializing scene" << std::endl; _scene.reset(new OSPRayScene(renderersForScene, _parametersManager)); - _camera.reset(new OSPRayCamera(rp.getCameraType())); + + BRAYNS_INFO << "Initializing camera" << std::endl; + _createCamera(); + _camera->setEnvironmentMap( !parametersManager.getSceneParameters().getEnvironmentMap().empty()); @@ -246,4 +242,51 @@ Vector2ui OSPRayEngine::getMinimumFrameSize() const return {TILE_SIZE * 2, TILE_SIZE}; return {TILE_SIZE, TILE_SIZE}; } + +void OSPRayEngine::_createCamera() +{ + auto& rp = _parametersManager.getRenderingParameters(); + const auto cameraType = rp.getCameraType(); + auto cameraTypeAsString = rp.getCameraTypeAsString(cameraType); + try + { + _camera = + std::make_shared(cameraType, cameraTypeAsString); + } + catch (const std::runtime_error& e) + { + BRAYNS_WARN << e.what() << ". Using default camera instead" + << std::endl; + rp.initializeDefaultCameras(); + cameraTypeAsString = rp.getCameraTypeAsString(CameraType::default_); + _camera = + std::make_shared(cameraType, cameraTypeAsString); + } +} + +Renderers OSPRayEngine::_createRenderers() +{ + Renderers renderersForScene; + auto& rp = _parametersManager.getRenderingParameters(); + for (const auto& renderer : rp.getRenderers()) + { + auto name = rp.getRendererAsString(renderer); + try + { + _renderers[renderer] = + std::make_shared(name, _parametersManager); + } + catch (const std::runtime_error& e) + { + BRAYNS_WARN << e.what() << ". Using default renderer instead" + << std::endl; + rp.initializeDefaultRenderers(); + name = rp.getRendererAsString(RendererType::default_); + _renderers[renderer] = + std::make_shared(name, _parametersManager); + } + renderersForScene.push_back(_renderers[renderer]); + } + return renderersForScene; +} } diff --git a/plugins/engines/ospray/OSPRayEngine.h b/plugins/engines/ospray/OSPRayEngine.h index 99b9f090d..aa800d955 100644 --- a/plugins/engines/ospray/OSPRayEngine.h +++ b/plugins/engines/ospray/OSPRayEngine.h @@ -63,6 +63,9 @@ class OSPRayEngine : public Engine /** @copydoc Engine::haveDeflectPixelOp */ bool haveDeflectPixelOp() const final { return _haveDeflectPixelOp; } private: + void _createCamera(); + Renderers _createRenderers(); + bool _haveDeflectPixelOp{false}; bool _useDynamicLoadBalancer{false}; EngineType _type{EngineType::ospray}; diff --git a/plugins/engines/ospray/OSPRayRenderer.cpp b/plugins/engines/ospray/OSPRayRenderer.cpp index b8e199f40..98c50d8fd 100644 --- a/plugins/engines/ospray/OSPRayRenderer.cpp +++ b/plugins/engines/ospray/OSPRayRenderer.cpp @@ -32,9 +32,10 @@ OSPRayRenderer::OSPRayRenderer(const std::string& name, : Renderer(parametersManager) , _name(name) , _camera(0) + , _renderer{ospNewRenderer(name.c_str())} { - _renderer = ospNewRenderer(name.c_str()); - assert(_renderer); + if (!_renderer) + throw std::runtime_error(name + " is not a registered renderer"); } OSPRayRenderer::~OSPRayRenderer() diff --git a/plugins/extensions/plugins/jsonSerialization.h b/plugins/extensions/plugins/jsonSerialization.h index b389557ac..586568e6d 100644 --- a/plugins/extensions/plugins/jsonSerialization.h +++ b/plugins/extensions/plugins/jsonSerialization.h @@ -94,7 +94,7 @@ STATICJSON_DECLARE_ENUM(brayns::MemoryMode, {"replicated", brayns::MemoryMode::replicated}); STATICJSON_DECLARE_ENUM( - brayns::RendererType, {"basic", brayns::RendererType::basic}, + brayns::RendererType, {"default", brayns::RendererType::default_}, {"proximity", brayns::RendererType::proximity}, {"simulation", brayns::RendererType::simulation}, {"particle", brayns::RendererType::particle}, diff --git a/tests/brayns.cpp b/tests/brayns.cpp index c217b7502..464b73842 100644 --- a/tests/brayns.cpp +++ b/tests/brayns.cpp @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(defaults) brayns::Brayns brayns(argc, argv); auto& camera = brayns.getEngine().getCamera(); - BOOST_CHECK(camera.getType() == brayns::CameraType::perspective); + BOOST_CHECK(camera.getType() == brayns::CameraType::default_); BOOST_CHECK_EQUAL(camera.getPosition(), brayns::Vector3f(0.5f, 0.5f, 1.5f)); BOOST_CHECK_EQUAL(camera.getTarget(), brayns::Vector3f(0.5f, 0.5f, 0.5f)); BOOST_CHECK_EQUAL(camera.getUp(), brayns::Vector3f(0, 1, 0)); @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(defaults) const auto& renderParams = pm.getRenderingParameters(); BOOST_CHECK(renderParams.getEngine() == brayns::EngineType::ospray); BOOST_CHECK_EQUAL(renderParams.getModule(), ""); - BOOST_CHECK(renderParams.getRenderer() == brayns::RendererType::basic); + BOOST_CHECK(renderParams.getRenderer() == brayns::RendererType::default_); BOOST_CHECK_EQUAL(renderParams.getRenderers().size(), 7); BOOST_CHECK(!renderParams.getShadows()); BOOST_CHECK(!renderParams.getSoftShadows()); @@ -91,8 +91,7 @@ BOOST_AUTO_TEST_CASE(defaults) brayns::Vector3f(1, 0, 0)); BOOST_CHECK_EQUAL(renderParams.getDetectionFarColor(), brayns::Vector3f(0, 1, 0)); - BOOST_CHECK(renderParams.getCameraType() == - brayns::CameraType::perspective); + BOOST_CHECK(renderParams.getCameraType() == brayns::CameraType::default_); const auto& geomParams = pm.getGeometryParameters(); BOOST_CHECK_EQUAL(geomParams.getMorphologyFolder(), ""); diff --git a/tests/braynsTestData.cpp b/tests/braynsTestData.cpp index fe731a2fd..773498164 100644 --- a/tests/braynsTestData.cpp +++ b/tests/braynsTestData.cpp @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(render_protein_in_stereo_and_compare) "off", "--pdb-file", pdbFile.c_str(), - "--camera-type", + "--camera", "stereo"}; const int argc = sizeof(argv) / sizeof(char*);