diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 501bf5bf20..63de5e0ccd 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -520,23 +520,21 @@ void OpenSpaceEngine::preSynchronization() { //const double dt = sgct::Engine::instance()->getDt(); const double dt = sgct::Engine::instance()->getAvgDt(); - _interactionHandler->update(dt); Time::ref().advanceTime(dt); Time::ref().preSynchronization(); - _interactionHandler.update(dt); + _interactionHandler->update(dt); //_interactionHandler.lockControls(); - _scriptEngine.preSynchronization(); + _scriptEngine->preSynchronization(); _renderEngine->preSynchronization(); } } void OpenSpaceEngine::postSynchronizationPreDraw() { - _renderEngine->postSynchronizationPreDraw(); Time::ref().postSynchronizationPreDraw(); - _scriptEngine.postSynchronizationPreDraw(); - _renderEngine.postSynchronizationPreDraw(); + _scriptEngine->postSynchronizationPreDraw(); + _renderEngine->postSynchronizationPreDraw(); if (sgct::Engine::instance()->isMaster() && _gui->isEnabled()) { double posX, posY; @@ -642,10 +640,9 @@ void OpenSpaceEngine::mouseScrollWheelCallback(int pos) { void OpenSpaceEngine::encode() { if (_syncBuffer) { - _renderEngine->serialize(_syncBuffer); - _scriptEngine.serialize(_syncBuffer); Time::ref().serialize(_syncBuffer); - _renderEngine.serialize(_syncBuffer); + _scriptEngine->serialize(_syncBuffer); + _renderEngine->serialize(_syncBuffer); _syncBuffer->write(); } @@ -654,11 +651,10 @@ void OpenSpaceEngine::encode() { void OpenSpaceEngine::decode() { if (_syncBuffer) { _syncBuffer->read(); - _renderEngine->deserialize(_syncBuffer); - _scriptEngine.deserialize(_syncBuffer); Time::ref().deserialize(_syncBuffer); - _renderEngine.deserialize(_syncBuffer); + _scriptEngine->deserialize(_syncBuffer); + _renderEngine->deserialize(_syncBuffer); } } @@ -676,9 +672,8 @@ void OpenSpaceEngine::externalControlCallback(const char* receivedChars, { std::string script = std::string(receivedChars + 1); LINFO("Received Lua Script: '" << script << "'"); - _scriptEngine->runScript(script); - //_scriptEngine.runScript(script); - _scriptEngine.queueScript(script); + //_scriptEngine->runScript(script); + _scriptEngine->queueScript(script); } } } diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index b5ace527cf..68e3860d75 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -536,8 +536,12 @@ void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz //get "old" focus position psc focus = _camera->focusPosition(); - // get camera position - psc relative = _camera->position(); + //// get camera position + //psc relative = _camera->position(); + + // get camera position (UNSYNCHRONIZED) + psc relative = _camera->unsynchedPosition(); + //get relative vector psc relative_focus_coordinate = relative - focus; //rotate relative vector @@ -855,9 +859,8 @@ void InteractionHandler::keyboardCallback(int key, int action) { _validKeyLua = true; auto ret = _keyLua.equal_range(key); for (auto it = ret.first; it != ret.second; ++it) { - OsEng.scriptEngine()->runScript(it->second); - //OsEng.scriptEngine().runScript(it->second); - OsEng.scriptEngine().queueScript(it->second); + //OsEng.scriptEngine()->runScript(it->second); + OsEng.scriptEngine()->queueScript(it->second); if (!_validKeyLua) { break; } diff --git a/src/interaction/luaconsole.cpp b/src/interaction/luaconsole.cpp index 9cfa7ac987..fcb15901a9 100644 --- a/src/interaction/luaconsole.cpp +++ b/src/interaction/luaconsole.cpp @@ -217,9 +217,8 @@ void LuaConsole::keyboardCallback(int key, int action) { // ENTER == run lua script else { if (_commands.at(_activeCommand) != "") { - OsEng.scriptEngine()->runScript(_commands.at(_activeCommand)); - //OsEng.scriptEngine().runScript(_commands.at(_activeCommand)); - OsEng.scriptEngine().queueScript(_commands.at(_activeCommand)); + //OsEng.scriptEngine()->runScript(_commands.at(_activeCommand)); + OsEng.scriptEngine()->queueScript(_commands.at(_activeCommand)); if (!_commandsHistory.empty() && _commands.at(_activeCommand) != _commandsHistory.at(_commandsHistory.size() - 1)) _commandsHistory.push_back(_commands.at(_activeCommand)); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index f68c9672a7..0d85952dc9 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -74,660 +74,660 @@ namespace { namespace openspace { -const std::string RenderEngine::PerformanceMeasurementSharedData = - "OpenSpacePerformanceMeasurementSharedData"; + const std::string RenderEngine::PerformanceMeasurementSharedData = + "OpenSpacePerformanceMeasurementSharedData"; -namespace luascriptfunctions { + namespace luascriptfunctions { -/** - * \ingroup LuaScripts - * takeScreenshot(): - * Save the rendering to an image file - */ -int takeScreenshot(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 0) - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - OsEng.renderEngine()->takeScreenshot(); - return 0; -} + /** + * \ingroup LuaScripts + * takeScreenshot(): + * Save the rendering to an image file + */ + int takeScreenshot(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 0) + return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); + OsEng.renderEngine()->takeScreenshot(); + return 0; + } -/** -* \ingroup LuaScripts -* visualizeABuffer(bool): -* Toggle the visualization of the ABuffer -*/ -int visualizeABuffer(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 1) - return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + /** + * \ingroup LuaScripts + * visualizeABuffer(bool): + * Toggle the visualization of the ABuffer + */ + int visualizeABuffer(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); - const int type = lua_type(L, -1); - bool b = lua_toboolean(L, -1) != 0; - OsEng.renderEngine()->toggleVisualizeABuffer(b); - return 0; -} + const int type = lua_type(L, -1); + bool b = lua_toboolean(L, -1) != 0; + OsEng.renderEngine()->toggleVisualizeABuffer(b); + return 0; + } -/** -* \ingroup LuaScripts -* visualizeABuffer(bool): -* Toggle the visualization of the ABuffer -*/ -int showRenderInformation(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 1) - return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + /** + * \ingroup LuaScripts + * visualizeABuffer(bool): + * Toggle the visualization of the ABuffer + */ + int showRenderInformation(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); - const int type = lua_type(L, -1); - bool b = lua_toboolean(L, -1) != 0; - OsEng.renderEngine()->toggleInfoText(b); - return 0; -} + const int type = lua_type(L, -1); + bool b = lua_toboolean(L, -1) != 0; + OsEng.renderEngine()->toggleInfoText(b); + return 0; + } -/** -* \ingroup LuaScripts -* visualizeABuffer(bool): -* Toggle the visualization of the ABuffer -*/ -int setPerformanceMeasurement(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 1) - return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + /** + * \ingroup LuaScripts + * visualizeABuffer(bool): + * Toggle the visualization of the ABuffer + */ + int setPerformanceMeasurement(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); - bool b = lua_toboolean(L, -1) != 0; - OsEng.renderEngine()->setPerformanceMeasurements(b); - return 0; -} + bool b = lua_toboolean(L, -1) != 0; + OsEng.renderEngine()->setPerformanceMeasurements(b); + return 0; + } -} // namespace luascriptfunctions + } // namespace luascriptfunctions -RenderEngine::RenderEngine() - : _mainCamera(nullptr) - , _sceneGraph(nullptr) - , _abuffer(nullptr) - , _log(nullptr) - , _showInfo(true) - , _showScreenLog(true) - , _takeScreenshot(false) - , _doPerformanceMeasurements(false) - , _performanceMemory(nullptr) - , _visualizeABuffer(false) - , _visualizer(nullptr) -{ -} + RenderEngine::RenderEngine() + : _mainCamera(nullptr) + , _sceneGraph(nullptr) + , _abuffer(nullptr) + , _log(nullptr) + , _showInfo(true) + , _showScreenLog(true) + , _takeScreenshot(false) + , _doPerformanceMeasurements(false) + , _performanceMemory(nullptr) + , _visualizeABuffer(false) + , _visualizer(nullptr) + { + } -RenderEngine::~RenderEngine() -{ - if(_abuffer) - delete _abuffer; - _abuffer = nullptr; + RenderEngine::~RenderEngine() + { + if (_abuffer) + delete _abuffer; + _abuffer = nullptr; - if(_sceneGraph) - delete _sceneGraph; - _sceneGraph = nullptr; + if (_sceneGraph) + delete _sceneGraph; + _sceneGraph = nullptr; - delete _mainCamera; - if (_visualizer) - delete _visualizer; + delete _mainCamera; + if (_visualizer) + delete _visualizer; - delete _performanceMemory; - if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) - ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); -} + delete _performanceMemory; + if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) + ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); + } -bool RenderEngine::initialize() -{ - generateGlslConfig(); + bool RenderEngine::initialize() + { + generateGlslConfig(); - // init camera and set temporary position and scaling - _mainCamera = new Camera(); - _mainCamera->setScaling(glm::vec2(1.0, -8.0)); - _mainCamera->setPosition(psc(0.f, 0.f, 1.499823f, 11.f)); - OsEng.interactionHandler()->setCamera(_mainCamera); + // init camera and set temporary position and scaling + _mainCamera = new Camera(); + _mainCamera->setScaling(glm::vec2(1.0, -8.0)); + _mainCamera->setPosition(psc(0.f, 0.f, 1.499823f, 11.f)); + OsEng.interactionHandler()->setCamera(_mainCamera); #ifdef GHOUL_USE_DEVIL - ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderDevIL); + ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderDevIL); #endif // GHOUL_USE_DEVIL #ifdef GHOUL_USE_FREEIMAGE - ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderFreeImage); + ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderFreeImage); #endif // GHOUL_USE_FREEIMAGE - ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderCMAP); - + ghoul::io::TextureReader::ref().addReader(new ghoul::io::impl::TextureReaderCMAP); + #if ABUFFER_IMPLEMENTATION == ABUFFER_FRAMEBUFFER - _abuffer = new ABufferFramebuffer(); + _abuffer = new ABufferFramebuffer(); #elif ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED - _abuffer = new ABufferSingleLinked(); + _abuffer = new ABufferSingleLinked(); #elif ABUFFER_IMPLEMENTATION == ABUFFER_FIXED - _abuffer = new ABufferFixed(); + _abuffer = new ABufferFixed(); #elif ABUFFER_IMPLEMENTATION == ABUFFER_DYNAMIC - _abuffer = new ABufferDynamic(); + _abuffer = new ABufferDynamic(); #endif - return true; -} + return true; + } -bool RenderEngine::initializeGL() -{ - // LDEBUG("RenderEngine::initializeGL()"); - sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getActiveWindowPtr(); + bool RenderEngine::initializeGL() + { + // LDEBUG("RenderEngine::initializeGL()"); + sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getActiveWindowPtr(); - // TODO: Fix the power scaled coordinates in such a way that these - // values can be set to more realistic values + // TODO: Fix the power scaled coordinates in such a way that these + // values can be set to more realistic values - // set the close clip plane and the far clip plane to extreme values while in - // development - sgct::Engine::instance()->setNearAndFarClippingPlanes(0.01f,10000.0f); - // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 30.0f); + // set the close clip plane and the far clip plane to extreme values while in + // development + sgct::Engine::instance()->setNearAndFarClippingPlanes(0.01f, 10000.0f); + // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 30.0f); - // calculating the maximum field of view for the camera, used to - // determine visibility of objects in the scene graph - if (wPtr->isUsingFisheyeRendering()) { - // fisheye mode, looking upwards to the "dome" - glm::vec4 upDirection(0, 1, 0, 0); + // calculating the maximum field of view for the camera, used to + // determine visibility of objects in the scene graph + if (wPtr->isUsingFisheyeRendering()) { + // fisheye mode, looking upwards to the "dome" + glm::vec4 upDirection(0, 1, 0, 0); - // get the tilt and rotate the view - const float tilt = wPtr->getFisheyeTilt(); - glm::mat4 tiltMatrix - = glm::rotate(glm::mat4(1.0f), tilt, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::vec4 viewdir = tiltMatrix * upDirection; + // get the tilt and rotate the view + const float tilt = wPtr->getFisheyeTilt(); + glm::mat4 tiltMatrix + = glm::rotate(glm::mat4(1.0f), tilt, glm::vec3(1.0f, 0.0f, 0.0f)); + const glm::vec4 viewdir = tiltMatrix * upDirection; - // set the tilted view and the FOV - _mainCamera->setCameraDirection(glm::vec3(viewdir[0], viewdir[1], viewdir[2])); - _mainCamera->setMaxFov(wPtr->getFisheyeFOV()); - _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); - } else { - // get corner positions, calculating the forth to easily calculate center - glm::vec3 corners[4]; - corners[0] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::Viewport::LowerLeft); - corners[1] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::Viewport::UpperLeft); - corners[2] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::Viewport::UpperRight); - corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); - const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]) - / 4.0f; + // set the tilted view and the FOV + _mainCamera->setCameraDirection(glm::vec3(viewdir[0], viewdir[1], viewdir[2])); + _mainCamera->setMaxFov(wPtr->getFisheyeFOV()); + _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); + } + else { + // get corner positions, calculating the forth to easily calculate center + glm::vec3 corners[4]; + corners[0] = wPtr->getCurrentViewport()->getViewPlaneCoords( + sgct_core::Viewport::LowerLeft); + corners[1] = wPtr->getCurrentViewport()->getViewPlaneCoords( + sgct_core::Viewport::UpperLeft); + corners[2] = wPtr->getCurrentViewport()->getViewPlaneCoords( + sgct_core::Viewport::UpperRight); + corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); + const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]) + / 4.0f; #if 0 -// @TODO Remove the ifdef when the next SGCT version is released that requests the -// getUserPtr to get a name parameter ---abock + // @TODO Remove the ifdef when the next SGCT version is released that requests the + // getUserPtr to get a name parameter ---abock - // set the eye position, useful during rendering - const glm::vec3 eyePosition - = sgct_core::ClusterManager::instance()->getUserPtr("")->getPos(); + // set the eye position, useful during rendering + const glm::vec3 eyePosition + = sgct_core::ClusterManager::instance()->getUserPtr("")->getPos(); #else - const glm::vec3 eyePosition - = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); + const glm::vec3 eyePosition + = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); #endif - // get viewdirection, stores the direction in the camera, used for culling - const glm::vec3 viewdir = glm::normalize(eyePosition - center); - _mainCamera->setCameraDirection(-viewdir); - _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); + // get viewdirection, stores the direction in the camera, used for culling + const glm::vec3 viewdir = glm::normalize(eyePosition - center); + _mainCamera->setCameraDirection(-viewdir); + _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); - // set the initial fov to be 0.0 which means everything will be culled - float maxFov = 0.0f; + // set the initial fov to be 0.0 which means everything will be culled + float maxFov = 0.0f; - // for each corner - for (int i = 0; i < 4; ++i) { - // calculate radians to corner - glm::vec3 dir = glm::normalize(eyePosition - corners[i]); - float radsbetween = acos(glm::dot(viewdir, dir)) - / (glm::length(viewdir) * glm::length(dir)); + // for each corner + for (int i = 0; i < 4; ++i) { + // calculate radians to corner + glm::vec3 dir = glm::normalize(eyePosition - corners[i]); + float radsbetween = acos(glm::dot(viewdir, dir)) + / (glm::length(viewdir) * glm::length(dir)); - // the angle to a corner is larger than the current maxima - if (radsbetween > maxFov) { - maxFov = radsbetween; - } - } - _mainCamera->setMaxFov(maxFov); - } - - _abuffer->initialize(); - - _log = new ScreenLog(); - ghoul::logging::LogManager::ref().addLog(_log); + // the angle to a corner is larger than the current maxima + if (radsbetween > maxFov) { + maxFov = radsbetween; + } + } + _mainCamera->setMaxFov(maxFov); + } - _visualizer = new ABufferVisualizer(); + _abuffer->initialize(); - // successful init - return true; -} + _log = new ScreenLog(); + ghoul::logging::LogManager::ref().addLog(_log); -void RenderEngine::preSynchronization(){ - if (_mainCamera){ - _mainCamera->preSynchronization(); + _visualizer = new ABufferVisualizer(); + + // successful init + return true; } -} -void RenderEngine::postSynchronizationPreDraw() -{ - if (_mainCamera){ - _mainCamera->postSynchronizationPreDraw(); - } - - sgct_core::SGCTNode * thisNode = sgct_core::ClusterManager::instance()->getThisNodePtr(); - bool updateAbuffer = false; - for (unsigned int i = 0; i < thisNode->getNumberOfWindows(); i++) { - if (sgct::Engine::instance()->getWindowPtr(i)->isWindowResized()) { - updateAbuffer = true; - break; + void RenderEngine::preSynchronization(){ + if (_mainCamera){ + _mainCamera->preSynchronization(); } } - if (updateAbuffer) { - generateGlslConfig(); - _abuffer->reinitialize(); - } - - // converts the quaternion used to rotation matrices - _mainCamera->compileViewRotationMatrix(); - UpdateData a = { Time::ref().currentTime(), Time::ref().deltaTime() }; - // update and evaluate the scene starting from the root node - _sceneGraph->update({ - Time::ref().currentTime(), - Time::ref().deltaTime(), - _doPerformanceMeasurements - }); + void RenderEngine::postSynchronizationPreDraw() + { + if (_mainCamera){ + _mainCamera->postSynchronizationPreDraw(); + } - _sceneGraph->evaluate(_mainCamera); + sgct_core::SGCTNode * thisNode = sgct_core::ClusterManager::instance()->getThisNodePtr(); + bool updateAbuffer = false; + for (unsigned int i = 0; i < thisNode->getNumberOfWindows(); i++) { + if (sgct::Engine::instance()->getWindowPtr(i)->isWindowResized()) { + updateAbuffer = true; + break; + } + } + if (updateAbuffer) { + generateGlslConfig(); + _abuffer->reinitialize(); + } - // clear the abuffer before rendering the scene - _abuffer->clear(); - - //Allow focus node to update camera (enables camera-following) - //FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES - if (const SceneGraphNode* node = OsEng.ref().interactionHandler()->focusNode()){ - /*if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){ - node->updateCamera(_mainCamera); - }*/ - -} + // converts the quaternion used to rotation matrices + _mainCamera->compileViewRotationMatrix(); + UpdateData a = { Time::ref().currentTime(), Time::ref().deltaTime() }; -void RenderEngine::render() -{ - // We need the window pointer - sgct::SGCTWindow* w = sgct::Engine::instance()->getActiveWindowPtr(); - if (w->isUsingFisheyeRendering()) - _abuffer->clear(); - - // SGCT resets certain settings -#ifndef __APPLE__ - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); -#else - glEnable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); -#endif - // setup the camera for the current frame - -#if 0 -// @TODO: Use this as soon as the new SGCT version is available ---abock - const glm::vec3 eyePosition - = sgct_core::ClusterManager::instance()->getUserPtr("")->getPos(); -#else - const glm::vec3 eyePosition - = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); -#endif - //@CHECK does the dome disparity disappear if this line disappears? ---abock - const glm::mat4 view - = glm::translate(glm::mat4(1.0), - eyePosition); // make sure the eye is in the center - _mainCamera->setViewProjectionMatrix( - sgct::Engine::instance()->getActiveModelViewProjectionMatrix() * view); - - _mainCamera->setModelMatrix( - sgct::Engine::instance()->getModelMatrix()); - - _mainCamera->setViewMatrix( - sgct::Engine::instance()->getActiveViewMatrix()* view); - - _mainCamera->setProjectionMatrix( - sgct::Engine::instance()->getActiveProjectionMatrix()); - - - // render the scene starting from the root node - if (!_visualizeABuffer) { - _abuffer->preRender(); - _sceneGraph->render({ - *_mainCamera, - psc(), + // update and evaluate the scene starting from the root node + _sceneGraph->update({ + Time::ref().currentTime(), + Time::ref().deltaTime(), _doPerformanceMeasurements }); - _abuffer->postRender(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - _abuffer->resolve(); - glDisable(GL_BLEND); + _sceneGraph->evaluate(_mainCamera); + + // clear the abuffer before rendering the scene + _abuffer->clear(); + + //Allow focus node to update camera (enables camera-following) + //FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES + //if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){ + //node->updateCamera(_mainCamera); + //} + } - else { - _visualizer->render(); - } - + + void RenderEngine::render() + { + // We need the window pointer + sgct::SGCTWindow* w = sgct::Engine::instance()->getActiveWindowPtr(); + if (w->isUsingFisheyeRendering()) + _abuffer->clear(); + + // SGCT resets certain settings +#ifndef __APPLE__ + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); +#else + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); +#endif + // setup the camera for the current frame + +#if 0 + // @TODO: Use this as soon as the new SGCT version is available ---abock + const glm::vec3 eyePosition + = sgct_core::ClusterManager::instance()->getUserPtr("")->getPos(); +#else + const glm::vec3 eyePosition + = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); +#endif + //@CHECK does the dome disparity disappear if this line disappears? ---abock + const glm::mat4 view + = glm::translate(glm::mat4(1.0), + eyePosition); // make sure the eye is in the center + _mainCamera->setViewProjectionMatrix( + sgct::Engine::instance()->getActiveModelViewProjectionMatrix() * view); + + _mainCamera->setModelMatrix( + sgct::Engine::instance()->getModelMatrix()); + + _mainCamera->setViewMatrix( + sgct::Engine::instance()->getActiveViewMatrix()* view); + + _mainCamera->setProjectionMatrix( + sgct::Engine::instance()->getActiveProjectionMatrix()); + + + // render the scene starting from the root node + if (!_visualizeABuffer) { + _abuffer->preRender(); + _sceneGraph->render({ + *_mainCamera, + psc(), + _doPerformanceMeasurements + }); + _abuffer->postRender(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + _abuffer->resolve(); + glDisable(GL_BLEND); + } + else { + _visualizer->render(); + } + #if 1 - - // Print some useful information on the master viewport - if (sgct::Engine::instance()->isMaster() && ! w->isUsingFisheyeRendering()) { - // TODO: Adjust font_size properly when using retina screen - const int font_size_mono = 10; - const int font_size_light = 8; - const int font_with_light = static_cast(font_size_light*0.7); - const sgct_text::Font* fontLight = sgct_text::FontManager::instance()->getFont(constants::fonts::keyLight, font_size_light); - const sgct_text::Font* fontMono = sgct_text::FontManager::instance()->getFont(constants::fonts::keyMono, font_size_mono); - - if (_showInfo) { - const sgct_text::Font* font = fontMono; - int x1, xSize, y1, ySize; - sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); - int startY = ySize - 2 * font_size_mono; - const glm::vec2 scaling = _mainCamera->scaling(); - const glm::vec3 viewdirection = _mainCamera->viewDirection(); - const psc position = _mainCamera->position(); - const psc origin = OsEng.interactionHandler()->focusNode()->worldPosition(); - const PowerScaledScalar pssl = (position - origin).length(); + // Print some useful information on the master viewport + if (sgct::Engine::instance()->isMaster() && !w->isUsingFisheyeRendering()) { - // GUI PRINT -// Using a macro to shorten line length and increase readability + // TODO: Adjust font_size properly when using retina screen + const int font_size_mono = 10; + const int font_size_light = 8; + const int font_with_light = static_cast(font_size_light*0.7); + const sgct_text::Font* fontLight = sgct_text::FontManager::instance()->getFont(constants::fonts::keyLight, font_size_light); + const sgct_text::Font* fontMono = sgct_text::FontManager::instance()->getFont(constants::fonts::keyMono, font_size_mono); + + if (_showInfo) { + const sgct_text::Font* font = fontMono; + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + int startY = ySize - 2 * font_size_mono; + const glm::vec2 scaling = _mainCamera->scaling(); + const glm::vec3 viewdirection = _mainCamera->viewDirection(); + const psc position = _mainCamera->position(); + const psc origin = OsEng.interactionHandler()->focusNode()->worldPosition(); + const PowerScaledScalar pssl = (position - origin).length(); + + // GUI PRINT + // Using a macro to shorten line length and increase readability #define PrintText(i, format, ...) Freetype::print(font, 10.f, static_cast(startY - font_size_mono * i * 2), format, __VA_ARGS__); - int i = 0; - PrintText(i++, "Date: %s", Time::ref().currentTimeUTC().c_str()); - PrintText(i++, "Avg. Frametime: %.5f", sgct::Engine::instance()->getAvgDt()); - PrintText(i++, "Drawtime: %.5f", sgct::Engine::instance()->getDrawTime()); - PrintText(i++, "Frametime: %.5f", sgct::Engine::instance()->getDt()); - PrintText(i++, "Origin: (% .5f, % .5f, % .5f, % .5f)", origin[0], origin[1], origin[2], origin[3]); - PrintText(i++, "Cam pos: (% .5f, % .5f, % .5f, % .5f)", position[0], position[1], position[2], position[3]); - PrintText(i++, "View dir: (% .5f, % .5f, % .5f)", viewdirection[0], viewdirection[1], viewdirection[2]); - PrintText(i++, "Cam->origin: (% .15f, % .4f)", pssl[0], pssl[1]); - PrintText(i++, "Scaling: (% .5f, % .5f)", scaling[0], scaling[1]); + int i = 0; + PrintText(i++, "Date: %s", Time::ref().currentTimeUTC().c_str()); + PrintText(i++, "Avg. Frametime: %.5f", sgct::Engine::instance()->getAvgDt()); + PrintText(i++, "Drawtime: %.5f", sgct::Engine::instance()->getDrawTime()); + PrintText(i++, "Frametime: %.5f", sgct::Engine::instance()->getDt()); + PrintText(i++, "Origin: (% .5f, % .5f, % .5f, % .5f)", origin[0], origin[1], origin[2], origin[3]); + PrintText(i++, "Cam pos: (% .5f, % .5f, % .5f, % .5f)", position[0], position[1], position[2], position[3]); + PrintText(i++, "View dir: (% .5f, % .5f, % .5f)", viewdirection[0], viewdirection[1], viewdirection[2]); + PrintText(i++, "Cam->origin: (% .15f, % .4f)", pssl[0], pssl[1]); + PrintText(i++, "Scaling: (% .5f, % .5f)", scaling[0], scaling[1]); #undef PrintText - } - - if (_showScreenLog) - { - const sgct_text::Font* font = fontLight; - const int max = 10; - const int category_length = 20; - const int msg_length = 140; - const float ttl = 15.f; - const float fade = 5.f; - auto entries = _log->last(max); - - const glm::vec4 white(0.9, 0.9, 0.9, 1); - const glm::vec4 red(1, 0, 0, 1); - const glm::vec4 yellow(1, 1, 0, 1); - const glm::vec4 green(0, 1, 0, 1); - const glm::vec4 blue(0, 0, 1, 1); - - size_t nr = 1; - for (auto& it = entries.first; it != entries.second; ++it) { - const ScreenLog::LogEntry* e = &(*it); - - const double t = sgct::Engine::instance()->getTime(); - float diff = static_cast(t - e->timeStamp); - - // Since all log entries are ordered, once one is exceeding TTL, all have - if (diff > ttl) - break; - - float alpha = 1; - float ttf = ttl - fade; - if (diff > ttf) { - diff = diff - ttf; - float p = 0.8f - diff / fade; - alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); } - // Since all log entries are ordered, once one exceeds alpha, all have - if (alpha <= 0.0) - break; + if (_showScreenLog) + { + const sgct_text::Font* font = fontLight; + const int max = 10; + const int category_length = 20; + const int msg_length = 140; + const float ttl = 15.f; + const float fade = 5.f; + auto entries = _log->last(max); - const std::string lvl = "(" + ghoul::logging::LogManager::stringFromLevel(e->level) + ")"; - const std::string& message = e->message.substr(0, msg_length); - nr += std::count(message.begin(), message.end(), '\n'); + const glm::vec4 white(0.9, 0.9, 0.9, 1); + const glm::vec4 red(1, 0, 0, 1); + const glm::vec4 yellow(1, 1, 0, 1); + const glm::vec4 green(0, 1, 0, 1); + const glm::vec4 blue(0, 0, 1, 1); - Freetype::print(font, 10.f, static_cast(font_size_light * nr * 2), white*alpha, - "%-14s %s%s", // Format - e->timeString.c_str(), // Time string - e->category.substr(0, category_length).c_str(), // Category string (up to category_length) - e->category.length() > 20 ? "..." : ""); // Pad category with "..." if exceeds category_length + size_t nr = 1; + for (auto& it = entries.first; it != entries.second; ++it) { + const ScreenLog::LogEntry* e = &(*it); - glm::vec4 color = white; - if (e->level == ghoul::logging::LogManager::LogLevel::Debug) - color = green; - if (e->level == ghoul::logging::LogManager::LogLevel::Warning) - color = yellow; - if (e->level == ghoul::logging::LogManager::LogLevel::Error) - color = red; - if (e->level == ghoul::logging::LogManager::LogLevel::Fatal) - color = blue; + const double t = sgct::Engine::instance()->getTime(); + float diff = static_cast(t - e->timeStamp); - Freetype::print(font, static_cast(10 + 39 * font_with_light), static_cast(font_size_light * nr * 2), color*alpha, "%s", lvl.c_str()); + // Since all log entries are ordered, once one is exceeding TTL, all have + if (diff > ttl) + break; - - Freetype::print(font, static_cast(10 + 53 * font_with_light), static_cast(font_size_light * nr * 2), white*alpha, "%s", message.c_str()); - ++nr; + float alpha = 1; + float ttf = ttl - fade; + if (diff > ttf) { + diff = diff - ttf; + float p = 0.8f - diff / fade; + alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); + } + + // Since all log entries are ordered, once one exceeds alpha, all have + if (alpha <= 0.0) + break; + + const std::string lvl = "(" + ghoul::logging::LogManager::stringFromLevel(e->level) + ")"; + const std::string& message = e->message.substr(0, msg_length); + nr += std::count(message.begin(), message.end(), '\n'); + + Freetype::print(font, 10.f, static_cast(font_size_light * nr * 2), white*alpha, + "%-14s %s%s", // Format + e->timeString.c_str(), // Time string + e->category.substr(0, category_length).c_str(), // Category string (up to category_length) + e->category.length() > 20 ? "..." : ""); // Pad category with "..." if exceeds category_length + + glm::vec4 color = white; + if (e->level == ghoul::logging::LogManager::LogLevel::Debug) + color = green; + if (e->level == ghoul::logging::LogManager::LogLevel::Warning) + color = yellow; + if (e->level == ghoul::logging::LogManager::LogLevel::Error) + color = red; + if (e->level == ghoul::logging::LogManager::LogLevel::Fatal) + color = blue; + + Freetype::print(font, static_cast(10 + 39 * font_with_light), static_cast(font_size_light * nr * 2), color*alpha, "%s", lvl.c_str()); + + + Freetype::print(font, static_cast(10 + 53 * font_with_light), static_cast(font_size_light * nr * 2), white*alpha, "%s", message.c_str()); + ++nr; + } + } + } +#endif + } + + void RenderEngine::postDraw() { + if (_takeScreenshot) { + sgct::Engine::instance()->takeScreenshot(); + _takeScreenshot = false; + } + + if (_doPerformanceMeasurements) + storePerformanceMeasurements(); + } + + void RenderEngine::takeScreenshot() { + _takeScreenshot = true; + } + + void RenderEngine::toggleVisualizeABuffer(bool b) { + _visualizeABuffer = b; + if (!_visualizeABuffer) + return; + + std::vector _d = _abuffer->pixelData(); + _visualizer->updateData(_d); + } + + + void RenderEngine::toggleInfoText(bool b) { + _showInfo = b; + } + + SceneGraph* RenderEngine::sceneGraph() + { + // TODO custom assert (ticket #5) + assert(_sceneGraph); + return _sceneGraph; + } + + void RenderEngine::setSceneGraph(SceneGraph* sceneGraph) + { + _sceneGraph = sceneGraph; + } + + void RenderEngine::serialize(SyncBuffer* syncBuffer) { + if (_mainCamera){ + _mainCamera->serialize(syncBuffer); } } - } -#endif -} -void RenderEngine::postDraw() { - if (_takeScreenshot) { - sgct::Engine::instance()->takeScreenshot(); - _takeScreenshot = false; - } + void RenderEngine::deserialize(SyncBuffer* syncBuffer) { + if (_mainCamera){ + _mainCamera->deserialize(syncBuffer); + } + } - if (_doPerformanceMeasurements) - storePerformanceMeasurements(); -} + Camera* RenderEngine::camera() const { + return _mainCamera; + } -void RenderEngine::takeScreenshot() { - _takeScreenshot = true; -} + ABuffer* RenderEngine::abuffer() const { + return _abuffer; + } -void RenderEngine::toggleVisualizeABuffer(bool b) { - _visualizeABuffer = b; - if (!_visualizeABuffer) - return; + void RenderEngine::generateGlslConfig() { + LDEBUG("Generating GLSLS config, expect shader recompilation"); + int xSize = sgct::Engine::instance()->getActiveWindowPtr()->getXFramebufferResolution();; + int ySize = sgct::Engine::instance()->getActiveWindowPtr()->getYFramebufferResolution();; - std::vector _d = _abuffer->pixelData(); - _visualizer->updateData(_d); -} - - -void RenderEngine::toggleInfoText(bool b) { - _showInfo = b; -} - -SceneGraph* RenderEngine::sceneGraph() -{ - // TODO custom assert (ticket #5) - assert(_sceneGraph); - return _sceneGraph; -} - -void RenderEngine::setSceneGraph(SceneGraph* sceneGraph) -{ - _sceneGraph = sceneGraph; -} - -void RenderEngine::serialize(SyncBuffer* syncBuffer) { - if (_mainCamera){ - _mainCamera->serialize(syncBuffer); - } -} - -void RenderEngine::deserialize(SyncBuffer* syncBuffer) { - if (_mainCamera){ - _mainCamera->deserialize(syncBuffer); - } -} - -Camera* RenderEngine::camera() const { - return _mainCamera; -} - -ABuffer* RenderEngine::abuffer() const { - return _abuffer; -} - -void RenderEngine::generateGlslConfig() { - LDEBUG("Generating GLSLS config, expect shader recompilation"); - int xSize = sgct::Engine::instance()->getActiveWindowPtr()->getXFramebufferResolution();; - int ySize = sgct::Engine::instance()->getActiveWindowPtr()->getYFramebufferResolution();; - - // TODO: Make this file creation dynamic and better in every way - // TODO: If the screen size changes it is enough if this file is regenerated to - // recompile all necessary files - std::ofstream os(absPath("${SHADERS_GENERATED}/constants.hglsl")); - os << "#ifndef CONSTANTS_HGLSL\n" - << "#define CONSTANTS_HGLSL\n" - << "#define SCREEN_WIDTH " << xSize << "\n" - << "#define SCREEN_HEIGHT " << ySize << "\n" - << "#define MAX_LAYERS " << ABuffer::MAX_LAYERS << "\n" - << "#define ABUFFER_FRAMEBUFFER " << ABUFFER_FRAMEBUFFER << "\n" - << "#define ABUFFER_SINGLE_LINKED " << ABUFFER_SINGLE_LINKED << "\n" - << "#define ABUFFER_FIXED " << ABUFFER_FIXED << "\n" - << "#define ABUFFER_DYNAMIC " << ABUFFER_DYNAMIC << "\n" - << "#define ABUFFER_IMPLEMENTATION " << ABUFFER_IMPLEMENTATION << "\n"; -// System specific + // TODO: Make this file creation dynamic and better in every way + // TODO: If the screen size changes it is enough if this file is regenerated to + // recompile all necessary files + std::ofstream os(absPath("${SHADERS_GENERATED}/constants.hglsl")); + os << "#ifndef CONSTANTS_HGLSL\n" + << "#define CONSTANTS_HGLSL\n" + << "#define SCREEN_WIDTH " << xSize << "\n" + << "#define SCREEN_HEIGHT " << ySize << "\n" + << "#define MAX_LAYERS " << ABuffer::MAX_LAYERS << "\n" + << "#define ABUFFER_FRAMEBUFFER " << ABUFFER_FRAMEBUFFER << "\n" + << "#define ABUFFER_SINGLE_LINKED " << ABUFFER_SINGLE_LINKED << "\n" + << "#define ABUFFER_FIXED " << ABUFFER_FIXED << "\n" + << "#define ABUFFER_DYNAMIC " << ABUFFER_DYNAMIC << "\n" + << "#define ABUFFER_IMPLEMENTATION " << ABUFFER_IMPLEMENTATION << "\n"; + // System specific #ifdef WIN32 - os << "#define WIN32\n"; + os << "#define WIN32\n"; #endif #ifdef __APPLE__ - os << "#define APPLE\n"; + os << "#define APPLE\n"; #endif #ifdef __linux__ - os << "#define linux\n"; + os << "#define linux\n"; #endif - os << "#endif\n"; + os << "#endif\n"; - os.close(); -} - -scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { - return { - "", - { - { - "takeScreenshot", - &luascriptfunctions::takeScreenshot, - "", - "Renders the current image to a file on disk" - }, - { - "visualizeABuffer", - &luascriptfunctions::visualizeABuffer, - "bool", - "Toggles the visualization of the ABuffer" - }, - { - "showRenderInformation", - &luascriptfunctions::showRenderInformation, - "bool", - "Toggles the showing of render information on-screen text" - }, - { - "setPerformanceMeasurement", - &luascriptfunctions::setPerformanceMeasurement, - "bool", - "Sets the performance measurements" - } - }, - }; -} - -void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) { - _doPerformanceMeasurements = performanceMeasurements; -} - -bool RenderEngine::doesPerformanceMeasurements() const { - return _doPerformanceMeasurements; -} - -void RenderEngine::storePerformanceMeasurements() { - const int8_t Version = 0; - const int nValues = 250; - const int lengthName = 256; - const int maxValues = 50; - - struct PerformanceLayout { - int8_t version; - int32_t nValuesPerEntry; - int32_t nEntries; - int32_t maxNameLength; - int32_t maxEntries; - - struct PerformanceLayoutEntry { - char name[lengthName]; - float renderTime[nValues]; - float updateRenderable[nValues]; - float updateEphemeris[nValues]; - - int32_t currentRenderTime; - int32_t currentUpdateRenderable; - int32_t currentUpdateEphemeris; - }; - - PerformanceLayoutEntry entries[maxValues]; - }; - - const int nNodes = static_cast(sceneGraph()->allSceneGraphNodes().size()); - if (!_performanceMemory) { - - // Compute the total size - const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) + - maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry); - LINFO("Create shared memory of " << totalSize << " bytes"); - - ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); - _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); - - PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); - layout->version = Version; - layout->nValuesPerEntry = nValues; - layout->nEntries = nNodes; - layout->maxNameLength = lengthName; - layout->maxEntries = maxValues; - - memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry)); - - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i]; - - memset(layout->entries[i].name, 0, lengthName); - strcpy(layout->entries[i].name, node->name().c_str()); - - layout->entries[i].currentRenderTime = 0; - layout->entries[i].currentUpdateRenderable = 0; - layout->entries[i].currentUpdateEphemeris = 0; + os.close(); } - } - PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); - _performanceMemory->acquireLock(); - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i]; - SceneGraphNode::PerformanceRecord r = node->performanceRecord(); - PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; + scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { + return{ + "", + { + { + "takeScreenshot", + &luascriptfunctions::takeScreenshot, + "", + "Renders the current image to a file on disk" + }, + { + "visualizeABuffer", + &luascriptfunctions::visualizeABuffer, + "bool", + "Toggles the visualization of the ABuffer" + }, + { + "showRenderInformation", + &luascriptfunctions::showRenderInformation, + "bool", + "Toggles the showing of render information on-screen text" + }, + { + "setPerformanceMeasurement", + &luascriptfunctions::setPerformanceMeasurement, + "bool", + "Sets the performance measurements" + } + }, + }; + } - entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f; - entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f; - entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f; + void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) { + _doPerformanceMeasurements = performanceMeasurements; + } - entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues; - entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues; - entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues; - } - _performanceMemory->releaseLock(); -} + bool RenderEngine::doesPerformanceMeasurements() const { + return _doPerformanceMeasurements; + } -} // namespace openspace + void RenderEngine::storePerformanceMeasurements() { + const int8_t Version = 0; + const int nValues = 250; + const int lengthName = 256; + const int maxValues = 50; + + struct PerformanceLayout { + int8_t version; + int32_t nValuesPerEntry; + int32_t nEntries; + int32_t maxNameLength; + int32_t maxEntries; + + struct PerformanceLayoutEntry { + char name[lengthName]; + float renderTime[nValues]; + float updateRenderable[nValues]; + float updateEphemeris[nValues]; + + int32_t currentRenderTime; + int32_t currentUpdateRenderable; + int32_t currentUpdateEphemeris; + }; + + PerformanceLayoutEntry entries[maxValues]; + }; + + const int nNodes = static_cast(sceneGraph()->allSceneGraphNodes().size()); + if (!_performanceMemory) { + + // Compute the total size + const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) + + maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry); + LINFO("Create shared memory of " << totalSize << " bytes"); + + ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); + _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); + + PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); + layout->version = Version; + layout->nValuesPerEntry = nValues; + layout->nEntries = nNodes; + layout->maxNameLength = lengthName; + layout->maxEntries = maxValues; + + memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry)); + + for (int i = 0; i < nNodes; ++i) { + SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i]; + + memset(layout->entries[i].name, 0, lengthName); + strcpy(layout->entries[i].name, node->name().c_str()); + + layout->entries[i].currentRenderTime = 0; + layout->entries[i].currentUpdateRenderable = 0; + layout->entries[i].currentUpdateEphemeris = 0; + } + } + + PerformanceLayout* layout = reinterpret_cast(_performanceMemory->pointer()); + _performanceMemory->acquireLock(); + for (int i = 0; i < nNodes; ++i) { + SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i]; + SceneGraphNode::PerformanceRecord r = node->performanceRecord(); + PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; + + entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f; + entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f; + entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f; + + entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues; + entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues; + entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues; + } + _performanceMemory->releaseLock(); + } + +}// namespace openspace