mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-21 04:19:19 -06:00
Restructured SceneGraphNode code
This commit is contained in:
@@ -36,8 +36,8 @@ namespace openspace {
|
||||
|
||||
class Renderable : public properties::PropertyOwner {
|
||||
public:
|
||||
// constructors & destructor
|
||||
Renderable(const ghoul::Dictionary& dictionary);
|
||||
// constructors & destructor
|
||||
Renderable(const ghoul::Dictionary& dictionary);
|
||||
virtual ~Renderable();
|
||||
|
||||
void setName(std::string name);
|
||||
@@ -45,22 +45,21 @@ public:
|
||||
|
||||
virtual bool initialize() = 0;
|
||||
virtual bool deinitialize() = 0;
|
||||
|
||||
void setBoundingSphere(const pss &boundingSphere);
|
||||
const pss &getBoundingSphere();
|
||||
|
||||
virtual void render(const Camera *camera, const psc &thisPosition) = 0;
|
||||
virtual void update();
|
||||
void setBoundingSphere(const pss& boundingSphere);
|
||||
const pss& getBoundingSphere();
|
||||
|
||||
virtual void render(const Camera* camera, const psc& thisPosition) = 0;
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
//Renderable();
|
||||
// Renderable();
|
||||
private:
|
||||
std::string _name;
|
||||
|
||||
pss boundingSphere_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __RENDERABLE_H__
|
||||
#endif // __RENDERABLE_H__
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace openspace {
|
||||
|
||||
class ConstantPositionInformation: public PositionInformation {
|
||||
public:
|
||||
ConstantPositionInformation(const ghoul::Dictionary& dictionary);
|
||||
ConstantPositionInformation(const ghoul::Dictionary& dictionary
|
||||
= ghoul::Dictionary());
|
||||
virtual ~ConstantPositionInformation();
|
||||
virtual bool initialize();
|
||||
virtual const psc& position() const;
|
||||
|
||||
@@ -25,36 +25,36 @@
|
||||
#ifndef SCENEGRAPH_H
|
||||
#define SCENEGRAPH_H
|
||||
|
||||
// open space includes
|
||||
#include <openspace/scenegraph/scenegraphnode.h>
|
||||
|
||||
// std includes
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <openspace/util/camera.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class SceneGraphNode;
|
||||
|
||||
class SceneGraph {
|
||||
public:
|
||||
|
||||
// constructors & destructor
|
||||
SceneGraph();
|
||||
~SceneGraph();
|
||||
// constructors & destructor
|
||||
SceneGraph();
|
||||
~SceneGraph();
|
||||
|
||||
/**
|
||||
* Initalizes the SceneGraph by loading modules from the ${SCENEPATH} directory
|
||||
*/
|
||||
bool initialize();
|
||||
|
||||
bool initialize();
|
||||
|
||||
/*
|
||||
* Clean up everything
|
||||
*/
|
||||
bool deinitialize();
|
||||
|
||||
|
||||
/*
|
||||
* Load the scenegraph from the provided folder
|
||||
*/
|
||||
@@ -66,17 +66,17 @@ public:
|
||||
/*
|
||||
* Updates all SceneGraphNodes relative positions
|
||||
*/
|
||||
void update();
|
||||
|
||||
void update();
|
||||
|
||||
/*
|
||||
* Evaluates if the SceneGraphNodes are visible to the provided camera
|
||||
*/
|
||||
void evaluate(Camera *camera);
|
||||
|
||||
void evaluate(Camera* camera);
|
||||
|
||||
/*
|
||||
* Render visible SceneGraphNodes using the provided camera
|
||||
*/
|
||||
void render(Camera *camera);
|
||||
void render(Camera* camera);
|
||||
|
||||
/*
|
||||
* Prints the SceneGraph tree. For debugging purposes
|
||||
@@ -90,12 +90,11 @@ public:
|
||||
|
||||
private:
|
||||
std::string _focus, _position;
|
||||
|
||||
// actual scenegraph
|
||||
SceneGraphNode *_root;
|
||||
std::vector<SceneGraphNode*> _nodes;
|
||||
std::map<std::string, SceneGraphNode*> _allNodes;
|
||||
|
||||
// actual scenegraph
|
||||
SceneGraphNode* _root;
|
||||
std::vector<SceneGraphNode*> _nodes;
|
||||
std::map<std::string, SceneGraphNode*> _allNodes;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -29,12 +29,14 @@
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scenegraph/positioninformation.h>
|
||||
|
||||
#include <openspace/scenegraph/scenegraph.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
// std includes
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -42,8 +44,10 @@ class SceneGraphNode {
|
||||
public:
|
||||
|
||||
// constructors & destructor
|
||||
SceneGraphNode(const ghoul::Dictionary& dictionary);
|
||||
SceneGraphNode();
|
||||
~SceneGraphNode();
|
||||
|
||||
static SceneGraphNode* createFromDictionary(const ghoul::Dictionary& dictionary);
|
||||
|
||||
bool initialize();
|
||||
bool deinitialize();
|
||||
@@ -77,7 +81,6 @@ public:
|
||||
const Renderable * getRenderable() const;
|
||||
|
||||
private:
|
||||
|
||||
// essential
|
||||
std::vector<SceneGraphNode*> _children;
|
||||
SceneGraphNode* _parent;
|
||||
@@ -98,6 +101,4 @@ private:
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#include <openspace/scenegraph/scenegraphnode.inl>
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef SCENEGRAPHNODE_INL
|
||||
#define SCENEGRAPHNODE_INL
|
||||
|
||||
#endif
|
||||
@@ -252,6 +252,7 @@ bool OpenSpaceEngine::initialize()
|
||||
|
||||
// Load scenegraph
|
||||
std::shared_ptr<SceneGraph> sceneGraph(new SceneGraph);
|
||||
_renderEngine->setSceneGraph(sceneGraph);
|
||||
if (!OsEng.configurationManager().hasValue<std::string>(
|
||||
configuration::sceneConfigurationKey)) {
|
||||
LFATAL("Configuration needs to point to the scene file");
|
||||
|
||||
134
src/main.cpp
134
src/main.cpp
@@ -47,121 +47,131 @@ void mainEncodeFun();
|
||||
void mainDecodeFun();
|
||||
void mainExternalControlCallback(const char * receivedChars, int size, int clientId);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// create the OpenSpace engine and get arguments for the sgct engine
|
||||
std::vector<std::string> sgctArguments;
|
||||
openspace::OpenSpaceEngine::create(argc, argv, sgctArguments);
|
||||
|
||||
// create sgct engine c arguments
|
||||
int newArgc = sgctArguments.size();
|
||||
char** newArgv = new char*[newArgc];
|
||||
char** newArgv = new char* [newArgc];
|
||||
for (int i = 0; i < newArgc; ++i) {
|
||||
//newArgv[i] = new char[sgctArguments.at(i).length()];
|
||||
//std::strcpy(newArgv[i], sgctArguments.at(i).c_str());
|
||||
// newArgv[i] = new char[sgctArguments.at(i).length()];
|
||||
// std::strcpy(newArgv[i], sgctArguments.at(i).c_str());
|
||||
newArgv[i] = const_cast<char*>(sgctArguments.at(i).c_str());
|
||||
}
|
||||
|
||||
_sgctEngine = new sgct::Engine(newArgc, newArgv);
|
||||
|
||||
|
||||
_sgctEngine = new sgct::Engine(newArgc, newArgv);
|
||||
|
||||
// deallocate sgct c arguments
|
||||
for (int i = 0; i < newArgc; ++i) {
|
||||
//delete newArgv[i];
|
||||
// delete newArgv[i];
|
||||
}
|
||||
delete[] newArgv;
|
||||
|
||||
|
||||
// Bind functions
|
||||
_sgctEngine->setInitOGLFunction( mainInitFunc );
|
||||
_sgctEngine->setPreSyncFunction( mainPreSyncFunc );
|
||||
_sgctEngine->setPostSyncPreDrawFunction( mainPostSyncPreDrawFunc );
|
||||
_sgctEngine->setDrawFunction( mainRenderFunc );
|
||||
_sgctEngine->setPostDrawFunction( mainPostDrawFunc );
|
||||
_sgctEngine->setKeyboardCallbackFunction( mainKeyboardCallback );
|
||||
_sgctEngine->setMouseButtonCallbackFunction( mainMouseButtonCallback );
|
||||
_sgctEngine->setMousePosCallbackFunction( mainMousePosCallback );
|
||||
_sgctEngine->setMouseScrollCallbackFunction( mainMouseScrollCallback );
|
||||
_sgctEngine->setExternalControlCallback( mainExternalControlCallback );
|
||||
_sgctEngine->setInitOGLFunction(mainInitFunc);
|
||||
_sgctEngine->setPreSyncFunction(mainPreSyncFunc);
|
||||
_sgctEngine->setPostSyncPreDrawFunction(mainPostSyncPreDrawFunc);
|
||||
_sgctEngine->setDrawFunction(mainRenderFunc);
|
||||
_sgctEngine->setPostDrawFunction(mainPostDrawFunc);
|
||||
_sgctEngine->setKeyboardCallbackFunction(mainKeyboardCallback);
|
||||
_sgctEngine->setMouseButtonCallbackFunction(mainMouseButtonCallback);
|
||||
_sgctEngine->setMousePosCallbackFunction(mainMousePosCallback);
|
||||
_sgctEngine->setMouseScrollCallbackFunction(mainMouseScrollCallback);
|
||||
_sgctEngine->setExternalControlCallback(mainExternalControlCallback);
|
||||
|
||||
// set encode and decode functions
|
||||
// NOTE: starts synchronizing before init functions
|
||||
sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun);
|
||||
sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun);
|
||||
// set encode and decode functions
|
||||
// NOTE: starts synchronizing before init functions
|
||||
sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun);
|
||||
sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun);
|
||||
|
||||
// init the interface which will handle callbacks from an external gui
|
||||
_interface = new openspace::Interface(&OsEng);
|
||||
// init the interface which will handle callbacks from an external gui
|
||||
_interface = new openspace::Interface(&OsEng);
|
||||
|
||||
// try to open a window
|
||||
if( ! _sgctEngine->init(sgct::Engine::OpenGL_4_0_Core_Profile)) {
|
||||
// could not open a window, deallocates and exits
|
||||
delete _sgctEngine;
|
||||
// try to open a window
|
||||
if (!_sgctEngine->init(sgct::Engine::OpenGL_4_0_Core_Profile)) {
|
||||
// could not open a window, deallocates and exits
|
||||
delete _sgctEngine;
|
||||
openspace::OpenSpaceEngine::destroy();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Main loop
|
||||
_sgctEngine->render();
|
||||
|
||||
// Clean up (de-allocate)
|
||||
delete _sgctEngine;
|
||||
|
||||
// Exit program
|
||||
exit( EXIT_SUCCESS );
|
||||
// Main loop
|
||||
_sgctEngine->render();
|
||||
|
||||
// Clean up (de-allocate)
|
||||
delete _sgctEngine;
|
||||
|
||||
// Exit program
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void mainExternalControlCallback(const char * receivedChars, int size, int clientId) {
|
||||
if (_sgctEngine->isMaster())
|
||||
_interface->callback(receivedChars);
|
||||
void mainExternalControlCallback(const char* receivedChars, int size, int clientId)
|
||||
{
|
||||
if (_sgctEngine->isMaster())
|
||||
_interface->callback(receivedChars);
|
||||
}
|
||||
|
||||
void mainInitFunc(void) {
|
||||
void mainInitFunc(void)
|
||||
{
|
||||
OsEng.initialize();
|
||||
OsEng.initializeGL();
|
||||
}
|
||||
|
||||
void mainPreSyncFunc(void) {
|
||||
void mainPreSyncFunc(void)
|
||||
{
|
||||
OsEng.preSynchronization();
|
||||
}
|
||||
|
||||
void mainPostSyncPreDrawFunc(void) {
|
||||
void mainPostSyncPreDrawFunc(void)
|
||||
{
|
||||
OsEng.postSynchronizationPreDraw();
|
||||
}
|
||||
|
||||
void mainRenderFunc(void) {
|
||||
void mainRenderFunc(void)
|
||||
{
|
||||
OsEng.render();
|
||||
}
|
||||
|
||||
void mainPostDrawFunc(void) {
|
||||
void mainPostDrawFunc(void)
|
||||
{
|
||||
OsEng.postDraw();
|
||||
}
|
||||
|
||||
void mainKeyboardCallback(int key, int action) {
|
||||
if (_sgctEngine->isMaster())
|
||||
void mainKeyboardCallback(int key, int action)
|
||||
{
|
||||
if (_sgctEngine->isMaster())
|
||||
OsEng.keyboardCallback(key, action);
|
||||
}
|
||||
|
||||
void mainMouseButtonCallback(int key, int action) {
|
||||
if (_sgctEngine->isMaster())
|
||||
void mainMouseButtonCallback(int key, int action)
|
||||
{
|
||||
if (_sgctEngine->isMaster())
|
||||
OsEng.mouseButtonCallback(key, action);
|
||||
}
|
||||
|
||||
void mainMousePosCallback(double x, double y) {
|
||||
void mainMousePosCallback(double x, double y)
|
||||
{
|
||||
// TODO use float instead
|
||||
if (_sgctEngine->isMaster())
|
||||
if (_sgctEngine->isMaster())
|
||||
OsEng.mousePositionCallback(static_cast<int>(x), static_cast<int>(y));
|
||||
}
|
||||
|
||||
void mainMouseScrollCallback(double pos, double /*pos2*/) {
|
||||
void mainMouseScrollCallback(double pos, double /*pos2*/)
|
||||
{
|
||||
// TODO use float instead
|
||||
if (_sgctEngine->isMaster())
|
||||
if (_sgctEngine->isMaster())
|
||||
OsEng.mouseScrollWheelCallback(static_cast<int>(pos));
|
||||
}
|
||||
|
||||
void mainEncodeFun() {
|
||||
OsEng.encode();
|
||||
void mainEncodeFun()
|
||||
{
|
||||
OsEng.encode();
|
||||
}
|
||||
|
||||
void mainDecodeFun() {
|
||||
OsEng.decode();
|
||||
void mainDecodeFun()
|
||||
{
|
||||
OsEng.decode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -49,11 +49,13 @@ namespace {
|
||||
const std::string _loggerCat = "SceneGraph";
|
||||
const std::string _rootNodeName = "Root";
|
||||
const std::string _moduleExtension = ".mod";
|
||||
|
||||
namespace configuration {
|
||||
const std::string modulesKey = "Modules";
|
||||
const std::string cameraKey = "Camera";
|
||||
const std::string nameKey = "Name";
|
||||
const std::string parentKey = "Parent";
|
||||
const std::string focusKey = "Focus";
|
||||
const std::string positionKey = "Position";
|
||||
const std::string modulePathKey = "ModulePath";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,10 +240,10 @@ bool SceneGraph::loadScene(const std::string& sceneDescriptionFilePath,
|
||||
|
||||
|
||||
// initialize the root node
|
||||
_root = new SceneGraphNode(Dictionary());
|
||||
_root = new SceneGraphNode();
|
||||
_root->setName(_rootNodeName);
|
||||
_nodes.push_back(_root);
|
||||
_allNodes.insert(std::make_pair("Root", _root));
|
||||
_allNodes.emplace(_rootNodeName, _root);
|
||||
|
||||
Dictionary dictionary;
|
||||
loadDictionaryFromFile(sceneDescriptionFilePath, dictionary);
|
||||
@@ -263,8 +265,8 @@ bool SceneGraph::loadScene(const std::string& sceneDescriptionFilePath,
|
||||
std::string focus;
|
||||
std::string position;
|
||||
|
||||
if (cameraDictionary.hasKey("Focus")
|
||||
&& cameraDictionary.getValue("Focus", focus)) {
|
||||
if (cameraDictionary.hasKey(configuration::focusKey)
|
||||
&& cameraDictionary.getValue(configuration::focusKey, focus)) {
|
||||
auto focusIterator = _allNodes.find(focus);
|
||||
if (focusIterator != _allNodes.end()) {
|
||||
_focus = focus;
|
||||
@@ -273,8 +275,8 @@ bool SceneGraph::loadScene(const std::string& sceneDescriptionFilePath,
|
||||
else
|
||||
LERROR("Could not find focus object '" << focus << "'");
|
||||
}
|
||||
if (cameraDictionary.hasKey("Position")
|
||||
&& cameraDictionary.getValue("Position", position)) {
|
||||
if (cameraDictionary.hasKey(configuration::positionKey)
|
||||
&& cameraDictionary.getValue(configuration::positionKey, position)) {
|
||||
auto positionIterator = _allNodes.find(position);
|
||||
if (positionIterator != _allNodes.end()) {
|
||||
_position = position;
|
||||
@@ -303,39 +305,54 @@ void SceneGraph::loadModule(const std::string& modulePath)
|
||||
ghoul::lua::loadDictionaryFromFile(fullModule, moduleDictionary);
|
||||
std::vector<std::string> keys = moduleDictionary.keys();
|
||||
for (const std::string& key : keys) {
|
||||
ghoul::Dictionary singleModuleDictionary;
|
||||
if (moduleDictionary.getValue(key, singleModuleDictionary)) {
|
||||
std::string moduleName;
|
||||
if (singleModuleDictionary.getValue(configuration::nameKey, moduleName)) {
|
||||
std::string parentName;
|
||||
if (!singleModuleDictionary.getValue(configuration::parentKey, parentName)) {
|
||||
LWARNING("Could not find 'Parent' key, using 'Root'.");
|
||||
parentName = "Root";
|
||||
}
|
||||
|
||||
auto parentIterator = _allNodes.find(parentName);
|
||||
if (parentIterator == _allNodes.end()) {
|
||||
LFATAL("Could not find parent named '"
|
||||
<< parentName << "' for '" << moduleName << "'."
|
||||
<< " Check module definition order. Skipping module.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate SceneGraphNode and initialize with Dictionary
|
||||
singleModuleDictionary.setValue("Path", modulePath);
|
||||
SceneGraphNode* node = nullptr;
|
||||
node = new SceneGraphNode(singleModuleDictionary);
|
||||
if (node != nullptr) {
|
||||
// add to internal data structures
|
||||
_allNodes.insert(std::make_pair(moduleName, node));
|
||||
_nodes.push_back(node);
|
||||
|
||||
// set child and parent
|
||||
SceneGraphNode* parentNode = parentIterator->second;
|
||||
parentNode->addNode(node);
|
||||
}
|
||||
}
|
||||
if (!moduleDictionary.hasValue<ghoul::Dictionary>(key)) {
|
||||
LERROR("SceneGraphElement '" << key << "' is not a table in module '"
|
||||
<< fullModule << "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
ghoul::Dictionary element;
|
||||
moduleDictionary.getValue(key, element);
|
||||
|
||||
element.setValue(configuration::modulePathKey, modulePath);
|
||||
|
||||
SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
|
||||
|
||||
_allNodes.emplace(node->nodeName(), node);
|
||||
_nodes.push_back(node);
|
||||
|
||||
|
||||
// std::string moduleName;
|
||||
// if (element.getValue(configuration::nameKey, moduleName)) {
|
||||
// std::string parentName;
|
||||
// if (!element.getValue(configuration::parentKey, parentName)) {
|
||||
// LWARNING("Could not find 'Parent' key, using 'Root'.");
|
||||
// parentName = "Root";
|
||||
// }
|
||||
|
||||
// auto parentIterator = _allNodes.find(parentName);
|
||||
// if (parentIterator == _allNodes.end()) {
|
||||
// LFATAL("Could not find parent named '"
|
||||
// << parentName << "' for '" << moduleName << "'."
|
||||
// << " Check module definition order. Skipping module.");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // allocate SceneGraphNode and initialize with Dictionary
|
||||
// element.setValue("Path", modulePath);
|
||||
// SceneGraphNode* node = nullptr;
|
||||
// node = new SceneGraphNode(element);
|
||||
// if (node != nullptr) {
|
||||
// // add to internal data structures
|
||||
// _allNodes.insert(std::make_pair(moduleName, node));
|
||||
// _nodes.push_back(node);
|
||||
|
||||
// // set child and parent
|
||||
// SceneGraphNode* parentNode = parentIterator->second;
|
||||
// parentNode->addNode(node);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
// Print the tree
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
// open space includes
|
||||
#include <openspace/scenegraph/scenegraphnode.h>
|
||||
#include <openspace/util/spice.h>
|
||||
#include <openspace/query/query.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
@@ -39,27 +40,34 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SceneGraphNode";
|
||||
const std::string _loggerCat = "SceneGraphNode";
|
||||
|
||||
const std::string _unnamedSceneGraphNodeName = "Unnamed";
|
||||
namespace configuration {
|
||||
const std::string nameKey = "Name";
|
||||
const std::string parentKey = "Parent";
|
||||
const std::string modulePathKey = "ModulePath";
|
||||
const std::string renderableKey = "Renderable";
|
||||
const std::string positionKey = "Position";
|
||||
}
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
template <class T>
|
||||
bool safeCreationWithDictionary(T** object, const std::string& key,
|
||||
ghoul::Dictionary* dictionary,
|
||||
const std::string& path = "") {
|
||||
if (dictionary->hasKey(key)) {
|
||||
const ghoul::Dictionary& dictionary,
|
||||
const std::string& path = "")
|
||||
{
|
||||
if (dictionary.hasKey(key)) {
|
||||
ghoul::Dictionary tmpDictionary;
|
||||
if (dictionary->getValue(key, tmpDictionary)) {
|
||||
if (dictionary.getValue(key, tmpDictionary)) {
|
||||
if (!tmpDictionary.hasKey("Path") && path != "") {
|
||||
tmpDictionary.setValue("Path", path);
|
||||
}
|
||||
std::string renderableType;
|
||||
if (tmpDictionary.getValue("Type", renderableType)) {
|
||||
ghoul::TemplateFactory<T>* factory
|
||||
= FactoryManager::ref().factoryByType<T>();
|
||||
= FactoryManager::ref().factoryByType<T>();
|
||||
T* tmp = factory->create(renderableType, tmpDictionary);
|
||||
if (tmp != nullptr) {
|
||||
*object = tmp;
|
||||
@@ -71,45 +79,68 @@ bool safeCreationWithDictionary(T** object, const std::string& key,
|
||||
return false;
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
SceneGraphNode* result = new SceneGraphNode;
|
||||
|
||||
SceneGraphNode::SceneGraphNode(const ghoul::Dictionary& dictionary)
|
||||
std::string path;
|
||||
dictionary.getValue(configuration::modulePathKey, path);
|
||||
|
||||
if (!dictionary.hasValue<std::string>(configuration::nameKey)) {
|
||||
LERROR("SceneGraphNode in '" << path << "' did not contain a '"
|
||||
<< configuration::nameKey << "' key");
|
||||
return nullptr;
|
||||
}
|
||||
dictionary.getValue(configuration::nameKey, result->_nodeName);
|
||||
|
||||
|
||||
if (dictionary.hasKey(configuration::renderableKey)) {
|
||||
if (safeCreationWithDictionary<Renderable>(
|
||||
&result->_renderable, configuration::renderableKey, dictionary, path)) {
|
||||
LDEBUG(result->_nodeName << ": Successful creation of renderable");
|
||||
result->_renderable->setName(result->_nodeName);
|
||||
}
|
||||
else {
|
||||
LDEBUG(result->_nodeName << ": Failed to create renderable");
|
||||
}
|
||||
}
|
||||
if (dictionary.hasKey(configuration::positionKey)) {
|
||||
if (safeCreationWithDictionary<PositionInformation>(
|
||||
&result->_position, configuration::positionKey, dictionary, path)) {
|
||||
LDEBUG(result->_nodeName << ": Successful creation of position");
|
||||
}
|
||||
else {
|
||||
LDEBUG(result->_nodeName << ": Failed to create position");
|
||||
}
|
||||
}
|
||||
|
||||
std::string parentName;
|
||||
if (!dictionary.getValue(configuration::parentKey, parentName)) {
|
||||
LWARNING("Could not find 'Parent' key, using 'Root'.");
|
||||
parentName = "Root";
|
||||
}
|
||||
|
||||
SceneGraphNode* parentNode = getSceneGraphNode(parentName);
|
||||
if (parentNode == nullptr) {
|
||||
LFATAL("Could not find parent named '"
|
||||
<< parentName << "' for '" << result->_nodeName << "'."
|
||||
<< " Check module definition order. Skipping module.");
|
||||
}
|
||||
|
||||
parentNode->addNode(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
SceneGraphNode::SceneGraphNode()
|
||||
: _parent(nullptr)
|
||||
, _nodeName(_unnamedSceneGraphNodeName)
|
||||
, _position(nullptr)
|
||||
, _nodeName("")
|
||||
, _position(new ConstantPositionInformation)
|
||||
, _renderable(nullptr)
|
||||
, _renderableVisible(false)
|
||||
, _boundingSphereVisible(false)
|
||||
{
|
||||
ghoul::Dictionary localDictionary = dictionary;
|
||||
|
||||
// set the _nodeName if available
|
||||
localDictionary.getValue("Name", _nodeName);
|
||||
|
||||
std::string path = "";
|
||||
localDictionary.getValue("Path", path);
|
||||
|
||||
if (localDictionary.hasKey("Renderable")) {
|
||||
if (safeCreationWithDictionary<Renderable>(&_renderable, "Renderable",
|
||||
&localDictionary, path)) {
|
||||
LDEBUG(_nodeName << ": Successful creation of renderable!");
|
||||
_renderable->setName(_nodeName);
|
||||
} else {
|
||||
LDEBUG(_nodeName << ": Failed to create renderable!");
|
||||
}
|
||||
}
|
||||
if (localDictionary.hasKey("Position")) {
|
||||
if (safeCreationWithDictionary<PositionInformation>(&_position, "Position",
|
||||
&localDictionary, path)) {
|
||||
LDEBUG(_nodeName << ": Successful creation of position!");
|
||||
} else {
|
||||
LDEBUG(_nodeName << ": Failed to create position!");
|
||||
}
|
||||
}
|
||||
|
||||
if (_position == nullptr) {
|
||||
_position = new ConstantPositionInformation(ghoul::Dictionary());
|
||||
_position->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
SceneGraphNode::~SceneGraphNode()
|
||||
@@ -128,24 +159,25 @@ bool SceneGraphNode::initialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceneGraphNode::deinitialize() {
|
||||
bool SceneGraphNode::deinitialize()
|
||||
{
|
||||
LDEBUG("Deinitialize: " << _nodeName);
|
||||
|
||||
// deallocate the renderable
|
||||
if(_renderable != nullptr)
|
||||
delete _renderable;
|
||||
|
||||
|
||||
// deallocate the renderable
|
||||
if (_renderable != nullptr)
|
||||
delete _renderable;
|
||||
|
||||
// deallocate position
|
||||
if(_position != nullptr)
|
||||
if (_position != nullptr)
|
||||
delete _position;
|
||||
|
||||
// deallocate the child nodes and delete them, iterate c++11 style
|
||||
for( auto child: _children)
|
||||
delete child;
|
||||
|
||||
|
||||
// deallocate the child nodes and delete them, iterate c++11 style
|
||||
for (auto child : _children)
|
||||
delete child;
|
||||
|
||||
// empty the children vector
|
||||
_children.erase(_children.begin(), _children.end());
|
||||
|
||||
|
||||
// reset variables
|
||||
_parent = nullptr;
|
||||
_renderable = nullptr;
|
||||
@@ -153,190 +185,199 @@ bool SceneGraphNode::deinitialize() {
|
||||
_nodeName = "Unnamed OpenSpace SceneGraphNode";
|
||||
_renderableVisible = false;
|
||||
_boundingSphereVisible = false;
|
||||
_boundingSphere = pss(0.0,0.0);
|
||||
|
||||
_boundingSphere = pss(0.0, 0.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// essential
|
||||
void SceneGraphNode::update() {
|
||||
void SceneGraphNode::update()
|
||||
{
|
||||
_position->update();
|
||||
}
|
||||
|
||||
void SceneGraphNode::evaluate(const Camera *camera, const psc& parentPosition) {
|
||||
void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition)
|
||||
{
|
||||
const psc thisPosition = parentPosition + _position->position();
|
||||
const psc camPos = camera->getPosition();
|
||||
const psc toCamera = thisPosition - camPos;
|
||||
|
||||
const psc thisPosition = parentPosition + _position->position();
|
||||
const psc camPos = camera->getPosition();
|
||||
const psc toCamera = thisPosition - camPos;
|
||||
|
||||
// init as not visible
|
||||
_boundingSphereVisible = false;
|
||||
_renderableVisible = false;
|
||||
|
||||
// check if camera is outside the node boundingsphere
|
||||
if(toCamera.length() > _boundingSphere) {
|
||||
|
||||
// check if the boudningsphere is visible before avaluating children
|
||||
if( ! sphereInsideFrustum(thisPosition, _boundingSphere, camera)) {
|
||||
// the node is completely outside of the camera view, stop evaluating this node
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// inside boudningsphere or parts of the sphere is visible, individual
|
||||
// init as not visible
|
||||
_boundingSphereVisible = false;
|
||||
_renderableVisible = false;
|
||||
|
||||
// check if camera is outside the node boundingsphere
|
||||
if (toCamera.length() > _boundingSphere) {
|
||||
// check if the boudningsphere is visible before avaluating children
|
||||
if (!sphereInsideFrustum(thisPosition, _boundingSphere, camera)) {
|
||||
// the node is completely outside of the camera view, stop evaluating this
|
||||
// node
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// inside boudningsphere or parts of the sphere is visible, individual
|
||||
// children needs to be evaluated
|
||||
_boundingSphereVisible = true;
|
||||
|
||||
// this node has an renderable
|
||||
if(_renderable) {
|
||||
_boundingSphereVisible = true;
|
||||
|
||||
// check if the renderable boundingsphere is visible
|
||||
_renderableVisible = sphereInsideFrustum(thisPosition, _renderable->getBoundingSphere(), camera);
|
||||
}
|
||||
// this node has an renderable
|
||||
if (_renderable) {
|
||||
// check if the renderable boundingsphere is visible
|
||||
_renderableVisible = sphereInsideFrustum(
|
||||
thisPosition, _renderable->getBoundingSphere(), camera);
|
||||
}
|
||||
|
||||
// evaluate all the children, tail-recursive function(?)
|
||||
for(auto &child: _children) {
|
||||
child->evaluate(camera,psc());
|
||||
}
|
||||
|
||||
// evaluate all the children, tail-recursive function(?)
|
||||
for (auto& child : _children) {
|
||||
child->evaluate(camera, psc());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::render(const Camera *camera, const psc & parentPosition) {
|
||||
void SceneGraphNode::render(const Camera* camera, const psc& parentPosition)
|
||||
{
|
||||
const psc thisPosition = parentPosition + _position->position();
|
||||
|
||||
const psc thisPosition = parentPosition + _position->position();
|
||||
|
||||
// check if camera is outside the node boundingsphere
|
||||
if( ! _boundingSphereVisible) {
|
||||
return;
|
||||
}
|
||||
if(_renderableVisible) {
|
||||
//LDEBUG("Render");
|
||||
_renderable->render(camera,thisPosition);
|
||||
}
|
||||
// check if camera is outside the node boundingsphere
|
||||
if (!_boundingSphereVisible) {
|
||||
return;
|
||||
}
|
||||
if (_renderableVisible) {
|
||||
// LDEBUG("Render");
|
||||
_renderable->render(camera, thisPosition);
|
||||
}
|
||||
|
||||
// evaluate all the children, tail-recursive function(?)
|
||||
|
||||
for(auto &child: _children) {
|
||||
child->render(camera,thisPosition);
|
||||
}
|
||||
// evaluate all the children, tail-recursive function(?)
|
||||
|
||||
for (auto& child : _children) {
|
||||
child->render(camera, thisPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// set & get
|
||||
void SceneGraphNode::addNode(SceneGraphNode *child) {
|
||||
// add a child node and set this node to be the parent
|
||||
void SceneGraphNode::addNode(SceneGraphNode* child)
|
||||
{
|
||||
// add a child node and set this node to be the parent
|
||||
|
||||
child->setParent(this);
|
||||
_children.push_back(child);
|
||||
}
|
||||
|
||||
void SceneGraphNode::setName(const std::string &name) {
|
||||
_nodeName = name;
|
||||
void SceneGraphNode::setName(const std::string& name)
|
||||
{
|
||||
_nodeName = name;
|
||||
}
|
||||
|
||||
void SceneGraphNode::setParent(SceneGraphNode *parent) {
|
||||
_parent = parent;
|
||||
void SceneGraphNode::setParent(SceneGraphNode* parent)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
const psc &SceneGraphNode::getPosition() const {
|
||||
return _position->position();
|
||||
const psc& SceneGraphNode::getPosition() const
|
||||
{
|
||||
return _position->position();
|
||||
}
|
||||
|
||||
psc SceneGraphNode::getWorldPosition() const {
|
||||
|
||||
// recursive up the hierarchy if there are parents available
|
||||
if(_parent) {
|
||||
return _position->position() + _parent->getWorldPosition();
|
||||
} else {
|
||||
return _position->position();
|
||||
}
|
||||
psc SceneGraphNode::getWorldPosition() const
|
||||
{
|
||||
// recursive up the hierarchy if there are parents available
|
||||
if (_parent) {
|
||||
return _position->position() + _parent->getWorldPosition();
|
||||
} else {
|
||||
return _position->position();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string SceneGraphNode::nodeName() const {
|
||||
std::string SceneGraphNode::nodeName() const
|
||||
{
|
||||
return _nodeName;
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraphNode::parent() const {
|
||||
SceneGraphNode* SceneGraphNode::parent() const
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
const std::vector<SceneGraphNode*>& SceneGraphNode::children() const {
|
||||
const std::vector<SceneGraphNode*>& SceneGraphNode::children() const
|
||||
{
|
||||
return _children;
|
||||
}
|
||||
|
||||
// bounding sphere
|
||||
pss SceneGraphNode::calculateBoundingSphere() {
|
||||
|
||||
// set the vounding sphere to 0.0
|
||||
_boundingSphere = 0.0;
|
||||
pss SceneGraphNode::calculateBoundingSphere()
|
||||
{
|
||||
// set the vounding sphere to 0.0
|
||||
_boundingSphere = 0.0;
|
||||
|
||||
if(_children.size() > 0) { // node
|
||||
pss maxChild;
|
||||
if (_children.size() > 0) { // node
|
||||
pss maxChild;
|
||||
|
||||
// loop though all children and find the one furthest away/with the largest bounding sphere
|
||||
for(size_t i = 0; i < _children.size(); ++i) {
|
||||
// loop though all children and find the one furthest away/with the largest
|
||||
// bounding sphere
|
||||
for (size_t i = 0; i < _children.size(); ++i) {
|
||||
// when positions is dynamix, change this part to fins the most distant
|
||||
// position
|
||||
pss child = _children.at(i)->getPosition().length()
|
||||
+ _children.at(i)->calculateBoundingSphere();
|
||||
if (child > maxChild) {
|
||||
maxChild = child;
|
||||
}
|
||||
}
|
||||
_boundingSphere += maxChild;
|
||||
} else { // leaf
|
||||
|
||||
// when positions is dynamix, change this part to fins the most distant position
|
||||
pss child = _children.at(i)->getPosition().length() +
|
||||
_children.at(i)->calculateBoundingSphere();
|
||||
if(child > maxChild) {
|
||||
maxChild = child;
|
||||
}
|
||||
}
|
||||
_boundingSphere += maxChild;
|
||||
} else { // leaf
|
||||
// if has a renderable, use that boundingsphere
|
||||
if (_renderable)
|
||||
_boundingSphere += _renderable->getBoundingSphere();
|
||||
}
|
||||
|
||||
// if has a renderable, use that boundingsphere
|
||||
if(_renderable)
|
||||
_boundingSphere += _renderable->getBoundingSphere();
|
||||
}
|
||||
|
||||
return _boundingSphere;
|
||||
return _boundingSphere;
|
||||
}
|
||||
|
||||
// renderable
|
||||
void SceneGraphNode::setRenderable(Renderable *renderable) {
|
||||
_renderable = renderable;
|
||||
update();
|
||||
void SceneGraphNode::setRenderable(Renderable* renderable)
|
||||
{
|
||||
_renderable = renderable;
|
||||
update();
|
||||
}
|
||||
|
||||
const Renderable * SceneGraphNode::getRenderable() const{
|
||||
return _renderable;
|
||||
const Renderable* SceneGraphNode::getRenderable() const
|
||||
{
|
||||
return _renderable;
|
||||
}
|
||||
|
||||
// private helper methods
|
||||
bool SceneGraphNode::sphereInsideFrustum(const psc s_pos, const pss & s_rad, const Camera *camera) {
|
||||
bool SceneGraphNode::sphereInsideFrustum(const psc s_pos, const pss& s_rad,
|
||||
const Camera* camera)
|
||||
{
|
||||
// direction the camera is looking at in power scale
|
||||
psc psc_camdir = psc(camera->getViewDirection());
|
||||
|
||||
// direction the camera is looking at in power scale
|
||||
psc psc_camdir = psc(camera->getViewDirection());
|
||||
// the position of the camera, moved backwards in the view direction to encapsulate
|
||||
// the sphere radius
|
||||
psc U = camera->getPosition() - psc_camdir * s_rad * (1.0 / camera->getSinMaxFov());
|
||||
|
||||
// the position of the camera, moved backwards in the view direction to encapsulate the sphere radius
|
||||
psc U = camera->getPosition() - psc_camdir * s_rad * ( 1.0 / camera->getSinMaxFov());
|
||||
// the vector to the object from the new position
|
||||
psc D = s_pos - U;
|
||||
|
||||
// the vector to the object from the new position
|
||||
psc D = s_pos - U;
|
||||
|
||||
const double a = psc_camdir.angle(D);
|
||||
if ( a < camera->getMaxFov())
|
||||
{
|
||||
// center is inside K''
|
||||
D = s_pos - camera->getPosition();
|
||||
if ( D.length()* psc_camdir.length() *camera->getSinMaxFov() <= -psc_camdir.dot(D)) {
|
||||
// center is inside K'' and inside K'
|
||||
return D.length() <= s_rad;
|
||||
} else {
|
||||
// center is inside K'' and outside K'
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// outside the maximum angle
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a < camera->getMaxFov()) {
|
||||
// center is inside K''
|
||||
D = s_pos - camera->getPosition();
|
||||
if (D.length() * psc_camdir.length() * camera->getSinMaxFov()
|
||||
<= -psc_camdir.dot(D)) {
|
||||
// center is inside K'' and inside K'
|
||||
return D.length() <= s_rad;
|
||||
} else {
|
||||
// center is inside K'' and outside K'
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// outside the maximum angle
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraphNode::get(const std::string& name) {
|
||||
SceneGraphNode* SceneGraphNode::get(const std::string& name)
|
||||
{
|
||||
if (_nodeName == name)
|
||||
return this;
|
||||
else
|
||||
@@ -349,11 +390,12 @@ SceneGraphNode* SceneGraphNode::get(const std::string& name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SceneGraphNode::print() const {
|
||||
void SceneGraphNode::print() const
|
||||
{
|
||||
std::cout << _nodeName << std::endl;
|
||||
for (auto it : _children) {
|
||||
it->print();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
} // namespace openspace
|
||||
Reference in New Issue
Block a user